metasploit-framework/lib/msf/core/exploit/web.rb

146 lines
3.6 KiB
Ruby

# -*- coding: binary -*-
module Msf
###
#
# This module exposes methods that may be useful to exploits that deal with
# webservers.
#
###
module Exploit::Remote::Web
include Exploit::Remote::Tcp
include Exploit::Remote::HttpClient
# Default value for #web_payload_stub
WEB_PAYLOAD_STUB = '!payload!'
#
# Optional stub to be replaced with the exploit payload.
#
# Default stub is 'WEB_PAYLOAD_STUB'.
#
attr_accessor :web_payload_stub
# Creates an instance of a Telnet exploit module.
#
def initialize( info = {} )
super
register_options([
OptString.new( 'PATH', [ true, 'The path to the vulnerable script.', '/' ] ),
OptString.new( 'GET', [ false, "GET parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
OptString.new( 'POST', [ false, "POST parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
OptString.new( 'COOKIES', [ false, "Cookies to be sent with the request. ('foo=bar;vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
OptString.new( 'HEADERS', [ false, "Headers to be sent with the request. ('User-Agent=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
], self.class )
self.web_payload_stub = WEB_PAYLOAD_STUB
end
def path
Rex::Text.uri_encode( substitute_web_payload_stub( datastore['PATH'] ) )
end
def get
substitute_in_hash( parse_query( datastore['GET'] ) )
end
def post
substitute_in_hash( parse_query( datastore['POST'] ) )
end
def cookies
substitute_web_payload_stub( datastore['COOKIES'], ',;' )
end
def headers
substitute_in_hash( parse_query( datastore['HEADERS'] ) )
end
def method
post.empty? ? 'GET' : 'POST'
end
def check
path = datastore['PATH']
print_status "Checking #{path}"
response = send_request_raw( 'uri' => path )
return Exploit::CheckCode::Detected if response.code == 200
print_error "Server responded with #{response.code}"
Exploit::CheckCode::Unknown
end
def exploit
print_status "Sending HTTP request for #{path}"
res = perform_request
if res
print_status "The server responded with HTTP status code #{res.code}."
else
print_status 'The server did not respond to our request.'
end
handler
end
def tries
1
end
private
def perform_request
send_request_cgi({
'global' => true,
'uri' => path,
'method' => method,
'vars_get' => get,
'vars_post' => post,
'headers' => headers,
'cookie' => cookies
}, 10 )
end
#
# Converts a URI query string into a key=>value hash.
#
def parse_query( query, sep = '&' )
query = query.to_s
return {} if query.empty?
query.split( sep ).inject({}) do |h, part|
k, v = part.split( '=', 2 )
h[k.to_s] = v.to_s
h
end
end
#
# With what to replace 'WEB_PAYLOAD_STUB'.
#
# By default returns 'payload.encoded', override as needed.
#
def stub_value
payload.encoded
end
#
# Substitutes 'web_payload_stub' with the exploit payload.
#
def substitute_web_payload_stub( str, escape = '' )
value = stub_value
value = URI.encode( stub_value, escape ) if !escape.empty?
str.to_s.gsub( web_payload_stub, value )
end
def substitute_in_hash( hash )
hash.inject({}) do |h, (k, v)|
h[substitute_web_payload_stub( k )] = substitute_web_payload_stub( v )
h
end
end
end
end