views:

195

answers:

3

I have a 3rd party server which has a classic ASP page which takes in form data. From my web page I have a PHP script which sends fields to the ASP page using curl. Everything works fine except if a user includes an apostrophe character to the text. In the back end it is received as "\'". What is even odder is that it only does this from my hosted website. When I test locally it works fine.

Here is the PHP snippet which sends the data:

$datatopost = array (); 
foreach($_POST as $key => $data) {
    $datatopost[$key] = $data;
}

$ch = curl_init("http://my.server.com/validate.asp");
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $datatopost);
$result =  curl_exec($ch);
+4  A: 

You probably need to disable Magic Quotes in that particular server: http://php.net/manual/en/security.magicquotes.php

Furthermore, you could add this code to the top of your scripts (better yet, in a library you include in each page) so no matter the enviroment, you'll always get the magic quotes reversed:

<?php
if (get_magic_quotes_gpc()) {
    function stripslashes_deep($value)
    {
        $value = is_array($value) ?
                    array_map('stripslashes_deep', $value) :
                    stripslashes($value);

        return $value;
    }

    $_POST = array_map('stripslashes_deep', $_POST);
    $_GET = array_map('stripslashes_deep', $_GET);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
    $_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}
?>

Taken from http://php.net/manual/en/security.magicquotes.disabling.php

Seb
Thank you! This fixed it. I just needed to add that script to the top.
BlueVoid
-1 for processing unfiltered input. A malicious user can cause this code to recurse to an arbitrary depth.
Ben Dunlap
@Ben Dunlap: Curl does its own processing. Unless you're referring to stripslashes_deep, in which case I'm going to point out that addslashes has already been run on the input (or else get_magic_quotes_gpc() would return false).
R. Bemrose
Yeah, I was referring to stripslashes_deep() (hence the note about recursion). My point was that PHP developers should not write code that processes unfiltered input, and I pointed out a potential security problem with the code above, to illustrate. If PHP processes unfiltered input internally (which is the only thing that would be indicated by a TRUE return value from get_magic_quotes_gpc()) -- then that might be a problem as well, but it's not really a problem the web developer can control.
Ben Dunlap
@Ben could you be more specific, please? I don't see how a simple stripslashes could hurt when run on already processed input by PHP...
Seb
@Seb The problem I see is less with stripslashes than with stripslashes_deep() -- it's a recursive function whose call-depth is controlled by user input. If the user passes a query-string like this, for example: `?foo[][][][]=bar` ... then stripslashes_deep() would recurse to a depth of 5. And so on. IIRC there have been bugs in PHP where it crashes at a certain recursion depth. Even if I'm remembering wrong it doesn't seem prudent to let the user determine that much about your code path.
Ben Dunlap
@Ben Gotcha! Yeah, but in that case I wouldn't care much: if the user posts a huge array, his request would fail (not all the others). Given that he's an attacker, why do you care at all?
Seb
@Seb I guess it's just a mindset more than anything. Somehow it doesn't sit right with me to use code that I know to be exploitable, even if the exploit appears innocuous at first glance. In my experience, application security is pretty knotty, and real site compromises usually take advantage of multiple vulnerabilities simultaneously, any one of which may not seem like a big deal on its own.
Ben Dunlap
Ok, fair enough. Now, how would you do it in PHP < 5.2.0? Your solution (using filter_input()) only works for PHP >= 5.2.0.
Seb
I'd say that if a site is running a 3-year-old (or older) version of PHP, it's got bigger problems than user-controllable recursion depth. But, assuming some sort of business constraint, and assuming an installation that's stayed current on relevant security patches to PHP... I would check for magic_quotes and then, if magic_quotes were set, I'd call stripslashes() individually on query parameters that I expected to be present.
Ben Dunlap
Yeah, well... hostings sometimes don't upgrade to the latest version. Also, I bet you never found deadline problems... if you had, I'm sure you'd understand why your solution or applying stripslashes() individually on each page is highly impractical, compared to the cost/benefits of doing a stripslashes_deep() globally. In fact, you said many times it's a matter of multiple vulnerabilities - if you can find a way to crack a site (not just freeze your request) using this, I'll accept you're right. But unless you do, then worrying about imaginary hacks is completely unnecessary.
Seb
@Seb, when you say "imaginary" do you mean that the security impact is imaginary? Or do you mean that the possibility that someone would actually use this attack is imaginary? Or do you mean both? And what do you mean by "crack a site"? Do you consider DOS to be a crack? BTW I never said that this particular vulnerability would need to be exploited in combination with others, to be a problem. I just said that apparently-innocuous vulnerabilities should never be assumed to be innocuous just because a harmful exploit isn't immediately obvious.
Ben Dunlap
Here are a few links to considerations of this particular problem. They classify the vulnerability as "remote DOS": http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2006-1549 http://www.php-security.org/MOPB/MOPB-02-2007.html http://xforce.iss.net/xforce/xfdb/25704
Ben Dunlap
Those links just show that all versions of PHP are vulnerable, and this happens **before** any actual code parsing. You keep failing in showing how this could be exploitable once it reaches the code - I believe it cannot: if you disable all error printing, any attacker would just see a blank page after the attack. While you're right this is like a DOS attack, I don't see how the stripslashes_deep() could be a problem, and it seems you don't either - if you do, please show a way of getting some advantage of it. Getting tired of this useless discussion...
Seb
Take a look at the 'php-security.org' link again. I don't know what you mean by "before any actual code parsing"; the proof-of-concept there is precisely an attack on stripslashes_deep(); exactly the same concept as what I illustrated above. That page also points out that "a crash will kill all other threads of a multithreaded webserver". This is not "like" a DOS -- this /is/ a DOS, and it's one that's trivially triggered by an unsophisticated remote attacker, at the application layer.
Ben Dunlap
BTW, if you're still on the fence, here's what the phpMyAdmin team thought about the problem (spoiler: it involves a security update): http://www.phpmyadmin.net/home_page/security/PMASA-2007-3.php
Ben Dunlap
+4  A: 

Make sure you have magic quotes disabled. Seeing how your data comes from $_POST, that is the most likely culprit.

Jani Hartikainen
+1  A: 

Use PHP's filter_input() to get at the POST variables. This will bypass magic_quotes if they're enabled and will encourage you to validate or sanitize your input, as appropriate.

This approach will require you to know the names of the POST variables ahead of time, but that's a good thing. Here's how it might look:

$expected_keys = array(
    'foo',
    'bar',
    // etc.
);

$datatopost = array();

foreach ($expected_keys as $expected_key) {
    $value = filter_input(INPUT_POST, $expected_key, <filter>, [<options>]);

    if ($value !== FALSE && !is_null($value)) {
        $datatopost[$expected_key] = $value;
    }
}

// CURL code here
Ben Dunlap
BTW, this is only available in PHP >= 5.2.0
Seb
Good point, but then again PHP 5.2.0 was released 3 years ago. More in the comments for @Seb's answer.
Ben Dunlap