Jean Pacal Perei

#!/usr/bin/perl

#

# THC Web Vulnerability Scanner v3.8

#

# $Id: thc.pl, v3.8 2010/20/06 16:15:56 jpp Exp $

#

#

# Description: THC is an effective open source web vulnerability

#              scanner for detecting security flaws and bugs in a

#              remote network. It also crawls for e-mail addresses

#              and sensitive files / directories.

#

# Author: Jean Pascal Pereira <pereira@secbiz.de>

#

# This program is free software; you can redistribute it and/or modify it under

# the terms of the GNU General Public License as published by the Free Software

# Foundation; either version 2 of the License, or (at your option) any later

# version.

#

# This program is distributed in the hope that it will be useful, but WITHOUT

# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more

# details.

#

# You should have received a copy of the GNU General Public License along with

# this program; if not, write to the Free Software Foundation, Inc., 59 Temple

# Place, Suite 330, Boston, MA  02111-1307  USA



use strict;

use 
threads;

use 
warnings;



use 
LWP::UserAgent;

use 
Getopt::Std;

use 
IO::Socket;





my %params=();

getopts("hpgqsrfmok:u:a:c:e:",%params);



if (
defined $params{h})

{

   print 
"n [ THC WEB VULNERABILITY SCANNER ]nn";

   print 
"  -u -- defines the target url (required)n";

   print 
"  -c -- defines the cookie for our http requestsn";

   print 
"  -a -- defines the user agent for our http requestn";

   print 
"  -p -- defines a http proxy for our http requestsn";

   print 
"  -e -- custom sql error string (usually not necessary)n";

   print 
"  -s -- silent moden";

   print 
"  -q -- disable sound alertsn";

   print 
"  -r -- do not save the vulnerability reportn";

   print 
"  -g -- enable google dorks (powerful, but get a cookie first!)n";

   print 
"  -o -- enable file backup scann";

   print 
"  -f -- scan for sensitive directories / files (could be noisy)n";

   print 
"  -m -- scans the target for e-mail addressesn";

   print 
"  -k -- string from charcode encoder/decoder for web attacksrnn";

   exit;

}



elsif (defined $params{k})

{

   
my $str $params{k};



   if(
$str =~ m/^-?[.|d|,]*Z/)

   {

      
my @strval split (/,/, $str);

   

      foreach(@
strval)

      {

         print 
chr($_);

      }

   }



   else

   {

      foreach(
0..length($str)-1)

      {

         print 
ord(substr($str,$_1));

         print 
"," if ($_ != length($str)-1);

      }

   }



   exit;

}



elsif (!defined $params{u})

{

   print 
"n [ THC WEB VULNERABILITY SCANNER ]nn";

   print 
"a" if(!defined $params{q});

   print 
" ERROR: missing argument(s), use the -h parameter for more informationrnn";

   exit;

}



my $verbose  1;

my $scan_uri $params{u};

my $emlscan;



my $user_agent;

my $http_cookie;

my $http_proxy;

my $sound_alerts;



my $no_reporting 0;



my $sqli_error_str $params{e} || "sql error";

my $xss_error_str "<XSSTEST>";



my $uriregexp "<a [^>]*href=.((http://)?((www.)?[-_a-zA-Z0-9/.~?&,=;]*)).[^>]*>(.*)</a>";



$verbose if(defined $params{s});

$emlscan if(defined $params{m});



$user_agent   =  $params{a} if(defined $params{a});

$http_cookie  =  $params{c} if(defined $params{c});

$http_proxy   =  $params{p} if(defined $params{p});



if(
defined $params{q})

{

   
$sound_alerts 0;

}



else

{

   
$sound_alerts 1;

}



if(
defined $params{r})

{

   
$no_reporting 1;

}



$scan_uri =~ s/http:////i;



my $host;

my $banner;



my @data_container;

my @crawled;



my @allowed_filetypes = ("php""php3""php4""php5""jsp""html""htm""asp""aspx""cgi");



my $output_file "THC_REPORT_".time().".html";



my $active 0;



sub start_crawling

