Files
beef/extensions/proxy/handlers/zombie/handler.rb
bcoles@gmail.com 21d5164d4d Response Headers is now the default accordion panel displayed (rather
than the Request panel) when viewing requester HTTP response details

The requester history panel now automatically refreshes upon display

Changed processed status from 'false' to 'waiting' and 'true' to 
'complete' in the requester

Fixes Issue 459



git-svn-id: https://beef.googlecode.com/svn/trunk@1226 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9
2011-08-21 03:29:42 +00:00

121 lines
5.0 KiB
Ruby

#
# Copyright 2011 Wade Alcorn wade@bindshell.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module BeEF
module Extension
module Proxy
module Handlers
module Zombie
class Handler
attr_reader :guard
@response = nil
H = BeEF::Core::Models::Http
# This function will forward requests to the target and
# the browser will perform the request. Then the results
# will be sent back.
def forward_request(hooked_browser_id, req, res)
# validate that the raw request is correct and can be used
req_parts = req.to_s.split(/ |\n/) # break up the request
verb = req_parts[0]
raise 'Only HEAD, GET, POST, OPTIONS, PUT or DELETE requests are supported' if not BeEF::Filters.is_valid_verb?(verb) #check verb
uri = req_parts[1]
raise 'Invalid URI' if not BeEF::Filters.is_valid_url?(uri) #check uri
version = req_parts[2]
raise 'Invalid HTTP version' if not BeEF::Filters.is_valid_http_version?(version) # check http version - HTTP/1.0
host_str = req_parts[3]
raise 'Invalid HTTP host header' if not BeEF::Filters.is_valid_host_str?(host_str) # check host string - Host:
host = req_parts[4]
host_parts = host.split(/:/)
hostname = host_parts[0]
raise 'Invalid hostname' if not BeEF::Filters.is_valid_hostname?(hostname) #check the target hostname
hostport = host_parts[1] || nil
if !hostport.nil?
raise 'Invalid hostport' if not BeEF::Filters.nums_only?(hostport) #check the target hostport
end
# Saves the new HTTP request to the db for processing by browser.
# IDs are created and incremented automatically by DataMapper.
http = H.new(
:request => req,
:method => req.request_method.to_s,
:domain => req.host,
:port => req.port,
:path => req.path.to_s,
:request_date => Time.now,
:hooked_browser_id => hooked_browser_id
)
http.save
# Starts a new thread scoped to this Handler instance, in order to minimize performance degradation
# while waiting for the HTTP response to be stored in the db.
print_info("[PROXY] Thread started in order to process request ##{http.id} to [#{req.path.to_s}] on domain [#{req.host}:#{req.port}]")
@response_thread = Thread.new do
while H.first(:id => http.id).has_ran != "complete"
sleep 0.5
end
@response = H.first(:id => http.id)
end
@response_thread.join
print_info("[PROXY] Response for request ##{http.id} to [#{req.path.to_s}] on domain [#{req.host}:#{req.port}] correctly processed")
res.body = @response['response_data']
# set the original response status code
res.status = @response['response_status_code']
headers = @response['response_headers']
#print_debug("====== original HTTP response headers =======\n#{headers}")
# The following is needed to forward back some of the original HTTP response headers obtained via XHR calls.
# Original XHR response headers are stored in extension_requester_http table (response_headers column),
# but we are forwarding back only some of them (Server, X-.. - like X-Powered-By -, Content-Type, ... ).
# Some of the original response headers need to be removed, like encoding and cache related: for example
# about encoding, the original response headers says that the content-length is 1000 as the response is gzipped,
# but the final content-length forwarded back by the proxy is clearly bigger. Date header follows the same way.
headers_hash = Hash.new
if(res.status != -1 && res.status != 0)
headers.each_line do |line|
# stripping the Encoding, Cache and other headers
if line.split(': ')[0] != "Content-Encoding" &&
line.split(': ')[0] != "Content-Length" &&
line.split(': ')[0] != "Keep-Alive" &&
line.split(': ')[0] != "Cache-Control" &&
line.split(': ')[0] != "Vary" &&
line.split(': ')[0] != "Pragma" &&
line.split(': ')[0] != "Connection" &&
line.split(': ')[0] != "Expires" &&
line.split(': ')[0] != "Accept-Ranges" &&
line.split(': ')[0] != "Date"
headers_hash[line.split(': ')[0]] = line.split(': ')[1].gsub!(/[\n]+/,"")
end
end
# note: override_headers is a (new) method of WebRick::HTTPResponse (the BeEF patch one: core\ruby\patches\webrick\httpresponse.rb)
res.override_headers(headers_hash)
end
res
end
end
end
end
end
end
end