2008-12-08 03:47:07 +00:00
#!/usr/bin/env ruby
2010-05-03 17:13:09 +00:00
#
# $Id$
# $Revision$
#
2008-12-08 03:47:07 +00:00
# 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 <spinbad.security () googlemail ! com>
require 'resolv'
require 'sqlite3'
puts " --- WMAP WebScarab Session Importer --------------------------------------------- "
puts
2010-05-03 17:13:09 +00:00
if ARGV . length < 2
2008-12-08 03:47:07 +00:00
$stderr . puts ( " Usage: #{ File . basename ( $0 ) } wescarabdirectory sqlite3database [target] [startrequest] " )
$stderr . puts
$stderr . puts ( " webscarabdirectory \t The directory where you stored the webscarab session " )
$stderr . puts ( " sqlite3database \t \t The name of the database file " )
$stderr . puts ( " target \t \t \t The target (host or domain) you want to add to the database " )
$stderr . puts ( " startrequest \t The 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
2010-11-05 00:06:31 +00:00
File . open ( " #{ ws_directory + File :: SEPARATOR } conversationlog " , " rb " ) do | log |
2008-12-08 03:47:07 +00:00
# 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...
2010-05-03 17:13:09 +00:00
regex_conversation = / ^ # # # Conversation : ( \ d+) /
2008-12-08 03:47:07 +00:00
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
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
# we don't care about scripts, commets
2010-05-03 17:13:09 +00:00
while ( line =~ regex_datetime ) == nil
2008-12-08 03:47:07 +00:00
line = log . gets
end
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
# 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 )
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
method = regex_method . match ( log . gets ) [ 1 ]
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
# we don't care about COOKIES
while ( line =~ regex_status ) == nil
line = log . gets
end
status = regex_status . match ( line ) [ 1 ]
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
url_matcher = regex_url . match ( log . gets )
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
puts " Processing ( #{ conversation_id } ): #{ url_matcher [ 0 ] } "
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
ssl = url_matcher [ 1 ] == " https "
host_name = url_matcher [ 2 ]
port = url_matcher [ 3 ]
path = url_matcher [ 4 ] . chomp
2010-05-03 17:13:09 +00:00
query = url_matcher [ 5 ]
2008-12-08 03:47:07 +00:00
if host_name . match ( " #{ target } $ " ) . nil? == true then
puts ( " Not the selected target, skipping... " )
next
end
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
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
2010-05-03 17:13:09 +00:00
end
2008-12-08 03:47:07 +00:00
# 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 )
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
#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 } " )
2010-05-03 17:13:09 +00:00
request_file = File . open ( request_filename , " rb " )
2008-12-08 03:47:07 +00:00
# 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
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
request_body = " "
while ( request_line = request_file . gets ) do
request_body += request_line
end
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
insert_statement . bind_param ( " headers " , request_header )
insert_statement . bind_param ( " body " , request_body )
2010-05-03 17:13:09 +00:00
request_file . close ( )
2008-12-08 03:47:07 +00:00
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 " )
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
# scip the first line
response_file . gets
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
# Analyse the response
response_header = " "
while ( response_line = response_file . gets ) do
response_header += response_line
break if response_line == " \r \n "
end
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
response_body = response_file . read
2010-05-03 17:13:09 +00:00
2008-12-08 03:47:07 +00:00
insert_statement . bind_param ( " resphead " , response_header )
insert_statement . bind_param ( " response " , response_body )
2010-05-03 17:13:09 +00:00
response_file . close ( )
2008-12-08 03:47:07 +00:00
insert_statement . execute ( )
2010-05-03 17:13:09 +00:00
end
2008-12-08 03:47:07 +00:00
end
end