146 lines
3.6 KiB
Ruby
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
|