From 1cf1354bc6193bab6c0e55db0100018a25ccc70e Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Wed, 20 Feb 2019 09:39:48 +0000 Subject: [PATCH] Replace /ui/xssrays controller with REST API - #1389 #1682 --- .../ui/panel/tabs/ZombieTabXssRays.js | 9 +- .../javascript/ui/panel/zombiesTreeList.js | 5 +- extensions/xssrays/controllers/xssrays.rb | 95 ------------------- extensions/xssrays/rest/xssrays.rb | 62 +++++++++--- 4 files changed, 57 insertions(+), 114 deletions(-) delete mode 100644 extensions/xssrays/controllers/xssrays.rb diff --git a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js index a2b3e0236..babe7a182 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js +++ b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js @@ -91,7 +91,7 @@ ZombieTab_XssRaysTab = function(zombie) { var form = new Ext.FormPanel({ title: 'Scan settings', id: 'xssrays-config-form-zombie'+zombie.session, - url: '<%= @base_path %>/xssrays/createNewScan', + url: '/api/xssrays/scan/' + zombie.session + '?token=' + token, labelWidth: 230, border: false, padding: '3px 5px 0 5px', @@ -106,6 +106,7 @@ ZombieTab_XssRaysTab = function(zombie) { padding: '10px 5px 0 5px' },{ xtype:'checkbox', + id:'cross_domain', fieldLabel: 'Cross-domain (check for XSS on cross-domain resources)', name: 'cross_domain', checked: true @@ -116,12 +117,10 @@ ZombieTab_XssRaysTab = function(zombie) { handler: function() { var form = Ext.getCmp('xssrays-config-form-zombie'+zombie.session).getForm(); - bar.update_sending('Saving settings and ready to start XssRays... ' + zombie.ip + '...'); - + bar.update_sending('Starting XssRays on ' + zombie.ip + ' ...'); form.submit({ params: { - nonce: Ext.get("nonce").dom.value, - zombie_session: zombie.session + cross_domain: document.getElementById('cross_domain').checked }, success: function() { bar.update_sent("Scan settings saved for hooked browser [" + zombie.ip + "]. XssRays will be added to victim DOM on next polling."); diff --git a/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js b/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js index 4554eca30..173fee2d6 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js +++ b/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js @@ -111,9 +111,8 @@ Ext.extend(zombiesTreeList, Ext.tree.TreePanel, { break; case 'xssrays_hooked_domain': Ext.Ajax.request({ - url: '<%= @base_path %>/xssrays/set_scan_target', - method: 'POST', - params: 'hb_id=' + escape(hb_id) + url: '/api/xssrays/scan/' + escape(hb_id) + '?token=' + beefwui.get_rest_token(), + method: 'POST' }); break; case 'rtc_caller': diff --git a/extensions/xssrays/controllers/xssrays.rb b/extensions/xssrays/controllers/xssrays.rb deleted file mode 100644 index bf6f967e0..000000000 --- a/extensions/xssrays/controllers/xssrays.rb +++ /dev/null @@ -1,95 +0,0 @@ -# -# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net -# Browser Exploitation Framework (BeEF) - http://beefproject.com -# See the file 'doc/COPYING' for copying permission -# -module BeEF -module Extension -module AdminUI -module Controllers - -class Xssrays < BeEF::Extension::AdminUI::HttpController - - HB = BeEF::Core::Models::HookedBrowser - XS = BeEF::Core::Models::Xssraysscan - XD = BeEF::Core::Models::Xssraysdetail - - # default values from config file, when XssRays is started right-clicking the zombie in the HB tree - CLEAN_TIMEOUT = BeEF::Core::Configuration.instance.get("beef.extension.xssrays.clean_timeout") - CROSS_DOMAIN = BeEF::Core::Configuration.instance.get("beef.extension.xssrays.cross_domain") - - def initialize - super({ - 'paths' => { - '/set_scan_target' => method(:set_scan_target), - '/createNewScan' => method(:create_new_scan) - } - }) - end - - # called by the UI. needed to pass the hooked browser ID/session and store a new scan in the DB. - # This is called when right-clicking the hooked browser from the tree. - # Default config options are read from config.yaml - def set_scan_target - hooked_browser = HB.first(:session => @params['hb_id'].to_s) - - if hooked_browser.nil? - print_error "[XSSRAYS] Invalid hooked browser ID" - return - end - - xssrays_scan = XS.new( - :hooked_browser_id => hooked_browser.id, - :scan_start => Time.now, - :domain => hooked_browser.domain, - :cross_domain => CROSS_DOMAIN, #check also cross-domain URIs found by the spider - :clean_timeout => CLEAN_TIMEOUT #check also cross-domain URIs found by the spider - ) - xssrays_scan.save - - print_info("[XSSRAYS] Starting XSSRays [ip:#{hooked_browser.ip}], hooked domain [#{hooked_browser.domain}]") - end - - # called by the UI, in the XssRays zombie tab - # Needed if we want to start a scan overriding default scan parameters without rebooting BeEF - def create_new_scan - hooked_browser = HB.first(:session => @params['zombie_session'].to_s) - - if hooked_browser.nil? - print_error "[XSSRAYS] Invalid hooked browser ID" - return - end - - # set Cross-domain settings - cross_domain = @params['cross_domain'] - if cross_domain.nil? or cross_domain.empty? - cross_domain = CROSS_DOMAIN - else - cross_domain = true - end - print_debug("[XSSRAYS] Setting scan cross_domain to #{cross_domain}") - - # set Clean-timeout settings - clean_timeout = @params['clean_timeout'] - if clean_timeout.nil? or clean_timeout.empty? - clean_timeout = CLEAN_TIMEOUT - end - print_debug("[XSSRAYS] Setting scan clean_timeout to #{clean_timeout}") - - xssrays_scan = XS.new( - :hooked_browser_id => hooked_browser.id, - :scan_start => Time.now, - :domain => hooked_browser.domain, - :cross_domain => cross_domain, #check also cross-domain URIs found by the crawler - :clean_timeout => clean_timeout #how long to wait before removing the iFrames from the DOM (5000ms default) - ) - xssrays_scan.save - - print_info("[XSSRAYS] Starting XSSRays [ip:#{hooked_browser.ip}], hooked domain [#{hooked_browser.domain}]") - end -end - -end -end -end -end diff --git a/extensions/xssrays/rest/xssrays.rb b/extensions/xssrays/rest/xssrays.rb index f11409017..59f5c9d3a 100644 --- a/extensions/xssrays/rest/xssrays.rb +++ b/extensions/xssrays/rest/xssrays.rb @@ -7,23 +7,24 @@ module BeEF module Extension module Xssrays - # This class handles the routing of RESTful API requests for XssRays + # This class handles the routing of RESTful API requests for XSSRays class XssraysRest < BeEF::Core::Router::Router - HB = BeEF::Core::Models::HookedBrowser - XS = BeEF::Core::Models::Xssraysscan - XD = BeEF::Core::Models::Xssraysdetail - # Filters out bad requests before performing any routing before do config = BeEF::Core::Configuration.instance - @nh = BeEF::Core::Models::NetworkHost - @ns = BeEF::Core::Models::NetworkService # Require a valid API token from a valid IP address halt 401 unless params[:token] == config.get('beef.api_token') halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip) + CLEAN_TIMEOUT = config.get("beef.extension.xssrays.clean_timeout") || 3_000 + CROSS_DOMAIN = config.get("beef.extension.xssrays.cross_domain") || true + + HB = BeEF::Core::Models::HookedBrowser + XS = BeEF::Core::Models::Xssraysscan + XD = BeEF::Core::Models::Xssraysdetail + headers 'Content-Type' => 'application/json; charset=UTF-8', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', @@ -117,19 +118,58 @@ module BeEF end # Starts a new scan on the specified zombie ID -=begin post '/scan/:id' do begin - # TODO + id = params[:id] + + hooked_browser = HB.first(:session => id, :unique => true, :order => [:id.asc]) + + if hooked_browser.nil? + print_error "[XSSRAYS] Invalid hooked browser ID" + return + end + + # set Cross-domain settings + cross_domain = params[:cross_domain].to_s + if cross_domain == '' + cross_domain = CROSS_DOMAIN + elsif cross_domain == 'false' + cross_domain = false + else + cross_domain = true + end + + # set clean timeout settings + clean_timeout = params[:clean_timeout].to_s + if clean_timeout == '' || !Filters.alphanums_only?(clean_timeout) + clean_timeout = CLEAN_TIMEOUT + end + + xssrays_scan = XS.new( + :hooked_browser_id => hooked_browser.id, + :scan_start => Time.now, + :domain => hooked_browser.domain, + # check also cross-domain URIs found by the crawler + :cross_domain => cross_domain, + # how long to wait before removing the iFrames from the DOM (5000ms default) + :clean_timeout => clean_timeout + ) + xssrays_scan.save + + print_info("[XSSRays] Starting XSSRays [ip:#{hooked_browser.ip}], hooked domain [#{hooked_browser.domain}], cross-domain: #{cross_domain}, clean timeout: #{clean_timeout}") + + result = scan2hash(xssrays_scan) + print_debug "[XSSRays] New scan: #{result}" + + #result.to_json rescue InvalidParamError => e print_error e.message halt 400 rescue StandardError => e - print_error "Internal error while retrieving host with id #{id} (#{e.message})" + print_error "Internal error while creating XSSRays scan on zombie with id #{id} (#{e.message})" halt 500 end end -=end private