{



   
$host shift;



   $| = 
1;



   if (!
$no_reporting)

   {



      
open(OUT,">".$output_file);

   

      print 
OUT "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"n";

      
print OUT "       "http://www.w3.org/TR/html4/loose.dtd">n";

      
print OUT "<html>n<head>n<title>THC Scan Report</title>n</head>";

      print 
OUT "<h1><u>THC SCAN REPORT</u></h1>n<br />n<b>Target URI: </b>";

      print 
OUT "<a href="".$host."">".$host."</a>n<br />n<br />n<hr>n";

      

   }

   

   
filescan($host) if (defined $params{f});



   if (!
$verbose)

   {

      
$banner threads->new(&statusbanner);

      
$banner->detach;

   }

   

   if (
defined $params{g})

   {

      
google_attack("site:".$scan_uri." php asc");

      
google_attack("site:".$scan_uri." php desc");

      
google_attack("site:".$scan_uri." php id");

      
google_attack("site:".$scan_uri." php order");

      
google_attack("site:".$scan_uri." php cat");

      
google_attack("site:".$scan_uri." php list");

      
google_attack("site:".$scan_uri." asp asc");

      
google_attack("site:".$scan_uri." asp desc");

      
google_attack("site:".$scan_uri." asp id");

      
google_attack("site:".$scan_uri." asp order");

      
google_attack("site:".$scan_uri." asp cat");

      
google_attack("site:".$scan_uri." asp list");

      
google_attack("site:".$scan_uri." jsp asc");

      
google_attack("site:".$scan_uri." jsp desc");

      
google_attack("site:".$scan_uri." jsp id");

      
google_attack("site:".$scan_uri." jsp order");

      
google_attack("site:".$scan_uri." jsp cat");

      
google_attack("site:".$scan_uri." jsp list");

   }

   

   
crawl($host);

}



sub relative

