#!/usr/bin/perl $|=1; $TIMEOUT=10; #connect timeout $RECEIVE_LEN=1024; #receive buffer if ($#ARGV < 0){help();exit} use Getopt::Std; getopts('R:H:P:p:hvao:O:'); if ($opt_h || !$opt_R || !$opt_H || !$opt_P){help();exit} $wwwhost=$opt_H; $wwwport=$opt_P; $verbose=$opt_v; $WAITALL=$opt_a;# MSG_WAITALL recv flag $use_proxy=$opt_p; $hlogfile=$opt_o; $mlogfile=$opt_O; @rules=loadrules($opt_R); if ($use_proxy){ @plist=loadproxy($use_proxy); $pnum=@plist; $pcur=0; if ($verbose){print STDERR "$pnum proxies loaded\n"} } use Socket; $SIG{PIPE}='IGNORE'; $FBUGS=0; for $rule (@rules){ my ($rflags, $data, $method, $uri, $explain)=parserule($rule); my $crlf=0; my $req=undef; my $res=undef; if ($uri=~/\\r\\n/){ $uri=~s/\\r\\n/\r\n/g; $crlf=1; } if ($use_proxy){ my $pfail=0; if (!($uri=~/^\//)){$uri=sprintf("/%s", $uri)} if ($crlf==1){ $uri=~s/\r\n\r\n/\r\nHost: $wwwhost:$wwwport\r\n\r\n/g; $req=sprintf("%s http://%s:%s%s",$method,$wwwhost,$wwwport,$uri); }else{ $req=sprintf("%s http://%s:%s%s HTTP/1.1\r\nHost: %s:%s\r\n\r\n",$method,$wwwhost,$wwwport,$uri,$wwwhost,$wwwport); } while(!$res){ if ($pcur >= $pnum){$pcur=0;} my ($proxyip, $proxyport) = split(/:/, $plist[$pcur++]); print STDERR "trying $proxyip:$proxyport ... "; $res=sendraw($proxyip, $proxyport, $req, $rflags); if (!$res){$pfail++;} if ($pfail >= $pnum){ print STDERR "all proxies are dead\n"; exit; } } $pfail=0; }else{ if ($crlf==1){ $uri=~s/\r\n\r\n/\r\nHost: $wwwhost:$wwwport\r\n\r\n/g; $req=sprintf("%s %s",$method,$uri); }else{ $req=sprintf("%s %s HTTP/1.1\r\nHost: %s:%s\r\n\r\n",$method,$uri,$wwwhost,$wwwport); } $res=sendraw($wwwhost, $wwwport, $req, $rflags); } # print out results if ($res=~/$data/){ $FBUGS++; my $tmp=$explain; $tmp=~s/(\\n\\t|\;)/\n\t/g; my $str="BUG FOUND($wwwhost:$wwwport):\n uri:\t$uri\n expl:\t$tmp\n"; print $str; if ($hlogfile){plog($hlogfile, $str)} if ($mlogfile){plog($mlogfile, "BUG^$wwwhost:$wwwport^$uri^$explain\n")} if ($verbose){ $str = " expc:\t$data\n"; print $str; if ($hlogfile){plog($hlogfile, $str)} $res=~s/\r\n/\r\n\t/g; $str=" resp:\t$res\n*********************************************\n"; print $str; if ($hlogfile){plog($hlogfile, $str)} }else{ $str="*********************************************\n"; print $str; if ($hlogfile){plog($hlogfile, $str)} } } } print STDERR "$FBUGS possible holes found total\n"; exit; # subroutines # send-receive data using sockets sub sendraw { my ($host,$port,$str,$rflags)=@_; my ($so,$res); socket($so,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) || die("socket:$!\n"); eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $TIMEOUT; if(!connect($so,pack "SnA4x8",2,$port,inet_aton($host))){ print STDERR "can't connect:$!\n"; return undef; } alarm 0; }; if($@ eq "alarm\n"){ print STDERR "connect to $host:$port timeout\n"; close($so); return undef; } send($so,$str,0); #while(read($so,$buf,512)){$res.=$buf} if ($WAITALL){$rflags=MSG_WAITALL();} recv($so,$res,$RECEIVE_LEN,$rflags); return $res; } # show help sub help { print < :: bom shankar! Usage: zwwwcan.pl -R -H -P [-p proxyfile] [-a] [-v] [-o logfile] [-O logfile] -R 'rulefile' : load arirang rule file 'rulefile' -H 'host' : target host 'host' -P 'port' : target port 'port' -p 'proxyfile' : use proxy list 'proxyfile' for scaning -h : this help -v : verbose output(recommended) -a : force MSG_WAITALL receive flag -o 'logfile' : save results in 'logfile' in human readable format -O 'logfile' : save results in 'logfile' in machine parseable format Note: Log files will be appended. === have a good day HELP ; } # load, strip proxylist sub loadproxy { my ($file)=@_; my $fd; my @pl; open($fd, $file) || die("open:$file:$!\n"); while(<$fd>){ s/[\r\n]//g;s/\s//g; if ($_){ push(@pl, $_); } } close($fd); return @pl; } # load arirang rules sub loadrules { my ($file)=@_; my $fd; my @rl; open($fd, $file) || die("open:$file:$!\n"); while(<$fd>){ s/[\r\n]//g; s/^\s+//; if (/^#/){next} if (!$_){next} push(@rl, $_); } close($fd); return @rl; } # parse rules string (based on manual scanrule/rule.uxe from arirang) sub parserule { my ($str)=@_; my ($tmp,$rflags,$rdata,$rmethod,$ruri); if ($str=~/^\(([^\)]*)\)\s/){ ($rflags, $tmp)=split(/\)\s/, $str, 2); $rflags=~s/\(//; if ($rflags eq "OOB"){$rflags=MSG_OOB();} elsif ($rflags eq "PEEK"){$rflags=MSG_PEEK();} elsif ($rflags eq "ALL"){$rflags=MSG_WAITALL();} else{$rflags=0} ($rdata, $tmp)=split(/\-\>\s/, $tmp, 2); }else{ $rflags=0; ($rdata, $tmp)=split(/\-\>\s/, $str, 2); } ($rmethod, $tmp)=split(/\s:/, $tmp, 2); ($ruri, $tmp)=split(/\^/, $tmp, 2); return ($rflags,$rdata,$rmethod,$ruri,$tmp); } sub plog { my ($file, $str)=@_; my $f; open($f,">>$file") or die "open:$file:$!\n"; print $f "$str"; close($f); }