From 381d0838952fe414546e2700620561dc053c37da Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 3 Aug 2011 11:59:13 +0000 Subject: [PATCH] Issue 384: added XssRays "Scan config" tab, to configure crossDomain and cleanTimeout options. Added defaults to xssrays config file, also to prevent printing console.log statements if debug=false. Minor changes to xssrays_scan model. git-svn-id: https://beef.googlecode.com/svn/trunk@1164 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9 --- .../admin_ui/controllers/xssrays/xssrays.rb | 49 +++++++++++++- .../ui/panel/tabs/ZombieTabXssRays.js | 67 ++++++++++++++++++- extensions/xssrays/api/scan.rb | 12 ++-- extensions/xssrays/config.yaml | 3 + extensions/xssrays/handler.rb | 2 +- extensions/xssrays/models/xssraysscan.rb | 4 +- 6 files changed, 122 insertions(+), 15 deletions(-) diff --git a/extensions/admin_ui/controllers/xssrays/xssrays.rb b/extensions/admin_ui/controllers/xssrays/xssrays.rb index ef9a7a5b6..1341d0366 100644 --- a/extensions/admin_ui/controllers/xssrays/xssrays.rb +++ b/extensions/admin_ui/controllers/xssrays/xssrays.rb @@ -24,12 +24,17 @@ class Xssrays < BeEF::Extension::AdminUI::HttpController 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), '/zombie.json' => method(:get_xssrays_logs), - '/rays' => method(:parse_rays) + '/rays' => method(:parse_rays), + '/createNewScan' => method(:create_new_scan) } }) end @@ -71,7 +76,8 @@ class Xssrays < BeEF::Extension::AdminUI::HttpController str end - # called by the UI. needed to pass the hooked browser ID/session and store a new scan in the DB + # 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) @@ -79,7 +85,44 @@ class Xssrays < BeEF::Extension::AdminUI::HttpController :hooked_browser_id => hooked_browser.id, :scan_start => Time.now, :domain => hooked_browser.domain, - :same_origin => false #check also cross-domain URIs found by the spider + :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 on HB with ip [#{hooked_browser.ip.to_s}], hooked on domain [#{hooked_browser.domain.to_s}]") + end + + 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) + + # 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 spider + :clean_timeout => clean_timeout #check also cross-domain URIs found by the spider ) xssrays_scan.save 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 373a126c1..6fd317f14 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js +++ b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js @@ -24,6 +24,12 @@ ZombieTab_XssRaysTab = function(zombie) { var req_pagesize = 30; + var xssrays_config_panel = new Ext.Panel({ + id: 'xssrays-config-zombie-'+zombie.session, + title: 'Scan Config', + layout: 'fit' + }); + var xssrays_logs_store = new Ext.ux.data.PagingJsonStore({ storeId: 'xssrays-logs-store-zombie-' + zombie.session, url: '/ui/xssrays/zombie.json', @@ -93,6 +99,58 @@ ZombieTab_XssRaysTab = function(zombie) { } }); + function genScanSettingsPanel(zombie, bar, value) { + var form = new Ext.FormPanel({ + title: 'Scan settings', + id: 'xssrays-config-form-zombie'+zombie.session, + url: '/ui/xssrays/createNewScan', + labelWidth: 230, + border: false, + padding: '3px 5px 0 5px', + defaults: {width: 100}, + defaultType: 'textfield', + + items:[{ + fieldLabel: 'Clean Timeout (milliseconds before the injected iFrames are removed from the DOM)', + name: 'clean_timeout', + allowBlank:false, + value: 5000, + padding: '10px 5px 0 5px' + },{ + xtype:'checkbox', + fieldLabel: 'Cross-domain (check for XSS on cross-domain resources)', + name: 'cross_domain', + checked: true + }], + + buttons: [{ + text: 'Start Scan', + 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 + '...'); + + form.submit({ + params: { + nonce: Ext.get("nonce").dom.value, + zombie_session: zombie.session + }, + success: function() { + bar.update_sent("Scan settings saved for hooked browser [" + zombie.ip + "]. XssRays will be added to victim DOM on next polling."); + }, + failure: function() { + bar.update_fail("Error! Something went wrong saving scan settings."); + } + }); + } + }] + }); + + panel = Ext.getCmp('xssrays-config-zombie-'+zombie.session); + panel.setTitle('Scan Config'); + panel.add(form); + } + ZombieTab_XssRaysTab.superclass.constructor.call(this, { id: 'xssrays-log-tab-'+zombie.session, title: 'XssRays', @@ -101,8 +159,13 @@ ZombieTab_XssRaysTab = function(zombie) { forceFit: true, type: 'fit' }, - items: [xssrays_logs_panel], - bbar: commands_statusbar + items: [xssrays_logs_panel, xssrays_config_panel], + bbar: commands_statusbar, + listeners: { + afterrender : function(){ + genScanSettingsPanel(zombie, commands_statusbar); + } + } }); }; diff --git a/extensions/xssrays/api/scan.rb b/extensions/xssrays/api/scan.rb index 881da01a2..de66e5827 100644 --- a/extensions/xssrays/api/scan.rb +++ b/extensions/xssrays/api/scan.rb @@ -45,19 +45,17 @@ module BeEF # the URI of the HTTP controller where rays should come back if the vulnerability is verified beefurl = "#{BeEF::Core::Server.instance.url}/ui/xssrays/rays" - - #TODO: this must be configurable is some ways, through the web UI - cross_domain = true - timeout = 5000 - + cross_domain = xs.cross_domain + timeout = xs.clean_timeout + debug = BeEF::Core::Configuration.instance.get("beef.extension.xssrays.js_console_logs") @body << %Q{ beef.execute(function() { - beef.net.xssrays.startScan('#{xs.id}', '#{hb.session}', '#{beefurl}', #{cross_domain}, #{timeout}); + beef.net.xssrays.startScan('#{xs.id}', '#{hb.session}', '#{beefurl}', #{cross_domain}, #{timeout}, #{debug}); }); } - print_debug("[XSSRAYS] Adding XssRays to the DOM. Scan id [#{xs.id}], started at [#{xs.scan_start}]") + print_debug("[XSSRAYS] Adding XssRays to the DOM. Scan id [#{xs.id}], started at [#{xs.scan_start}], cross domain [#{cross_domain}], clean timeout [#{timeout}], js console debug [#{debug}].") end end diff --git a/extensions/xssrays/config.yaml b/extensions/xssrays/config.yaml index f53f9cc20..14e18a950 100644 --- a/extensions/xssrays/config.yaml +++ b/extensions/xssrays/config.yaml @@ -18,3 +18,6 @@ beef: xssrays: enable: true authors: ["antisnatchor"] + clean_timeout: 5000 + cross_domain: false + js_console_logs: true diff --git a/extensions/xssrays/handler.rb b/extensions/xssrays/handler.rb index 7984ccda4..d1df1b7b3 100644 --- a/extensions/xssrays/handler.rb +++ b/extensions/xssrays/handler.rb @@ -42,7 +42,7 @@ module Xssrays # validates the scan id scan_id = @data['cid'] || nil - raise WEBrick::HTTPStatus::BadRequest, "Scan id (cid) is null" if request_id.nil? + raise WEBrick::HTTPStatus::BadRequest, "Scan id (cid) is null" if scan_id.nil? # validates that a hooked browser with the beef_hook token exists in the db hooked_browser = HB.first(:session => beef_hook) || nil diff --git a/extensions/xssrays/models/xssraysscan.rb b/extensions/xssrays/models/xssraysscan.rb index 7e8bed920..a01ac1952 100644 --- a/extensions/xssrays/models/xssraysscan.rb +++ b/extensions/xssrays/models/xssraysscan.rb @@ -32,9 +32,9 @@ module Models property :scan_start, DateTime, :lazy => true property :scan_finish, DateTime, :lazy => true - #TODO: the domain field is never filled, because the hooked_browser table has the same field empty too... property :domain, Text, :lazy => true - property :same_origin, Text, :lazy => true + property :cross_domain, Text, :lazy => true + property :clean_timeout, Integer, :lazy => false property :is_started, Boolean, :lazy => false, :default => false property :is_finished, Boolean, :lazy => false, :default => false