From e534edddb90ad131e43397038ff2c85329a8fc44 Mon Sep 17 00:00:00 2001 From: et <> Date: Mon, 8 Dec 2008 03:47:07 +0000 Subject: [PATCH] Script which allows to import OWASP WebScarab sessions to WMAP by sinbad git-svn-id: file:///home/svn/framework3/trunk@6004 4d416f70-5f16-0410-b530-b9f4589650da --- tools/import_webscarab.rb | 177 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 tools/import_webscarab.rb diff --git a/tools/import_webscarab.rb b/tools/import_webscarab.rb new file mode 100644 index 0000000000..84ce918aef --- /dev/null +++ b/tools/import_webscarab.rb @@ -0,0 +1,177 @@ +#!/usr/bin/env ruby + +# Script which allows to import OWASP WebScarab sessions +# (http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project) +# into the metasploit/WMAP database. +# By spinbad + +require 'resolv' +require 'sqlite3' + +puts "--- WMAP WebScarab Session Importer ---------------------------------------------" +puts + +if ARGV.length < 2 + $stderr.puts("Usage: #{File.basename($0)} wescarabdirectory sqlite3database [target] [startrequest]") + $stderr.puts + $stderr.puts("webscarabdirectory\tThe directory where you stored the webscarab session") + $stderr.puts("sqlite3database\t\tThe name of the database file") + $stderr.puts("target\t\t\tThe target (host or domain) you want to add to the database") + $stderr.puts("startrequest\tThe request to start with...") + $stderr.puts + $stderr.puts("Examples:") + $stderr.puts("#{File.basename($0)} /tmp/savedsession example.db") + $stderr.puts("#{File.basename($0)} /tmp/savedsession example.db www.example.com") + $stderr.puts("#{File.basename($0)} /tmp/savedsession example.db example.com") + $stderr.puts("#{File.basename($0)} /tmp/savedsession example.db www.example.com 21") + exit +end + +ws_directory = ARGV.shift +db_file = ARGV.shift +target = ARGV.shift || nil +start_id = ARGV.shift.to_i || 1 + +# check if we have what we need... +if File.exists?(ws_directory+ File::SEPARATOR) == false then + $stderr.puts("ERROR: Can't find webscarab directory #{ws_directory}.") + exit +end + +if File.file?(db_file) == false then + $stderr.puts("ERROR: Can't find sqlite3 database file #{db_file}.") + exit +end + +# Prepare the database +puts("Opening database file: #{db_file}") +database = SQLite3::Database.new(db_file) + +# Prepare the insert statement... +insert_statement = database.prepare("INSERT INTO requests(host,port,ssl,meth,path,headers,query,body,respcode,resphead,response,created) VALUES(:host,:port,:ssl,:meth,:path,:headers,:query,:body,:respcode,:resphead,:response,:created)"); + +# target hash -> Resolving dns names is soooo slow, I don't know why. So we use the +# following hash as a "micro hosts", so we don't have to call getaddress each time... +target_ips = {} + +# Try to open the conversationlog file +File.open("#{ws_directory+File::SEPARATOR}conversationlog", "r") do |log| + + # regulare expressions to extract the stuff that we really need + # i know that the url stuff can be handeled in one request but + # i am toooo lazy... + regex_conversation = /^### Conversation : (\d+)/ + regex_datetime = /^WHEN: (\d+)/ + regex_method = /^METHOD: (\S+)/ + regex_status = /^STATUS: (\d\d\d)/ + regex_url = /^URL: (http|https)?:\/\/(\S+):(\d+)\/([^\?]*)\?*(\S*)/ + + while line = log.gets + if line =~ regex_conversation then + conversation_id = regex_conversation.match(line)[1] + next if conversation_id.to_i < start_id + + # we don't care about scripts, commets + while (line =~ regex_datetime) == nil + line = log.gets + end + + # Add a dot to the timestring so we can convert it more easily + date_time = regex_datetime.match(line)[1] + date_time = Time.at(date_time.insert(-4, '.').to_f) + + method = regex_method.match(log.gets)[1] + + # we don't care about COOKIES + while (line =~ regex_status) == nil + line = log.gets + end + status = regex_status.match(line)[1] + + url_matcher = regex_url.match(log.gets) + + puts "Processing (#{conversation_id}): #{url_matcher[0]}" + + ssl = url_matcher[1] == "https" + host_name = url_matcher[2] + port = url_matcher[3] + path = url_matcher[4].chomp + query = url_matcher[5] + + if host_name.match("#{target}$").nil? == true then + puts("Not the selected target, skipping...") + next + end + + if(target_ips.has_key?(host_name)) then + host = target_ips[host_name] + else + ip = Resolv.getaddress(host_name) + target_ips[host_name] = ip + host = ip + end + + # set the parameters in the insert query + insert_statement.bind_param("host", host) + insert_statement.bind_param("port", port) + insert_statement.bind_param("ssl", ssl) + insert_statement.bind_param("meth", method) + insert_statement.bind_param("path", path) + insert_statement.bind_param("query", query) + insert_statement.bind_param("respcode", status) + insert_statement.bind_param("created", date_time) + insert_statement.bind_param("respcode", status) + + #Open the files with the requests and the responses... + request_filename = "#{ws_directory+File::SEPARATOR}conversations#{File::SEPARATOR+conversation_id}-request" + puts("Reading #{request_filename}") + request_file = File.open(request_filename, "rb") + + # Analyse the request + request_header = "" + request_file.gets # we don't need the return code... + while(request_line = request_file.gets) do + request_header += request_line + break if request_line == "\r\n" + end + + + request_body = "" + while(request_line = request_file.gets) do + request_body += request_line + end + + insert_statement.bind_param("headers", request_header) + insert_statement.bind_param("body", request_body) + + request_file.close() + + response_filename = "#{ws_directory+File::SEPARATOR}conversations#{File::SEPARATOR+conversation_id}-response" + puts("Reading #{response_filename}") + response_file = File.open("#{ws_directory+File::SEPARATOR}conversations#{File::SEPARATOR+conversation_id}-response", "rb") + + # scip the first line + response_file.gets + + # Analyse the response + response_header = "" + while(response_line = response_file.gets) do + response_header += response_line + break if response_line == "\r\n" + end + + response_body = response_file.read + + insert_statement.bind_param("resphead", response_header) + insert_statement.bind_param("response", response_body) + + response_file.close() + + insert_statement.execute() + end + end +end + + + +