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} #{ARGV[0]} -f xml -o #{wapiti_report_path}`
p "Report saved to #{wapiti_report_path}"
p "Parsing results"
results = []
report =, "rb")
doc =
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 == "url"
                                result[:url] = child.text
                        elsif == "parameter"
                                result[:parameter] = child.text
                results << result
                result = {}
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")
                p "Running GET sql injection test on url: " + url
                sqlmap_command = "#{sqlmap_path} -u \"#{url}\" --smart --skip=\"#{skipped_params.join(",")}\" --technique=EUS --flush-session --fresh-queries --level=2 --batch"
                out = `#{sqlmap_command}`
                printf out
                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")
                sqlmap_command = "#{sqlmap_path} -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


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

  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

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