Indepth Code Execution in PHP: Part Two
This is a continued post from Code Execution in PHP; you can read the first post here, so if you haven't read that before please go ahead and read it first or else you would have problem understanding the second part.
“…It’s no secret that PHP is an easy language to which anyone with amateur coding skills could work with and as a rule with poor knowledge of basic security concepts, this factor alone often lead to new poorly written web-applications; Thus compromising their hosts and extraction of sensitive information. Recently, I was on a pentest for a project to which I was working on and went noticing unusual type of code execution. I decided to write about Code Execution Indepth because the developers need to focus on their poorly written web applications in PHP. This article will try covering code execution flaws in places which are less predictable and detail on snippets of code which might look secure while providing possibilities for ‘code injection’...”
In the earlier article, I tried covering practical examples which could potentially lead to Remote Command Execution (RCE) in PHP. Now let’s discuss about some other methods/mistakes which a PHP developer might just had done in writing his/her web application.
Curly Braces:
They say curly syntax is meant to separate code from strings. In contrast to this view, what it actually does is, ‘embed’ it. As in PHP manual pages written, it means that it would allow to use complex expressions (too complex but let’s just stick with minimal complexity for the sake of the demonstration).
Imagine Curly braces being used this way:
Imagine Curly braces being used this way:
<?php
If(isset($_GET['year']){
$year=$_GET['year'];
$finalizae="My birthday is 19{'year}.";
print $finalize
?>
The code used is supposed to ‘echo’ out the year variable (97) embedded inside “My birthday is 19xx” so an user had to submit ‘12’ to the ‘year’ as an input, it code would print out or ‘echo’, “My birthday is 1912”
Maliciously submitting an input such as ‘dir’ would end up listing files and folders of current directory when $finalize is called in the realm of PHP. This in turn would provide vivid information to a web attacker. Other commands are possible, I had just used ‘dir’, to be reliably simple enough!
Let’s imagine cases like:
$brief="I was here until ${`dir`} appeared here";
From the aforementioned code, ‘dir’, the system command would get executed. Wow. Why did that happen? Well, the code between curly braces will be evaluated and result will replace {`dir`} thus ending up creating a variable. That is the absolute reason why if this one PHP will be complaining about undefined PHP variable. What happened is fairly similar to:
<?php
eval("$brief");
?>
“$breif” is a result of the “dir” command as a string, similar malicious case for an web attacker to execute commands and ex-filtrate information would be:
<?php
$name='phpinfo';
${name}();
?>
If the above example for example stored name as the username and our username submitted was ‘phpinfo’, what happened as per the malicious request submitted as a payload leads to command execution revealing sensitive information disclosure.
Other Cases:
There are functions such as assert() which could be equally exploited but is rarely known to the web developers, it is often found on CTF challenges, same thing as the eval function.
<?php
$name='phpinfo()';
assert($name);
?>
Assert is designed to help with debugging and not evaluation, thus, leading to command execution. So if you use assert in a user supplied input which you think is trustable, probability is your code might just be vulnerable to Remote Code Execution (RCE) using malicious payloads by users of the application you trust.
Developers can use array functions to apply some list of properties to data or reverse. In most cases applying functions are predefined, and these types of vulnerabilities are not ‘almost’ known to the public or is limited by knowledge.
Anyway, These are the array functions I had been dealing with which could lead to RCE:
array_intersect_uassoc(), usort(), uksort(), array_filter(),
array_diff_uassoc(), array_diff_ukey(), array_reduce(),
array_udiff(), array_udiff_assoc(), array_udiff_uassoc(),
array_intersect_assoc(), array_uintersect(), array_uintersect_assoc(),
array_uintersect_uassoc(), array_walk(), array_walk_recursive() ,
uasort(), array_map()
In short, don’t use those with a user supplied input unless sanitized properly in PHP. The formula for an almost secure web application is to never trust input from users!
Let’s take the last function for an example (array_map) and exploit it:
<?php
$evil =$_GET['name'];
$some_array=array(0,1,2,3);
$new_array=array_map($evil,$some_array);
?>
Honestly, this is a rare snippet of code but just to prove the point behind mysterious remote code execution attacks, grab me an opportunity to explain what it does! It receives a parameter called ‘name’ via GET request and use this parameter to map it into an array called ‘$some_array’. But the function is also designed to execute call backs to functions. Developers using insecure coding practices do not realize this, thus leading to RCE exploitation with exploits like the following demonstrated:
http://localhost/index.php?name=phpinfo
The payload ‘phpinfo’ will be executed and the resultant would be a remote code execution bug which persists due to insecure coding practices. This theory is practical but there is a limitation. The limitation being, only we can call already written functions like phpinfo() or uname() but can’t write a code to be executed other than call functions.
These other functions are using callbacks, but they are not array based like previous once. They can however be used to create situations like demonstrated before in this article, so do not use them in user supplied input.
stream_filter_register(), set_error_handler()
register_shutdown_function(), register_tick_function()
And some other XML functions by default enabled in php:
- ·xml_set_character_data_handler()
- ·xml_set_element_handler()
- ·xml_set_end_namespace_decl_handler()
- ·xml_set_external_entity_ref_handler()
- ·xml_set_notation_decl_handler()
- ·xml_set_default_handler()
or pretty much, xml_set_*_*()
Remember: function call backs/functions using them are good! However in certain cases they are very bad for the logic of the application to behave as we had witnessed in this article. Most of the issues covered weren’t vulnerabilities. Infact, they were features of PHP. But, from improper usages of these *features*, the worse can happen and could lead to existence of potential vulnerabilities tossing up an opportunity for a web attacker to compromise the security of an application. Please be wise and read the manual of a (new) function before implementing in on a practical code and running them on production servers.
Happy Hacking!
About the Author
This following article is a guest post by Paulos Yibelo. Yibelo is the newest member of RHA family. He is a full time PHP coder and most of his research is involved with application security. In his free time he loves writing articles related to application security http://paulosyibelo.blogspot.com/.