2009-10-11 22:52:54 +00:00
##
# $Id: wmap_error_sql_injection.rb 6479 2009-04-13 14:33:26Z kris $
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'rex/proto/http'
require 'msf/core'
class Metasploit3 < Msf :: Auxiliary
include Msf :: Exploit :: Remote :: HttpClient
include Msf :: Auxiliary :: WMAPScanUniqueQuery
include Msf :: Auxiliary :: Scanner
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'HTTP Error Based SQL Injection Scanner' ,
'Description' = > %q{
This module identifies the existence of Error Based SQL injection issues. Still requires alot of work
} ,
'Author' = > [ 'et [at] cyberspace.org' ] ,
'License' = > BSD_LICENSE ,
'Version' = > '$Revision: 6479 $' ) )
register_options (
[
OptString . new ( 'METHOD' , [ true , " HTTP Method " , 'GET' ] ) ,
OptString . new ( 'PATH' , [ true , " The path/file to test SQL injection " , '/default.aspx' ] ) ,
OptString . new ( 'QUERY' , [ false , " HTTP URI Query " , '' ] ) ,
2009-10-11 23:07:34 +00:00
OptString . new ( 'BODY' , [ false , " HTTP Body Data " , '' ] ) ,
2009-10-11 22:52:54 +00:00
OptString . new ( 'COOKIE' , [ false , " HTTP Cookies " , '' ] )
] , self . class )
end
def run_host ( ip )
gvars = nil
pvars = nil
cvars = nil
sqlinj = [
[ " ' " , 'Single quote' ] ,
[ " ') " , 'Single quote and parenthesis' ] ,
[ " \" " , 'Double quote' ]
]
errorstr = [
[
" Unclosed quotation mark after the character string " ,
'MSSQL' ,
'string'
]
]
#
# Dealing with empty query/data and making them hashes.
#
if ! datastore [ 'QUERY' ] or datastore [ 'QUERY' ] . empty?
gvars = queryparse ( datastore [ 'QUERY' ] ) #Now its a Hash
else
gvars = nil
end
2009-10-11 23:07:34 +00:00
if ! datastore [ 'BODY' ] or datastore [ 'BODY' ] . empty?
datastore [ 'BODY' ] = nil
2009-10-11 22:52:54 +00:00
pvars = nil
else
2009-10-11 23:07:34 +00:00
pvars = queryparse ( datastore [ 'BODY' ] )
2009-10-11 22:52:54 +00:00
end
if ! datastore [ 'COOKIE' ] or datastore [ 'COOKIE' ] . empty?
datastore [ 'COOKIE' ] = nil
cvars = nil
else
cvars = queryparse ( datastore [ 'COOKIE' ] )
end
#
# Send normal request to check if error is generated
# (means the error is caused by other means)
#
#
begin
normalres = send_request_cgi ( {
'uri' = > datastore [ 'PATH' ] ,
'vars_get' = > gvars ,
'method' = > datastore [ 'METHOD' ] ,
'ctype' = > 'application/x-www-form-urlencoded' ,
'cookie' = > datastore [ 'COOKIE' ] ,
2009-10-11 23:07:34 +00:00
'data' = > datastore [ 'BODY' ]
2009-10-11 22:52:54 +00:00
} , 20 )
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout
rescue :: Timeout :: Error , :: Errno :: EPIPE
end
print_status ( " Normal request sent. " )
found = false
inje = nil
dbt = nil
injt = nil
if normalres
errorstr . each do | estr , dbtype , injtype |
if normalres . body . include? estr
found = true
inje = estr
dbt = dbtype
injt = injtype
end
end
if found
print_error ( " Error string appears in the normal response, unable to test " )
print_error ( " Error string: ' #{ inje } ' " )
print_error ( " DB TYPE: #{ dbt } , Error type ' #{ injt } ' " )
rep_id = wmap_base_report_id (
wmap_target_host ,
wmap_target_port ,
wmap_target_ssl
)
vul_id = wmap_report ( rep_id , 'ERROR' , 'ERROR_BASED_SQL_INJECTION' , " #{ datastore [ 'PATH' ] } " , " Unable to test as normal response contains error message without injecting anything parameter " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'ERROR_STRING' , " #{ inje } " , " Error message found #{ inje } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'DB_TYPE' , " #{ dbt } " , " Database type is #{ dbt } " )
return
end
else
print_status ( " No response " )
return
end
#
# Test URI Query parameters
#
found = false
if gvars
sqlinj . each do | istr , idesc |
if found
break
end
gvars . each do | key , value |
gvars = queryparse ( datastore [ 'QUERY' ] ) #Now its a Hash
print_status ( " - Testing query with #{ idesc } . Parameter #{ key } : " )
gvars [ key ] = gvars [ key ] + istr
begin
testres = send_request_cgi ( {
'uri' = > datastore [ 'PATH' ] ,
'vars_get' = > gvars ,
'method' = > datastore [ 'METHOD' ] ,
'ctype' = > 'application/x-www-form-urlencoded' ,
'cookie' = > datastore [ 'COOKIE' ] ,
2009-10-11 23:07:34 +00:00
'data' = > datastore [ 'BODY' ]
2009-10-11 22:52:54 +00:00
} , 20 )
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout
rescue :: Timeout :: Error , :: Errno :: EPIPE
end
if testres
errorstr . each do | estr , dbtype , injtype |
if testres . body . include? estr
found = true
inje = estr
dbt = dbtype
injt = injtype
end
end
if found
print_status ( " SQL Injection found. " )
print_status ( " Error string: ' #{ inje } ' Test Value: #{ istr } " )
print_status ( " Vuln query parameter: #{ key } DB TYPE: #{ dbt } , Error type ' #{ injt } ' " )
rep_id = wmap_base_report_id (
wmap_target_host ,
wmap_target_port ,
wmap_target_ssl
)
vul_id = wmap_report ( rep_id , 'VULNERABILITY' , 'ERROR_BASED_SQL_INJECTION' , " #{ datastore [ 'PATH' ] } " , " SQL Injection found (Error based) in #{ datastore [ 'PATH' ] } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'PARAMETER' , " #{ key } " , " Parameter vulnerable #{ key } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'LOCATION' , " QUERY " , " Parameter located in URI query. " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'INJECTION_TYPE' , " #{ injt } " , " Injection appears to be treated as a #{ injt } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'VALUE' , " #{ istr } " , " String injected using #{ idesc } [ #{ istr } ]. " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'ERROR_STRING' , " #{ inje } " , " Error message found #{ inje } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'DB_TYPE' , " #{ dbt } " , " Database type is #{ dbt } " )
break
end
else
print_error ( " No response " )
return
end
end
end
end
#
# Test DATA parameters
#
found = false
if pvars
sqlinj . each do | istr , idesc |
if found
break
end
pvars . each do | key , value |
2009-10-11 23:07:34 +00:00
pvars = queryparse ( datastore [ 'BODY' ] ) #Now its a Hash
2009-10-11 22:52:54 +00:00
print_status ( " - Testing data with #{ idesc } . Parameter #{ key } : " )
pvars [ key ] = pvars [ key ] + istr
pvarstr = " "
pvars . each do | tkey , tvalue |
if pvarstr
pvarstr << '&'
end
pvarstr << tkey + '=' + tvalue
end
begin
testres = send_request_cgi ( {
'uri' = > datastore [ 'PATH' ] ,
'vars_get' = > gvars ,
'method' = > datastore [ 'METHOD' ] ,
'ctype' = > 'application/x-www-form-urlencoded' ,
'cookie' = > datastore [ 'COOKIE' ] ,
'data' = > pvarstr
} , 20 )
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout
rescue :: Timeout :: Error , :: Errno :: EPIPE
end
if testres
errorstr . each do | estr , dbtype , injtype |
if testres . body . include? estr
found = true
inje = estr
dbt = dbtype
injt = injtype
end
end
if found
print_status ( " SQL Injection found. " )
print_status ( " Error string: ' #{ inje } ' Test Value: #{ istr } " )
print_status ( " Vuln data parameter: #{ key } DB TYPE: #{ dbt } , Error type ' #{ injt } ' " )
rep_id = wmap_base_report_id (
wmap_target_host ,
wmap_target_port ,
wmap_target_ssl
)
vul_id = wmap_report ( rep_id , 'VULNERABILITY' , 'ERROR_BASED_SQL_INJECTION' , " #{ datastore [ 'PATH' ] } " , " SQL Injection found (Error based) in #{ datastore [ 'PATH' ] } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'PARAMETER' , " #{ key } " , " Parameter vulnerable #{ key } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'LOCATION' , " DATA " , " Parameter located in request DATA (POST_DATA). " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'INJECTION_TYPE' , " #{ injt } " , " Injection appears to be treated as a #{ injt } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'VALUE' , " #{ istr } " , " String injected using #{ idesc } [ #{ istr } ]. " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'ERROR_STRING' , " #{ inje } " , " Error message found #{ inje } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'DB_TYPE' , " #{ dbt } " , " Database type is #{ dbt } " )
break
end
else
print_error ( " No response " )
return
end
end
end
end
#
# Test COOKIE parameters
#
found = false
if datastore [ 'COOKIE' ]
sqlinj . each do | istr , idesc |
if found
break
end
cvars . each do | key , value |
cvars = queryparse ( datastore [ 'COOKIE' ] ) #Now its a Hash
print_status ( " - Testing cookie with #{ idesc } . Parameter #{ key } : " )
cvars [ key ] = cvars [ key ] + istr
cvarstr = " "
cvars . each do | tkey , tvalue |
if cvarstr
cvarstr << ';'
end
cvarstr << tkey + '=' + tvalue
end
begin
testres = send_request_cgi ( {
'uri' = > datastore [ 'PATH' ] ,
'vars_get' = > gvars ,
'method' = > datastore [ 'METHOD' ] ,
'ctype' = > 'application/x-www-form-urlencoded' ,
'cookie' = > cvarstr ,
'data' = > datastore [ 'COOKIE' ]
} , 20 )
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout
rescue :: Timeout :: Error , :: Errno :: EPIPE
end
if testres
errorstr . each do | estr , dbtype , injtype |
if testres . body . include? estr
found = true
inje = estr
dbt = dbtype
injt = injtype
end
end
if found
print_status ( " SQL Injection found. " )
print_status ( " Error string: ' #{ inje } ' Test Value: #{ istr } " )
print_status ( " Vuln cookie parameter: #{ key } DB TYPE: #{ dbt } , Error type ' #{ injt } ' " )
rep_id = wmap_base_report_id (
wmap_target_host ,
wmap_target_port ,
wmap_target_ssl
)
vul_id = wmap_report ( rep_id , 'VULNERABILITY' , 'ERROR_BASED_SQL_INJECTION' , " #{ datastore [ 'PATH' ] } " , " SQL Injection found (Error based) in #{ datastore [ 'PATH' ] } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'PARAMETER' , " #{ key } " , " Parameter vulnerable #{ key } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'LOCATION' , " COOKIE " , " Parameter located in Cookies. " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'INJECTION_TYPE' , " #{ injt } " , " Injection appears to be treated as a #{ injt } . " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'VALUE' , " #{ istr } " , " String injected using #{ idesc } [ #{ istr } ]. " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'ERROR_STRING' , " #{ inje } " , " Error message found #{ inje } " )
wmap_report ( vul_id , 'ERROR_BASED_SQL_INJECTION' , 'DB_TYPE' , " #{ dbt } " , " Database type is #{ dbt } " )
break
end
else
print_error ( " No response " )
return
end
end
end
end
end
end