I was just looking at some PHP code for one of our clients, and found a case I haven't seen many times before. I thought I should share it here.
The code I was looking at looks like this:
<?php // Init the PHP array with some SQL code to start the query $declareSQLArray = InitializedArray('stuff'); // Use a strong enough validation routine for do the input // validation of POST variables while(list($name, $value) = each($_POST)) { if(!is_array($value)) $$name = StrongValidation($value); else $$name = $value; } // Do something with my variables and always do a proper // validation when I use the data // Eventually, build my SQL command, and send this to the DB $sql_command = join(' ', $declareSQLArray); mysql_query($sql_command); ?>
The code, even if horribly constructed, does not seem to show importantweaknesses, but the usual case of submitting a POST variable as an array, and bypassing the StrongValidation
. Then, in that case, it would havefailed every other validation routines in the code.
Even if experienced with PHP, you might not have encountered variable variables before. In short, this allows to dynamically declare named variables. Here is a simple example:
$ php -r '$name="foo"; $$name="Hello World!"; echo $foo;' >>> Hello World!
Here, the variable $foo
gets declared, and assigned using PHP variable variables capabilities.
Getting back to our code example, I'm sure the reader will spot the issue,and what an attacker can do to exploit such scenario to trigger, in that case,a SQL injection. Since the variable $declareSQLArray
is definedand initialized before the POST variables lookup, it is possible to reassign itusing the variable variables. In that case, no validation is performed when wesubmit an array, and this is exactly what we want to do!
To exploit the SQL injection, you only need to submit POST variables tooverwrite the $declareSQLArray
, and add the content that we want in it!
POST /code_example.php HTTP/1.1 Host: example.com ...declareSQLArray%5B%5D=SELECT...;&declareSQLArray%5B%5D=--&whatever...
Job done! The resulting SQL query will start with the payload that wassubmitted as part of $declareSQLArray
. You've got your SQL injection.
Update: While driving back home, I was wondering if I couldoverwrite values from the SESSION using this technique. A couple of lines of code, and POST request after the answer is short: YES.
Imagine that you have an isadmin variable as part of thesession (which is an associative array). This variable would be set in a code like this:
if ($user->isNotAdmin()) $_SESSION['isadmin'] = 0; else $_SESSION['isadmin'] = 1;
Exploiting the previous weakness of the code example, we are able tooverwrite the $_SESSION['isadmin']
content, only by supplying what will be interpreted as an associative array by PHP:
POST /code_example.php HTTP/1.1 Host: example.com ..._SESSION%5Bisadmin%5D=1&whatever...
I'm sure you're thinking, as I do, that this is getting moreinteresting!
Anyways, this issue is not new at all, it is known as Dynamic Variable Evaluation (thanks to Steve Christey).
The interesting part of it is that DAST won't be able to detect it (or maybeif you are lucky enough), and it is very hard for a SAST to deal with it (actually, I doubt any SAST vendor who supports PHP handles this case, but it'snot impossible since they have all they need to solve the problem).
Update 2: Based on the comments, I did some testing and observed that even if we can overwrite data from the session, this data doesnot get persisted in the session. This means that you can still control a valuefrom a super global for the remaining execution of the script, but cannot persist the data.