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 interestingattacks...

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.

@Jericho. Absolutely, the results from google code are not guaranteed to be vulns. However its a pretty good way to find poor design decisions that use language API's insecurely.

So if your interested, as we were, about the most common ways developers fall prey to LFI, searching code is pretty helpful. Even if each specific search result isn't a vuln, the usage pattern is probably repeated plenty of times.