Archive for July, 2010

Is Julian Assange really Max Zorin?

Saturday, July 31st, 2010

Has anyone else noticed now much Julian Assange (founder of wiki leaks) looks like Max Zorin – founder of the evil Zorin Empire and former KGB agent?

Julian Assange (left) Max Zorin (Right)

Julian Assange (left) Max Zorin (Right)

MongoDB is vulnerable to SQL injection (in PHP at least)

Thursday, July 29th, 2010

Its a misconception amongst some PHP programmers that because MongoDB doesn’t use SQL (all queries are passed in as either BSON or PHP objects which have been converted into BSON) it isn’t vulnerable to SQL injection. It is pretty easy to show that if your lazy and complacent when you code you can leave yourself just as vulnerable to attack.

Lets assume we have a table of users with a username and password field. In MySQL you’d be asking for trouble if in your authentication function you did the something along the lines of the following:

if (mysql_query(“SELECT * FROM users WHERE username=’$_GET['username']‘ AND password=’” . $_GET['password'] . “’”)) {
do_auth();
}

And someone passed in

‘ OR ‘1′=’1

into your password field. If you simply checked the response and authenticated the user based on if a row was received from the MySQL Database the user would authenticate as the $_GET['username'] every time. The correct approach would be to sanitize your $_GET parameters before you pass them into MySQL.

In MongoDB you might be tempted to do something like

if ($result = $mongo->test->users->findone(array(”username” => $_GET['username'], “password” => $_GET['password']))) {
do_login();
}

No query language no SQL injection right? Wrong. Epic fail. Don’t forget in PHP when you append [] to a $_GET['variable'] it turns into an array within php.

http://woot.php?variable[]=hello

$_GET['variable'] is now a PHP array(0 => ‘hello’). We can even assign the key of the array like this

http://woot.php?variable[$ne]=hello

Now $_GET['variable'] is a PHP with array with a key array(’$ne’ =>’hello’). When you pass this to mongo db as your password paramater it evaluates to “Password does not equal ‘hello’” which will pass every time.

Update: Simply filtering out $ne strings from the array keys isn’t good enough as it appears that the mongo driver is also vulnerable to null byte injection. array(’$ne\0wootwoot’ => ‘hello’) will evaluate to array(’$ne’ => ‘hello’);

What can you do? Sanitize your input. Don’t allow multi dimensional arrays to be passed as a input parameters to mongo. Surprisingly there isn’t a function built into the mongodb pecl extension to do this. The function below called “MongoSanatize” should make all user input for MongoDB safe.


<?php
function MongoSanatize($var) {

    if (is_array($var)) {

        $newVar = array();

        foreach($var as $key => $value)
        {
            
$newKey $key;

            if (is_string($key))
                
$newKey str_replace(array(chr(0), '$'), ''$key);

            if (is_array($value))
                
$newVar[$newKey] = MongoSanatize($value);
            else
                
$newVar[$newKey] = $value;
        }

        return $newVar;
    }

    return $var;
}

The function strips out all dollar signs and null characters from the key values on the array. If its run on a string or integer it should just return the string or integer