From a14fe4ba0a9bc177f51461967bbc95ec7fe633f9 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Tue, 26 Jul 2011 18:35:46 +0000 Subject: [PATCH] Issue 384: First draft of XssRays (admin UI): extjs UI git-svn-id: https://beef.googlecode.com/svn/trunk@1113 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9 --- .../admin_ui/controllers/panel/index.html | 1 + .../admin_ui/controllers/xssrays/xssrays.rb | 113 ++++++++++++++++++ extensions/admin_ui/media/css/base.css | 4 + .../admin_ui/media/images/icons/xssrays.png | Bin 0 -> 865 bytes .../media/javascript/ui/panel/ZombieTab.js | 3 +- .../ui/panel/tabs/ZombieTabXssRays.js | 109 +++++++++++++++++ .../javascript/ui/panel/zombiesTreeList.js | 24 +++- 7 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 extensions/admin_ui/controllers/xssrays/xssrays.rb create mode 100644 extensions/admin_ui/media/images/icons/xssrays.png create mode 100644 extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js diff --git a/extensions/admin_ui/controllers/panel/index.html b/extensions/admin_ui/controllers/panel/index.html index 7957e2dc5..a92072e84 100644 --- a/extensions/admin_ui/controllers/panel/index.html +++ b/extensions/admin_ui/controllers/panel/index.html @@ -20,6 +20,7 @@ <%= script_tag 'ui/panel/tabs/ZombieTabLogs.js' %> <%= script_tag 'ui/panel/tabs/ZombieTabCommands.js' %> <%= script_tag 'ui/panel/tabs/ZombieTabRequester.js' %> + <%= script_tag 'ui/panel/tabs/ZombieTabXssRays.js' %> <%= script_tag 'ui/panel/PanelViewer.js' %> <%= script_tag 'ui/panel/DataGrid.js' %> diff --git a/extensions/admin_ui/controllers/xssrays/xssrays.rb b/extensions/admin_ui/controllers/xssrays/xssrays.rb new file mode 100644 index 000000000..4b886a495 --- /dev/null +++ b/extensions/admin_ui/controllers/xssrays/xssrays.rb @@ -0,0 +1,113 @@ +# +# Copyright 2011 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +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 + + def initialize + super({ + 'paths' => { + '/set_scan_target' => method(:set_scan_target), + '/zombie.json' => method(:get_xssrays_logs), + '/rays' => method(:parse_rays) + } + }) + end + + # called by the UI when rendering xssrays_details table content in the XssRays zombie tab + def get_xssrays_logs + # validate nonce + nonce = @params['nonce'] || nil + raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil? + raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce + + # validate that the hooked browser's session has been sent + zombie_session = @params['zombie_session'] || nil + raise WEBrick::HTTPStatus::BadRequest, "Zombie session is nil" if zombie_session.nil? + + # validate that the hooked browser exists in the db + zombie = Z.first(:session => zombie_session) || nil + raise WEBrick::HTTPStatus::BadRequest, "Invalid hooked browser session" if zombie.nil? + + logs = [] + BeEF::Core::Models::Xssraysdetail.all(:hooked_browser_id => zombie.id).each{|log| + logs << { + 'id' => log.id, + 'vector_method' => log.vector_method, + 'vector_name' => log.vector_name, + 'vector_poc' => log.vector_poc + } + } + + @body = {'success' => 'true', 'logs' => logs}.to_json + end + + # called by the UI. needed to pass the hooked browser ID/session and store a new scan in the DB + def set_scan_target + hooked_browser = HB.first(:session => @params['hb_id'].to_s) + if(hooked_browser != nil) + hooked_browser.update(:start_xssrays => true) + + xssrays_scan = XS.new( + :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 + ) + 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 + + # parse incoming rays: rays are veryfied XSS, as the attack vector is calling back BeEF when executed. + def parse_rays + print_debug("[XSSRAYS] Received ray: \n #{@params.to_s}") + + hooked_browser = HB.first(:session => @params['hbsess'].to_s) + + if(hooked_browser != nil) + + xssrays_scan = XS.first(:id => @params['raysscanid']) + + if(xssrays_scan != nil) + xssrays_detail = XD.new( + :hooked_browser_id => hooked_browser.id, + :vector_name => @params['name'], + :vector_method => @params['method'], + :vector_poc => @params['poc'], + :scan_id => xssrays_scan.id + ) + xssrays_detail.save + end + + print_info("[XSSRAYS] Received ray from HB with ip [#{hooked_browser.ip.to_s}], hooked on domain [#{hooked_browser.domain.to_s}]") + end + end +end + +end +end +end +end \ No newline at end of file diff --git a/extensions/admin_ui/media/css/base.css b/extensions/admin_ui/media/css/base.css index 38a37c471..621f9e541 100644 --- a/extensions/admin_ui/media/css/base.css +++ b/extensions/admin_ui/media/css/base.css @@ -74,6 +74,10 @@ background-image: url(../images/icons/proxy.gif); } +.zombie-tree-ctxMenu-xssrays { + background-image: url(../images/icons/xssrays.png); +} + .x-tree-node-leaf .x-tree-node-icon { width: 13px; height: 13px; diff --git a/extensions/admin_ui/media/images/icons/xssrays.png b/extensions/admin_ui/media/images/icons/xssrays.png new file mode 100644 index 0000000000000000000000000000000000000000..1e794cde97560d33c9925b1fa12a1cbdad8f9af1 GIT binary patch literal 865 zcmV-n1D^beP)Hkd z2#QkiAQlvnfQW)fZazWr?xlr7uQh@fd+^pCY&|OK(L)p>9z;-3@ZbX!1Q8z)52=Zo zhk5UIW^A^J>7gAMb~2gyX6FCD`Ni$&sU~7E_+QZ~Dp)~?Pu11c-^iy3zaPZS4F||} zJIIxl1xcxk3jkGRTgWmP>gw1hk=@t`Nt^Af-|v5mfFH%J&!@rVB`6LDyc!q)Nsh~8yfhx z5CRe>C+w%f$@6nicXz4kv;vt7Xb6@?jqUG)0bx2@ml&c1VplArD=G|rt zTQ04sff78UoKUi+X$)p=X<_@(=Y#0>wjLuMA3@>Ho}P4P6v33LDzNqRFi1`^cpM}& zD%s(!Ezpw5KVXO>sp!aJXZaf5+|-jvXzbY05d%?o{)q|5ghB;5gi|yoNkwO8!6gu| z@!dQ2kzHC}4@sm`0g3g_qETI~gM(moyY&&7XI`&P3;H_7$DhwIFOP5}nwvT!Ek{~Z zA~6jH!*exEpiXT4{W>@Sl5HOz*7HaShe=BpAUmD##^Wg(FEBU9057Rx9~l8tdpqZn z5)SVUA=`(BI4HMH)Kv^Q6_}lc2$K14+@p?joe9d7kyGVeUEmlSE26^P(h?K$4tF#E zc5@W5baa5Fx0hq&+FFo|-Q6IWOdLS0rWK)YV16F%mX~>NLn|xrb76t~`7wM!*p+0n zfe{&iFOYvawzlR`_x2!#&yh-1EEb6D>=eCW*1kT_@c(om0Fv3vFU`a1D!j%*WiHoe zk-*BqVDNj?>wO=bngaFV;h!H!$!Z1X%nX>^?jQJ`ePA#W1e{hQ5ziB@N%HUzw7eC2 rDFTnBtgQ|Bh|K0M2sBClUjhsOTv*ltrw{}y00000NkvXXu0mjf)R}_R literal 0 HcmV?d00001 diff --git a/extensions/admin_ui/media/javascript/ui/panel/ZombieTab.js b/extensions/admin_ui/media/javascript/ui/panel/ZombieTab.js index 7a7bce21a..2693de5c2 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/ZombieTab.js +++ b/extensions/admin_ui/media/javascript/ui/panel/ZombieTab.js @@ -19,6 +19,7 @@ ZombieTab = function(zombie) { log_tab = new ZombieTab_LogTab(zombie); commands_tab = new ZombieTab_Commands(zombie); requester_tab = new ZombieTab_Requester(zombie); + xssrays_tab = new ZombieTab_XssRaysTab(zombie); //------------------------------------------- ZombieTab.superclass.constructor.call(this, { @@ -32,7 +33,7 @@ ZombieTab = function(zombie) { forceFit: true, type: 'fit' }, - items:[main_tab, log_tab, commands_tab, requester_tab] + items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab] }); }; diff --git a/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js new file mode 100644 index 000000000..37f6e05e6 --- /dev/null +++ b/extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js @@ -0,0 +1,109 @@ +// +// Copyright 2011 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/* + * The XssRays Tab panel for the selected zombie. + */ + +//TODO: fix positioning issues, probably because we are not creating a nested (fucking) panel +ZombieTab_XssRaysTab = function(zombie) { + + var commands_statusbar = new Beef_StatusBar('xssrays-bbar-zombie-'+zombie.session); + + var req_pagesize = 30; + + var xssrays_logs_store = new Ext.ux.data.PagingJsonStore({ + storeId: 'xssrays-logs-store-zombie-' + zombie.session, + url: '/ui/xssrays/zombie.json', + remoteSort: false, + autoDestroy: true, + autoLoad: false, + root: 'logs', + + fields: ['id', 'vector_method', 'vector_name', 'vector_poc'], + sortInfo: {field: 'id', direction: 'DESC'}, + + baseParams: { + nonce: Ext.get("nonce").dom.value, + zombie_session: zombie.session + } + }); + + var xssrays_logs_bbar = new Ext.PagingToolbar({ + pageSize: req_pagesize, + store: xssrays_logs_store, + displayInfo: true, + displayMsg: 'Displaying history {0} - {1} of {2}', + emptyMsg: 'No history to display' + }); + + var xssrays_logs_grid = new Ext.grid.GridPanel({ + id: 'xssrays-logs-grid-zombie-' + zombie.session, + store: xssrays_logs_store, + bbar: xssrays_logs_bbar, + border: false, + loadMask: {msg:'Loading History...'}, + + viewConfig: { + forceFit:true + }, + + view: new Ext.grid.GridView({ + forceFit: true, + emptyText: "No History", + enableRowBody:true + }), + + columns: [ + {header: 'Id', width: 10, sortable: true, dataIndex: 'id', hidden:true}, + {header: 'Vector Method', width: 30, sortable: true, dataIndex: 'vector_method'}, + {header: 'Vector Name', width: 40, sortable: true, dataIndex: 'vector_name'}, + {header: 'Vector PoC', sortable: true, dataIndex: 'vector_poc'} + ], + + listeners: { + afterrender: function(datagrid) { + datagrid.store.reload({params:{start:0,limit:req_pagesize, sort: "date", dir:"DESC"}}); + } + } + }); + + var xssrays_logs_panel = new Ext.Panel({ + id: 'xssrays-logs-panel-zombie-'+zombie.session, + title: 'Logs', + items:[xssrays_logs_grid], + layout: 'fit', + + listeners: { + activate: function(xssrays_logs_panel) { + xssrays_logs_panel.items.items[0].store.reload(); + } + } + }); + + ZombieTab_XssRaysTab.superclass.constructor.call(this, { + id: 'xssrays-log-tab-'+zombie.session, + title: 'XssRays', + activeTab: 0, + viewConfig: { + forceFit: true, + type: 'fit' + }, + items: [xssrays_logs_panel], + bbar: commands_statusbar + }); +}; + +Ext.extend(ZombieTab_XssRaysTab, Ext.Panel, {} ); \ No newline at end of file diff --git a/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js b/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js index 502b6066c..7383e20c5 100644 --- a/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js +++ b/extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js @@ -76,20 +76,32 @@ Ext.extend(zombiesTreeList, Ext.tree.TreePanel, { //add a context menu that will contain common action shortcuts for HBs contextMenu: new Ext.menu.Menu({ items: [{ - id: 'use_as_proxy', - text: 'Use as Proxy', - iconCls: 'zombie-tree-ctxMenu-proxy' - } + id: 'use_as_proxy', + text: 'Use as Proxy', + iconCls: 'zombie-tree-ctxMenu-proxy' + },{ + id: 'xssrays_hooked_domain', + text: 'Launch XssRays on Hooked Homain', + iconCls: 'zombie-tree-ctxMenu-xssrays' + } + ], listeners: { itemclick: function(item, object) { + var hb_id = this.contextNode.id.split('zombie-online-')[1]; switch (item.id) { case 'use_as_proxy': - var hb_id = this.contextNode.id.split('zombie-online-')[1]; Ext.Ajax.request({ url: '/ui/proxy/setTargetZombie', method: 'POST', - params: 'hb_id=' + hb_id //, + params: 'hb_id=' + escape(hb_id) + }); + break; + case 'xssrays_hooked_domain': + Ext.Ajax.request({ + url: '/ui/xssrays/set_scan_target', + method: 'POST', + params: 'hb_id=' + escape(hb_id) }); break; }