HP Security Products Blog
From applications to infrastructure, enterprises and governments alike face a constant barrage of digital attacks designed to steal data, cripple networks, damage brands, and perform a host of other malicious intents. HP Enterprise Security Products offers products and services that help organizations meet the security demands of a rapidly changing and more dangerous world. HP ESP enables businesses and institutions to take a proactive approach to security that integrates information correlation, deep application analysis and network-level defense mechanisms—unifying the components of a complete security program and reducing risk across your enterprise. In this blog, we will announce the latest offerings from HP ESP, discuss current trends in vulnerability research and technology, reveal new HP ESP security initiatives and promote our upcoming appearances and speaking engagements.

Take your %00 and shove it

We've recently been optimizing our Local File Inclusion (LFI) audit engine. Part of that effort has included poking around in different frameworks (php, .NET, java, ruby/rails, python, perl... etc) and seeing how many ways a developer might fall prey to this vulnerability. One of the common ways to leverage this vulnerability is by appending  a null byte (%00, 0x00, ASCIIZ), c-style string terminator, to the end of a parameter that might be susceptible to an LFI vulnerability. Sadly, this type of injection has worked in almost all known major web development languages. Microsoft's .NET is the outlier. While there are currently no known API's that allow null bytes, it has had its fair share of issues in the past (fixed in 2007 KB928365).


So how does this happen? Some common ways this might happen in PHP are shown in the following snipit of code...



In the above code, the developer needs to include some file, or some template, and is using a raw HTTP parameter as the file name. Require/fopen/fpassthru will try to load files relative to the current working directory. However, if an attacker were to specify a full path (such as "/etc/passwd"), PHP would automatically try to read that file directly into memory (and in these cases, reflect it). Of course the PHP process user (usually Apache's user) would need to have access to that file but that doesn't exclude a lot of interesting attacks...


So why did you tell me about the null byte? The null byte trick helps when there is an appended value (like ".template"). A crafty attacker knows that the underlying system functions are all written in C and %00 is the url encoded version of the C string terminator (0x00, ASCIIZ). With this information you can effectively cause the appended value to be ignored. When "/etc/passwd\0.template" is passed to the underlying operating system the null byte (\0) will be interpreted as the end of the string, thus "/etc/passwd" will be loaded as the file. This type of vulnerability is severe. It's well known that this generally leads to arbitrary code execution on the server. Clearly, though, there is an even more immediate problem. Attackers now have complete access to your server-side source code. We've run into this problem so often during penetration tests that we wrote a tool to "mirror" website's source code based on a single LFI vulnerability and the pages we crawled.


You might be saying to yourself now, "Ok. Well thats fine, but I've never seen this. Why would anyone do that?". Well.,hopefully you're not thinking that but it is true that our previous example was fabricated... but Google Code Search doesn't index any of my example code, just real code. I wonder...how I can use this to my benefit?


Google Code is pretty awesome. You can search code with full regexs. (I wonder why I can't do this with Google itself! grr). So given that awesome functionality, here is a quick regex search to automatically find opensource PHP projects that have LFI vulnerabilities.


Of course its not all about PHP. Here are some other common ways we've seen LFI happen...


Here is some Ruby on Rails:



Here is some Java:



This is one snip-it of PHP, an image uploader and resizer, that really suprised me. This was essentially an insecure file upload as well as an LFI.




This all begs the question, why the f*$k do web development languages still forward these strings directly into the libc versions? Stefan Esser figured this out years ago when he was creating a the Hardened PHP project (althought not bullet proof as Esser points out himself). Hardened PHP has included file system wrappers that will not allow null bytes to be injected into underlying OS system calls. In fact, this was reported to PHP as early as 2001 in their bug database, but have chosen to ignore this for whatever reason. I have no idea why a developer would need that functionality. Perhaps their rationale is a performance one... but I can't believe the benefits in performace in this instance outweigh the security impact. I imagine thousands of vulnerabilities in OSS projects would not have existed if the uses of open in *nix or OpenFile in windows were wrapped and checked for bad characters. Microsoft has got this right, though. This is exactly what they and the Suhoshin patch do to protect the developers on the web. 


As a side note... Props to Ubuntu for distributing PHP with the Suhoshin patches applied to the default install. And to any other vendors that do this as well... although you should check your PHP install to make sure you have the Hardened PHP patches installed. Stefan et al. have done an excellent job tying up some of the loose ends PHP seems to leave all over the place.

Talking Headers: Part 2

While my rookie Mark McGwire cards aren't appreciating at all, my header collection is.  Check these actual headers out:



  • php warning: Unknown(): Unable to load dynamic library '/usr/local/lib/php/extensions/no-debug-non-zts-20020429/mysql.so' - Cannot open "/usr/local/lib/php/extensions/no-debug-non-zts-20020429/mysql.so" in Unknown on line 0

  • php: Error parsing /usr/www/users/bob/cgi-bin/php.ini on line 125

  • php warning: Function registration failed - duplicate name - pdf_new in Unknown on line 0, Function registration failed - duplicate name - pdf_delete in Unknown on line 0...


Yes, those are actual HTTP header names and values. That's some serious ugliness right there. Why PHP would be reporting errors through the headers I can only guess--but it is.


Finding any information on this via a search engine has proven impossible, as it's polluted with PHP syntax error messages and relevant discussions. So, if you have any ideas as to they why/how of this, I'd be interested to hear them.


And of course, my shameless product plug: WebInspect will alert on these.

Labels: Headers| HTTP| PHP| Research
Search
Showing results for 
Search instead for 
Do you mean 
About the Author(s)
Follow Us


HP Blog

HP Software Solutions Blog

Labels
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation