I guess I should have an intro as to what this is about. Mostly, I've been
coding and auditing various CGIs, and was trying to figure out how to leverage
a few problems I thought were holes. So whatever, I'll shutup and get onto
the holes.
----------------[ The Beef
----[ Poison NULL byte
Note: The name `Poison NULL byte` was originally used by Olaf Kirch in a
Bugtraq post. I liked it, and it fit... So I used. Greetings to Olaf.
When does "root" != "root", but at the same time, "root" == "root" (Confused
yet)? When you co-mingle programming languages.
One night I got to wondering, exactly what would Perl allow, and could I get
anything to blow up in unexpected ways. So I started piping very weird data
out to various system calls and functions. Nothing spectacular, except for
one that was quite notable...
You see, I wanted to open a particular file, "rfp.db". I used a fake web
scenario to get an incoming value "rfp", tacked on a ".db", and then opened
the file. In Perl, the functional part of the script was something like:
Great. I pass 'user_input=rfp', and the script tries to open "rfp.db".
Pretty simple (let's ignore the obvious /../ stuff right now).
Then it got interesting when I passed 'user_input=rfp%00'. Perl made
$database="rfp .db", and then tried to open $database. The results? It
opened "rfp" (or would have, had it existed). What happened to the ".db"?
This is the interesting part.
You see, Perl allows NUL characters in its variables as data. Unlike C,
NUL is not a string delimiter. So, "root" != "root ". But, the underlying
system/kernel calls are programmed in C, which DOES recognize NUL as a
delimiter. So the end result? Perl passes "rfp .db", but the underlying libs
stop processing when they hit the first (our) NUL.
What if we had a script that allowed trusted junior admins to change passwords
on anyone's account EXCEPT root? The code could be:
$user=$ARGV[1] # user the jr admin wants to change
if ($user ne "root"){
# do whatever needs to be done for this user }
(**NOTE: this is here in WAY simplistic form & theory just to
illustrate the point)
So, if the jr. admin tries 'root' as the name, it won't do anything. But, if
the jr. admin passes 'root ', Perl will succeed the test, and execute the
block. Now, when systems calls are piped out (unless it's all done in Perl,
which is possible, but not likely), that NUL will be effectively dropped, and
actions will be happening on root's record.
While this is not necessarily a security problem in itself, it is definitely
an interesting feature to watch for. I've seen many CGIs that tack on a
".html" to some user-submitted form data for the resulting page. I.e.
page.cgi?page=1
winds up showing me 1.html. Semi-secure, because it adds ".html" page, so
you'd think, at worst, it'd only show HTML pages. Well, if we send it