Best security questions in March 2012

Decrypt obfuscated perl script

12 votes

Had some spam issues on my server and, after finding out and removing some Perl and PHP scripts I'm down to checking what they really do, although I'm a senior PHP programmer I have little experience with Perl, can anyone give me a hand with the script here:

http://pastebin.com/MKiN8ifp

(It was one long line of code, script was called list.pl)


The start of the script is:

$??s:;s:s;;$?::s;(.*); ]="&\%[=.*.,-))'-,-#-*.).<.'.+-<-~-#,~-.-,.+,~-{-,.<'`.{'`'<-<--):)++,+#,-.{).+,,~+{+,,<)..})<.{.)-,.+.,.)-#):)++,+#,-.{).+,,~+{+,,<)..})<*{.}'`'<-<--):)++,+#,-.{).+:,+,+,',~+*+~+~+{+<+,)..})<'`'<.{'`'<'<-}.<)'+'.:*}.*.'-|-<.+):)~*{)~)|)++,+#,-.{).+:,+,+,',~+*+~+~+{+<+,)..})

It continues with precious few non-punctuation characters until the very end:

0-9\;\\_rs}&a-h;;s;(.*);$_;see;

Replace the s;(.*);$_;see; with print to get this. Replace s;(.*);$_;see; again with print in the first half of the payload to get this, which is the decryption code. The second half of the payload is the code to decrypt, but I can't go any further with it, because as you see, the decryption code is looking for a key in an envvar or a cookie (so that only the script's creator can control it or decode it, presumably), and I don't have that key. This is actually reasonably cleverly done.

Is using a for-loop on submitted POST data in PHP safe?

11 votes

I'm always a worry-wart about security in my PHP applications, and I just (potentially) thought of a way a hacker could kill my script. Currently my application takes form data and submits it as an array to a PHP script via AJAX, then loops through this array.

foreach($_POST['form_data'] as $field => $value){
   //Do something here.
}

However, what if a hacker were to forge an AJAX request, and repeatedly submit the 'form_data' array with 100000000000 random elements? The loop would have to iterate through each element, possibly causing a DoS (or at least slow down service), correct?

I'm not entirely educated here, so I may have some incorrect assumptions. Thanks for any input!

This will not be an issue: PHP limits the maximum number of POST vars using the max_input_vars directive, which defaults to 1000 variables.

This limit is actually enforced to prevent a much more serious type of DOS attack than the one you are thinking about (really, iterating a few thousand array elements is like nothing), namely hash table collision based attacks (often referred to as HashDOS). For more info on that issue see my article Supercolliding a PHP array.

Is jQuery .text() method XSS safe?

9 votes

I have unescaped data from users.

So is it safe to use like this:

var data = '<test>a&f"#</test>'; // example data from ajax response
if (typeof(data) === 'string')
    $('body').text(data);

Can I use like this or there is some problems like encoding or some specific symbols that I should be careful and add more strict validation?

When you set the text of an element using the text method, jQuery uses createTextNode internally, which escapes all special characters.

From the jQuery docs:

We need to be aware that this method escapes the string provided as necessary so that it will render correctly in HTML. To do so, it calls the DOM method .createTextNode(), which replaces special characters with their HTML entity equivalents (such as &lt; for <)

So yes, it should be safe. Here's your example in jsfiddle. Notice how the tags appear as literal text.

Securely send a Plain Text password?

5 votes

I'm working on an application for iOS which will have the user fill out their password. The password will then be posted to a PHP page on my site using either POST or GET. (It must be plaintext because it is used in a script.)

Besides HTTPS, is there any way to secure the password? Encrypt it in Obj-C and then decrypt it in PHP?

NOTE: The username is not sent... only the password is posted to the server.

EDIT: To clarify, David Stratton is correct... I'm trying to prevent malicious sniffers in public locations from simply reading clear text passwords as they are posted to the server.

Challenge response outline

Lets assume you have one-way hash function abc (in practice use md5 or sha1).

The password you store in your database is abc(password + salt) (store the salt separately)

The server generates a random challenge challenge and sends it to the client (with the salt) and calculates the expected response: abc(challenge + abc(password + salt))

The client then calculates: abc(user_password + salt) and applies the challenge to get abc(challenge + abc(user_password + salt)), that is sent to the server and the server can easily verify validity.

This is secure because:

  • The password is never sent in plaintext, or stored in plaintext
  • The hash value that is sent changes every time (mitigates replay attack)

There are some issues:

How do you know what salt to send? Well, I've never really found a solution for this, but using a deterministic algorithm to turn a username into a salt solves this problem. If the algorithm isn't deterministic an attacker could potentially figure out which username exists and which do not. This does require you to have a username though. Alternatively you could just have a static salt, but I don't know enough about cryptography to assess the quality of that implementation.

When is it safe to enable CORS?

4 votes

I am developing a JSON/REST web API, for which I specifically want third party websites to be able to call my service through AJAX. Hence, my service is sending the famous CORS header:

Access-Control-Allow-Origin: *

Which allows third party sites to call my service through AJAX. All fine so far.

However, a subsection of my web api is non-public and requires authentication (pretty standard stuff with OAuth and an access_token cookie). Is it safe to enable CORS on this part of my site as well?

On the one hand, it would be cool if third party websites could have ajax clients that also interact with this part of my service. However, the reason that there is a same origin policy in the first place, is that this might be risky. You don't want any website that you visit afterwards to be able to access your private content.

The scenario that I am afraid of is that a user logs in on my web api, either on the website or through a website that he trusts, and he forgets to logout. Will this allow every other website that he vists afterwards to access his private content using the existing session?

So my questions:

  • Is it ever safe to enable CORS on non-public content?
  • If a CORS enabled server sets a session_token through a cookie, will this cookie be saved under the domain of the CORS server or main web-page server?

In answer to your second question (If a CORS enabled server sets a session_token through a cookie...?), the cookie is saved under the domain of the CORS server. The main web page's JS code can't access the cookie, even via document.cookie. The cookie is only sent to the server when the .withCredentials property is set, and even then, it is only accepted when the server sets the Access-Control-Allow-Credentials header.

Your first question is a little more open ended. It is fairly secure, but there are ways to circumvent things. For example, an attacker could use a DNS poisoning technique to cause a preflight request to hit the actual server, but send the actual CORS request to the rogue server. Here are some more resources on CORS security:

http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Cross_Origin_Resource_Sharing

Lastly, your concern is around giving any website access to your CORS data. In order to protect against this, you should not use the Access-Control-Allow-Origin: * header. Instead, you should echo back the user's Origin value. For example:

Access-Control-Allow-Origin: http://www.example.com

This header will allow only http://www.example.com to access the response data.