Reviewing Practical PHP Exploitation Techniques

Fri, 04 Apr 2008 10:22:20 GMT

The OWASP London Chapter last night (03/Apr/08) was excellent. Thanks to everyone involved for a top night!

  • For those who didn't attend, Rodrigo Marcos discussed his research on hacking PHP sockets for fun and profit. I found the concept very interesting. He discussed hacking PHP sockets; however, the techniques he discusses could be used as an application reverse proxy, although, scalability and stability could be a problem.
  • David Kierznowski (myself) gave a talk on practical PHP exploitation techniques using real world examples. I think we scared some of the guys from a certain university who recognised real world vulnerable code in their own applications :)
  • Colin Watson opened a can of worms in his discussion of security badges (Hacker Safe, Hacker proof etc). We had a good discussion on this!

I have uploaded my presentation to my site. I spent a lot of time trying to get good screenshots, so I hope it makes it easy to follow for those who couldn't attend.

David KierznowskiDavid Kierznowski
Hugo sent me an interesting point regarding the urldecode() attack. I mentioned that urldecode would change %2527 to % + 27.
Hugo: The Webserver will change %25 to %, and then urldecode() will change %27 to "'".
Lets try this out:
$a = $_GET['t'];

    echo $a; // before urldecode
    $b = urldecode($a);
    echo $b; // after urldecode

We get from t=%25 | t=%:
    $a = %
    $b = % // no change
Thanks for the observation Hugo. While we are on the subject of urldecode(). urldecode() is also vulnerable to NULL byte injection. So there is certainly potential for other vulnerabilities such as File Include bugs (%2500).
Awesome AnDrEwAwesome AnDrEw
Correct me if I'm wrong, David, since I am in no way an expert in PHP, but nullbytes can easily be detected with preg_match and preg_match_all assuming they are in a Hex-encoded string, right? I've experimented with it a bit in the past, and always found it work in my test cases.
Gustavo CardialGustavo Cardial
Very nice, I'll check it out! Also, if you know where to find the php sockets presentation, please, let me know
JoeyJoey
Thanks for publishing your presentation David. Always good to have more documented vulnerabilities (and their solutions) to keep newly built applications on top of them.
hadaka-sarutobihadaka-sarutobi
Can you elaborate more on multi-byte encoding attacks and how one attacks/defends them?
mikemike
Wow, its cool to see some CVE's instead of just theory. I am not saying that I don't enjoy theory. urldecode() isn't the only way to bypass filtering. I used base64_decode() here to bypass magic_quotes_gpc to hit some nifty SQL injection. The SQL payload I used is a bit different from the norm. http://milw0rm.com/exploits/4733 Also EVERY file function in php suffers from a null byte issue because they are all calling the same C file handling function, go ahead look at the stack trace in GDB. To be honest as a C programmer I'm horrified some functions will read past the null byte. Peace
David KierznowskiDavid Kierznowski
Awesome AnDrEw, as far as I know, I think this is one way to handle NULL bytes. hadaka, I could probably do a seperate presentation on that topic. See Awesome AnDrEw's comment. mike, cool stuff man. Keep up the good work.
VizViz
There is an issue on slide 12 with
POST http://192.168.1.4/t/xoops-2.0.14/htdocs/install/index.php HTTP/1.1
lang=../../../../../../../../etc/passwd%00&op=start&submit=Next
NOTE: This attack will not work if MAGIC QUOTES are enabled. MAGIC QUOTES escapes null characters to . This feature is often forgotten about.
magic quotes is deprecated and will be going completely away with php 6. Advising people to use it is setting them up for trouble. per the manual: http://www.php.net/manual/en/security.magicquotes.php
Warning This feature has been DEPRECATED and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged.
As well it's inconsistent and doesn't always work. They are removing it because they've realized you can't create defensive coding with a language option that only works half the time. It simply doesn't work. A far better solution to the include problem is to compare the input variable and switch on it:
$var=$_GET['language'];
switch($var)
{
  case "english":
    $include='english.php';
    break;
  case "spanish":
    $include='spanish.php';
    break;
  default:
    $include='genericerror.php';
    //or even 'english.php'
}
You could also set up an associative array of include directories and do an array reference using $var as the index to locate a path or something. If the value at that index is empty (unexpected/malicious input) use the safety include. Using input directly, no matter how it's filtered, to build a path is very very bad form. Always has been. I've lost track (I'm sure you have too 8) of the number of vulnerabilities caused by this type of stupidity. As well, you can use a whitelist filter on your input to remove things like null. eg:
$inputvar=$_GET['inputvar'];
$inputvar=preg_replace("/^[\w\.\@]/","",$inputvar);
(remove all but a-z,A-Z,0-9, . and @)
Trying to filter all the bad stuff out is a losing proposition, much better to *only allow the good stuff*. It's future proof. Great article!!! -Viz