{

   
my $uri shift;

   

   if(
$uri !~ m/^https?:///)

   
{

      
$uri $host."/".$uri;

   }

   

   return 
$uri;

}



sub get

{

   
my $uri shift

   

   
my $agent $user_agent || "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1)";

   

   
my $ua LWP::UserAgent->new;

   

   
$ua->timeout(10);

   
$ua->agent($agent);

   
$ua->default_header("Cookie" => $http_cookie) if (defined $http_cookie);

   
$ua->proxy(["http"], "http://".$http_proxy."/") if (defined $http_proxy);



   
my $response $ua->get($uri);



   if (
$response->is_success)

   {

      return 
$response->content;

   }



   else

   {

      return -
1;

   }

}



sub check

{

   
my $target_uri shift;

   
my $errormessage shift;

   
my $http_response;

   

   
my @default_errors = ( "you have an error in your sql syntax""database error"

                          
"server error in""oracle error""mysql_fetch_array",

                          
"mysql_fetch_assoc""mysql_fetch_num""mysql_fetch_row",

                          
"mysql_fetch_object""syntax error""empty delimiter"

                          
"unclosed quotation mark""SQLServer JDBC Driver""ORA-01756" );

   

   
$target_uri relative($target_uri);

   

   
$http_response get($target_uri);

   

   if ((
defined $params{o}) && ($target_uri =~ /(.*)?/))

   {

      if(
get($1.".bak"ne "-1")

      {

         print 
"a" if ($sound_alerts);

         print 
"Possible backup file found: ".$1.".baknn";

         if (!
$no_reporting)

         {

            print 
OUT "<a href="".$1.".bak">";

            print 
OUT $1.".bak</a>n<br />n";

         }

      }



      
elsif(get($1."~"ne "-1")

      {

         print 
"a" if ($sound_alerts);

         print 
"Possible backup file found: ".$1."~nn";

         if (!
$no_reporting)

         {

            print 
OUT "<a href="".$1."~">";

            print 
OUT $1."~</a>n<br />n";

         }

      }

   }

   

   if(
$http_response)

   {

      if (
$http_response =~ m/$errormessage/ig)

      {

         if(
$verbose)

         {

            print 
"a" if ($sound_alerts);

            print 
"nPossible vulnerability: ".$target_uri."nn";

         }



         if (!
$no_reporting)

         {

            print 
OUT "<a href="".$target_uri."">";

 

            
$target_uri =~ s/</&lt;/g;

            
$target_uri =~ s/>/&gt;/g;



            print 
OUT $target_uri."</a>n<br />n";

         }



      }



      foreach(@
default_errors)

      {

         if (
$http_response =~ m/$_/ig)

         {

            if(
$verbose)

            {

               print 
"naPossible vulnerability: ".$target_uri."nn";

            }



            if(!
$no_reporting)

            {

               print 
OUT " "x4;

               print 
OUT "Possible vulnerability: <a href="".$target_uri."">";

 

               
$target_uri =~ s/</&lt;/g;

               
$target_uri =~ s/>/&gt;/g;



               print 
OUT $target_uri."</a>n<br />n";

            }

         }

      }

   }

}



sub attack

{

   
my $uri shift;

   
my $mode shift;

   
my $response shift;

   
my $attack_string;

   

   if(
$mode == 1)

   {

      
$attack_string shift || "%27";

   }

   

   
elsif($mode == 2)

   {

      
$attack_string shift || "<XSSTEST>";

   }

   

   
my @split_uri split (/&/,$uri);

   
my $current_uri;



   while(
scalar @split_uri)

   {

      foreach(@
split_uri)

      {

         
$current_uri .= $_."&";

      }

      

      
pop @split_uri;

      

      
$current_uri substr($current_uri,0,-1).$attack_string;



      
$current_uri =~ s/&amp;/&/g;

      

      if(
$verbose)

      {

         print 
"Attacking: ".$current_uri."n";

      }

      

      if(
$response)

      {

         
check($current_uri$response);

      }



      else

      {

         
check($current_uri);

      }

      

      
$current_uri undef;

   }

}



sub google_attack

{

   
my $query shift;



   
$query =~ s/ /+/g;



   
my $resp get("http://www.google.com/search?q=".$query."&as_qdr=all&num=100&filter=0");



   
my @content split(/</h3>/,$resp);



   foreach(@
content)

   {

      if(
$_ =~ m/<li class=g><h3 class=r><ab[^>]*href="(.*?)" b[^>]*>(.*?)</a>/)

      {

         
attack($11$sqli_error_str);

         
attack($12$xss_error_str);

         

         
mailscan($_) if (defined ($emlscan));

      }

   }

}



sub filescan

{

   
my $host shift;



   
my @sensitive_stuff = ("/admin/""/phpinfo.php""/server-status""/old.htaccess""/htaccess.old""/icons/",

                          
"/cgi-bin/""/cgi.cgi/""/webcgi/""/cgi-914/""/cgi-915/""/bin/""/cgi/""/log/",

                          
"/logs/""/ows-bin/""/cgi-sys/""/cgi-local/""/htbin/""/scripts/""/cgi-exe/"

                          
"/~root/""/robots.txt""/test/""/test.php""/test.asp""/info.php""/help/""/old/",

                          
"/index.php.bak""/config/""/conf/""/config.inc""/phpmyadmin/""/global.inc",

                          
"/inc/config.php""/version.php""/version.html""/version.htm""/README""/control/",

                          
"/backup/""/private/""/stats/""/traffic/""/counter.cgi""/sqladmin/""/sql/"

                          
"/WS_FTP.LOG""/Thumbs.db""/settings/""/autologon.html?10514""/administrator/",

                          
"/backup.rar""/backup.zip""/backup.tar""/backup.gz""/backup.tar.gz""/backup.bz2",

                          
"/logs.tar""/logs.rar""/logs.gz""/logs.tar.gz""/logs.bz2""/logs.zip""/access.log",

                          
"/guardian.log""/services/""/service/""/sshome/""/mail/""/webmail/""/roundcube/",

                          
"/cgi-perl/""/php.ini""/sqldump.sql""/dump.sql""/backup.sql""/structure.sql",

                          
"/logicworks.ini""/ip.txt""/ips.txt""/ip.log""/ips.log""/smssend.php""/sms.php",

                          
"/servlet/""/_vti_pvt/""/webalizer/""/doc/""/usage/""/setup/""/setup.php""/temp/",

                          
"/mysqldumper/""/turbodbadmin/""/tbda/""/Mem/""/data/""/code/""/boot/""/pma/",

                          
"/samples/""/upload/""/publisher/""/adserv/""/incoming/""/demo/""/examples/",

                          
"/cert/""/install.php""/install/""/install.php.bak""/install.php.old""/CHANGELOG.txt",

              
"/foo/""/foo.php""/foo.txt""/bla/""/blah/""/bleh/""/default/""/pdf/""/_._.html");



   foreach(@
sensitive_stuff)

   {

      print 
"Checking: ".$_."n";

      if((
get($host.$_ne "-1") && (get($host.$_) !~ m/404/gi) && (get($host.$_) !~ m/not found/gi))

      {

         print 
"a" if ($sound_alerts);

     print 
"Possible sensitive stuff: ".$host.$_."n"

     if (!
$no_reporting)

     {

        print 
OUT "Possible sensitive stuff: <a href="".$host.$_."">".$host.$_."</a>n<br />n";

     }

      }

   }

}



sub mailscan

{

   
my $uri shift;



   
$uri get($uri);



   if(
$uri)

   {

      
my @uri split(/n/, $uri);



      foreach(@
uri)

      {

         if (
get_mail($_))

         {

            print 
"a" if ($sound_alerts);

            print 
"Mail address detected: ".get_mail($_)."n";

            if (!
$no_reporting)

        {

           print 
OUT "Mail address detected: ".get_mail($_);

        }

         }

      }

   }

}



sub get_mail

{

   
my $content shift;



   
my $mailadd;



   
my @regexpr;



   
my @domains = ("ac","ad","ae","aero","af","ag","ai","al","am","an","ao","aq","ar","arpa","as","asia","at","au",

                  
"aw","ax","az","ba","bb","bd","be","bf","bg","bh","bi","biz","bj","bm","bn","bo","br","bs","bt",

                  
"bv","bw","by","bz","ca","cat","cc","cd","cf","cg","ch","ci","ck","cl","cm","cn","co","com","coop",

                  
"cr","cu","cv","cx","cy","cz","de","dj","dk","dm","do","dz","ec","edu","ee","eg","er","es","et",

                  
"eu","fi","fj","fk","fm","fo","fr","ga","gb","gd","ge","gf","gg","gh","gi","gl","gm","gn","gov",

                  
"gp","gq","gr","gs","gt","gu","gw","gy","hk","hm","hn","hr","ht","hu","id","ie","il","im","in",

                  
"info","int","io","iq","ir","is","it","je","jm","jo","jobs","jp","ke","kg","kh","ki","km","kn",

                  
"kp","kr","kw","ky","kz","la","lb","lc","li","lk","lr","ls","lt","lu","lv","ly","ma","mc","md",

                  
"me","mg","mh","mil","mk","ml","mm","mn","mo","mobi","mp","mq","mr","ms","mt","mu","museum","mv",

                  
"mw","mx","my","mz","na","name","nc","ne","net","nf","ng","ni","nl","no","np","nr","nu","nz","om",

                  
"org","pa","pe","pf","pg","ph","pk","pl","pm","pn","pr","pro","ps","pt","pw","py","qa","re","ro",

                  
"rs","ru","rw","sa","sb","sc","sd","se","sg","sh","si","sj","sk","sl","sm","sn","so","sr","st","su",

                  
"sv","sy","sz","tc","td","tel","tf","tg","th","tj","tk","tl","tm","tn","to","tp","tr","travel","tt",

                  
"tv","tw","tz","ua","ug","uk","us","uy","uz","va","vc","ve","vg","vi","vn","vu","wf","ws","ye","yt",

                  
"yu","za","zm","zw");



   
my $domains join("|", @domains);



   
# my black magic mail collection regular expressions ;o)

   # they should "bypass" / parse the most mail obfuscations



   
$regexpr[0] = "(\w+.[a-zA-Z0-9]*\s?_at_\s?\w+.[a-zA-Z0-9]*(.|[dot]|(dot))($domains))";

   
$regexpr[1] = "(\w+.[a-zA-Z0-9]*\@\w+.[a-zA-Z0-9]*(.|[dot]|(dot))($domains))";

   
$regexpr[2] = "(\w+.[a-zA-Z0-9]*\s?\[at\]\s?\w+.[a-zA-Z0-9]*(.|[dot]|(dot))($domains))";

   
$regexpr[3] = "(\w+.[a-zA-Z0-9]*\s?\(at\)\s?\w+.[a-zA-Z0-9]*(.|[dot]|(dot))($domains))";



   foreach(@
regexpr)

   {

      if(
$content =~ m/$_/i)

      {

         
$mailadd = $1;



         
# some filtering crap



         
$mailadd =~ s/_at_/@/g;

         
$mailadd =~ s/[at]/@/g;

         
$mailadd =~ s/(at)/@/g;

         
$mailadd =~ s/lt;//g;

         
$mailadd =~ s/&gt//g;

         
$mailadd =~ s/(.*)>//g;

         
$mailadd =~ s/mailto://g;



         
return $mailadd;

      }

   }

}



sub crawl

{

   
my $uri shift;

   

   
$uri relative($uri);

   

   if ((
$uri) && ($uri =~ m/$host/i))

   {

   

      
$uri get($uri);

      

      if(
$uri)

      {

         

         
my @content split(/n/,$uri);

      

         foreach(@
content)

         {

            if ((
$_ =~ m/$uriregexp/i) && (file_match($_, @allowed_filetypes) == 1))

            {

               if ((
array_search($1, @data_container)) == -1)

               {

                  
push @data_container, $1;

               }

            }

         }

      

         foreach(@
data_container)

         {

            if ((
array_search($_, @crawled)) == -1)

            {

               
attack($_1$sqli_error_str);

               
attack($_2$xss_error_str);

               

               
mailscan($_) if (defined ($emlscan));



               
push @crawled$_;

               
crawl($_);       

            }

         }

      }

   }

}



sub array_search

{

   
my $var shift;

   
my @array = @_;



   
my $index 0;

   

   while (
$array[$index])

   {

      
my $v $array[$index];

      if (
$v eq $var)

      {

         
last;

      }

     

      
$index++;

   }



   if (
$index > $#array)

   
{

      return -
1;

   }

   

   return 
1;

}



sub file_match

{

   
my $var shift;

   
my @array = @_;



   
my $index 0;

   

   while (
$array[$index])

   {

      
my $v $array[$index];

      

      if (
$var =~ m/.$v/i)

      {

         
last;

      }

      

      
$index++;

   }



   if (
$index > $#array)

   
{

      return -
1;

   }

   

   return 
1;

}



sub delay

{

   
select(undefundefundef0.0999999);

}



sub statusbanner

{

   $| = 
1;

   
$active 1;

   print 
"[ ] Crawling... ";

   

   while(
$active)

   {

      print 
"r["."|]";

      
delay;

      print 
"r["."/]";

      
delay;

      print 
"r["."".chr(196)."]";

      
delay;

      print 
"r["."\]";

      
delay;

   }

}



sub finish

{



   if(!
$no_reporting)

   {



      print 
OUT "<hr>n<br />n<br />n";

      print 
OUT "<small>Generated by THC web vulnerability scanner - ";

      print 
OUT "<a href="http://www.secbiz.de" target="_blank">www.secbiz.de</a></small>n";

      
print OUT "</body>n</html>";



      
close(OUT);

   }



   if(!
$verbose)

   {

      $| = 
0;

      
$active 0;



      print 
"r[#] Scan finished!";

      print 
"n[#] For futher information see "".$output_file.""." if (!$no_reporting);

      print 
"na" if ($sound_alerts);

      print 
"rnn";

   }

   

   else

   {

      print 
"a" if ($sound_alerts);

      print 
"nnScan finished! ";

      print 
"For futher information see "".$output_file.""." if (!$no_reporting);

      print 
"nrnn";

   }

   

}



start_crawling("http://".$scan_uri);

finish;
 


» ohne Titel
« ohne Titel