Merge branch 'activerecord'

This commit is contained in:
root
2019-12-17 00:16:44 +00:00
128 changed files with 814 additions and 817 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
### BeEF ###
beef.db
beef.log
test/msf-test
extensions/admin_ui/media/javascript-min/
custom-config.yaml

28
Gemfile
View File

@@ -8,37 +8,23 @@
gem 'eventmachine'
gem 'thin'
gem 'sinatra', '~> 2.0'
gem 'rack', '~> 2.0'
gem 'rack-protection', '~> 2.0'
gem 'sinatra'
gem 'rack'
gem 'rack-protection'
gem 'em-websocket' # WebSocket support
gem 'uglifier'
gem 'mime-types'
gem 'execjs'
gem 'ansi'
gem 'term-ansicolor', :require => 'term/ansicolor'
gem 'dm-core'
gem 'json'
gem 'data_objects'
gem 'rubyzip', '>= 1.2.2'
gem 'espeak-ruby', '>= 1.0.4' # Text-to-Voice
gem 'nokogiri', '>= 1.10.4'
gem 'rake'
# SQLite support
group :sqlite do
gem 'dm-sqlite-adapter'
end
# PostgreSQL support
group :postgres do
#gem dm-postgres-adapter
end
# MySQL support
group :mysql do
#gem dm-mysql-adapter
end
gem 'otr-activerecord'
gem 'sqlite3'
# Geolocation support
group :geoip do
@@ -47,7 +33,6 @@ end
gem 'parseconfig'
gem 'erubis'
gem 'dm-migrations'
# Metasploit Integration extension
group :ext_msf do
@@ -94,7 +79,8 @@ group :test do
gem 'capybara'
# RESTful API tests/generic command module tests
gem 'rest-client', '>= 2.0.1'
gem 'byebug'
gem 'irb'
gem 'pry-byebug'
end
source 'https://rubygems.org'

View File

@@ -4,6 +4,8 @@
# See the file 'doc/COPYING' for copying permission
#
require 'yaml'
require 'bundler/setup'
load 'tasks/otr-activerecord.rake'
#require 'pry-byebug'
@@ -236,6 +238,10 @@ task :cde_beef_start => 'beef' do
puts '.'
end
################################
# ActiveRecord
namespace :db do
task :environment do
require_relative "beef"
end
end

56
beef
View File

@@ -119,14 +119,6 @@ unless config.get('beef.http.public_port').to_s.eql?('') || BeEF::Filters.is_val
exit 1
end
#
# @note Validate database driver
#
unless ['sqlite', 'postgres', 'mysql'].include? config.get('beef.database.driver')
print_error 'No default database selected. Please add one in config.yaml'
exit 1
end
#
# @note After the BeEF core is loaded, bootstrap the rest of the framework internals
#
@@ -160,43 +152,25 @@ BeEF::Modules.load
Socket.do_not_reverse_lookup = true
#
# @note Database setup - use DataMapper::Logger.new($stdout, :debug) for development debugging
# @note Database setup
#
case config.get("beef.database.driver")
when "sqlite"
DataMapper.setup(:default, "sqlite3://#{$root_dir}/#{config.get("beef.database.db_file")}")
when "mysql", "postgres"
DataMapper.setup(:default,
:adapter => config.get("beef.database.driver"),
:host => config.get("beef.database.db_host"),
:port => config.get("beef.database.db_port"),
:username => config.get("beef.database.db_user"),
:password => config.get("beef.database.db_passwd"),
:database => config.get("beef.database.db_name"),
:encoding => config.get("beef.database.db_encoding")
)
else
print_error 'No default database selected. Please add one in config.yaml'
exit 1
end
#
# @note Load the database
#
begin
# @note Resets the database if the -x flag was passed
if BeEF::Core::Console::CommandLine.parse[:resetdb]
print_info 'Resetting the database for BeEF.'
DataMapper.auto_migrate!
else
DataMapper.auto_upgrade!
end
rescue => e
print_error "Could not connect to database: #{e.message}"
if config.get("beef.database.driver") == 'sqlite'
print_error "Ensure the #{$root_dir}/#{config.get("beef.database.db_file")} database file is writable"
end
exit 1
db_file = config.get('beef.database.file')
# @note Resets the database if the -x flag was passed
if BeEF::Core::Console::CommandLine.parse[:resetdb]
print_info 'Resetting the database for BeEF.'
File.delete(db_file) if File.exists?(db_file)
end
# Connect to DB
ActiveRecord::Base.logger = nil
OTR::ActiveRecord.migrations_paths = [File.join('core', 'main', 'ar-migrations')]
OTR::ActiveRecord.configure_from_hash!(adapter:'sqlite3', database:db_file)
# Migrate (if required)
context = ActiveRecord::Migration.new.migration_context
if context.needs_migration?
ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration).migrate
end
#

View File

@@ -90,28 +90,7 @@ beef:
cert: "beef_cert.pem"
database:
# For information on using other databases please read the
# README.databases file
# supported DBs: sqlite, mysql, postgres
# NOTE: you must change the Gemfile adding a gem require line like:
# gem "dm-postgres-adapter"
# or
# gem "dm-mysql-adapter"
# if you want to switch drivers from sqlite to postgres (or mysql).
# Finally, run a 'bundle install' command and start BeEF.
driver: "sqlite"
# db_file is only used for sqlite
db_file: "beef.db"
# db connection information is only used for mysql/postgres
db_host: "localhost"
db_port: 3306
db_name: "beef"
db_user: "beef"
db_passwd: "beef"
db_encoding: "UTF-8"
file: "beef.db"
# Autorun Rule Engine
autorun:

View File

@@ -30,8 +30,6 @@ require 'core/main/network_stack/assethandler'
require 'core/main/network_stack/api'
# @note Include the autorun engine
require 'core/main/autorun_engine/models/rule'
require 'core/main/autorun_engine/models/execution'
require 'core/main/autorun_engine/parser'
require 'core/main/autorun_engine/engine'
require 'core/main/autorun_engine/rule_loader'

View File

@@ -10,6 +10,7 @@ end
end
# @note Includes database models - the order must be consistent otherwise DataMapper goes crazy
require 'core/main/model'
require 'core/main/models/commandmodule'
require 'core/main/models/hookedbrowser'
require 'core/main/models/log'
@@ -17,6 +18,8 @@ require 'core/main/models/command'
require 'core/main/models/result'
require 'core/main/models/optioncache'
require 'core/main/models/browserdetails'
require 'core/main/models/rule'
require 'core/main/models/execution'
# @note Include the constants
require 'core/main/constants/browsers'

View File

@@ -10,14 +10,14 @@ module BeEF
# @param [String] sid hooked browser session id string
# @return [BeEF::Core::Models::HookedBrowser] returns the associated Hooked Browser
def self.get_by_session(sid)
BeEF::Core::Models::HookedBrowser.first(:session => sid)
BeEF::Core::Models::HookedBrowser.where(:session => sid).first
end
# Get hooked browser by id
# @param [Integer] id hooked browser database id
# @return [BeEF::Core::Models::HookedBrowser] returns the associated Hooked Browser
def self.get_by_id(id)
BeEF::Core::Models::HookedBrowser.first(:id => id)
BeEF::Core::Models::HookedBrowser.find(id)
end
end

View File

@@ -31,8 +31,7 @@ require 'execjs'
require 'ansi'
require 'term/ansicolor'
require 'json'
require 'data_objects'
require 'dm-do-adapter'
require 'otr-activerecord'
require 'parseconfig'
require 'erubis'
require 'mime/types'
@@ -41,7 +40,6 @@ require 'resolv'
require 'digest'
require 'zip'
require 'logger'
# @note Logger
require 'core/logger'

View File

@@ -0,0 +1,12 @@
class CreateCommandModules < ActiveRecord::Migration[6.0]
def change
create_table :command_modules do |t|
t.text :name
t.text :path
end
end
end

View File

@@ -0,0 +1,19 @@
class CreateHookedBrowsers < ActiveRecord::Migration[6.0]
def change
create_table :hooked_browsers do |t|
t.text :session
t.text :ip
t.text :firstseen
t.text :lastseen
t.text :httpheaders
t.text :domain
t.integer :port
t.integer :count
t.boolean :is_proxy
end
end
end

View File

@@ -0,0 +1,14 @@
class CreateLogs < ActiveRecord::Migration[6.0]
def change
create_table :logs do |t|
t.text :logtype
t.text :event
t.datetime :date
t.references :hooked_browser
end
end
end

View File

@@ -0,0 +1,16 @@
class CreateCommands < ActiveRecord::Migration[6.0]
def change
create_table :commands do |t|
t.references :command_module
t.references :hooked_browser
t.text :data
t.datetime :creationdate
t.text :label
t.boolean :instructions_sent, default: false
end
end
end

View File

@@ -0,0 +1,15 @@
class CreateResults < ActiveRecord::Migration[6.0]
def change
create_table :results do |t|
t.references :command
t.references :hooked_browser
t.datetime :date
t.integer :status
t.text :data
end
end
end

View File

@@ -0,0 +1,12 @@
class CreateOptionCaches < ActiveRecord::Migration[6.0]
def change
create_table :option_caches do |t|
t.text :name
t.text :value
end
end
end

View File

@@ -0,0 +1,13 @@
class CreateBrowserDetails < ActiveRecord::Migration[6.0]
def change
create_table :browser_details do |t|
t.text :session_id
t.text :detail_key
t.text :detail_value
end
end
end

View File

@@ -0,0 +1,17 @@
class CreateExecutions < ActiveRecord::Migration[6.0]
def change
create_table :executions do |t|
t.text :session_id
t.integer :mod_count
t.integer :mod_successful
t.text :mod_body
t.text :exec_time
t.text :rule_token
t.boolean :is_sent
end
end
end

View File

@@ -0,0 +1,20 @@
class CreateRules < ActiveRecord::Migration[6.0]
def change
create_table :rules do |t|
t.text :name
t.text :author
t.text :browser
t.text :browser_version
t.text :os
t.text :os_version
t.text :modules
t.text :execution_order
t.text :execution_delay
t.text :chain_mode
end
end
end

View File

@@ -0,0 +1,12 @@
class CreateInterceptor < ActiveRecord::Migration[6.0]
def change
create_table :interceptors do |t|
t.text :ip
t.text :post_data
end
end
end

View File

@@ -0,0 +1,12 @@
class CreateWebCloner < ActiveRecord::Migration[6.0]
def change
create_table :web_cloner do |t|
t.text :uri
t.text :mount
end
end
end

View File

@@ -0,0 +1,11 @@
class CreateMassMailer < ActiveRecord::Migration[6.0]
def change
create_table :mass_mailer do |t|
#todo fields
end
end
end

View File

@@ -0,0 +1,17 @@
class CreateNetworkHost < ActiveRecord::Migration[6.0]
def change
create_table :network_hosts do |t|
t.references :hooked_browser
t.text :ip
t.text :hostname
t.text :ntype
t.text :os
t.text :mac
t.text :lastseen
end
end
end

View File

@@ -0,0 +1,15 @@
class CreateNetworkService < ActiveRecord::Migration[6.0]
def change
create_table :network_services do |t|
t.references :hooked_browser
t.text :proto
t.text :ip
t.text :port
t.text :ntype
end
end
end

View File

@@ -0,0 +1,44 @@
class CreateHttp < ActiveRecord::Migration[6.0]
def change
create_table :http do |t|
t.references :hooked_browser
# The http request to perform. In clear text.
t.text :request
# Boolean value as string to say whether cross-domain requests are allowed
t.boolean :allow_cross_domain, :default => true
# The http response body received. In clear text.
t.text :response_data
# The http response code. Useful to handle cases like 404, 500, 302, ...
t.integer :response_status_code
# The http response code. Human-readable code: success, error, ecc..
t.text :response_status_text
# The port status. closed, open or not http
t.text :response_port_status
# The XHR Http response raw headers
t.text :response_headers
# The http response method. GET or POST.
t.text :method
# The content length for the request.
t.text :content_length, :default => 0
# The request protocol/scheme (http/https)
t.text :proto
# The domain on which perform the request.
t.text :domain
# The port on which perform the request.
t.text :port
# Boolean value to say if the request was cross-domain
t.text :has_ran, :default => "waiting"
# The path of the request.
# Example: /secret.html
t.text :path
# The date at which the http response has been saved.
t.datetime :response_date
# The date at which the http request has been saved.
t.datetime :request_date
end
end
end

View File

@@ -0,0 +1,13 @@
class CreateRtcStatus < ActiveRecord::Migration[6.0]
def change
create_table :rtc_status do |t|
t.references :hooked_browser
t.integer :target_hooked_browser_id
t.text :status
end
end
end

View File

@@ -0,0 +1,13 @@
class CreateRtcManage < ActiveRecord::Migration[6.0]
def change
create_table :rtc_manage do |t|
t.references :hooked_browser
t.text :message
t.text :has_sent, default: "waiting"
end
end
end

View File

@@ -0,0 +1,14 @@
class CreateRtcSignal < ActiveRecord::Migration[6.0]
def change
create_table :rtc_signal do |t|
t.references :hooked_browser
t.integer :target_hooked_browser_id
t.text :signal
t.text :has_sent, default: "waiting"
end
end
end

View File

@@ -0,0 +1,14 @@
class CreateRtcModuleStatus < ActiveRecord::Migration[6.0]
def change
create_table :rtc_module_status do |t|
t.references :hooked_browser
t.references :command_module
t.integer :target_hooked_browser_id
t.text :status
end
end
end

View File

@@ -0,0 +1,14 @@
class CreateXssraysDetail < ActiveRecord::Migration[6.0]
def change
create_table :xssrays_detail do |t|
t.references :hooked_browser
t.text :vector_name
t.text :vector_method
t.text :vector_poc
end
end
end

View File

@@ -0,0 +1,14 @@
class CreateDnsRule < ActiveRecord::Migration[6.0]
def change
create_table :dns_rule do |t|
t.text :pattern
t.text :resource
t.text :response
t.text :callback
end
end
end

View File

@@ -0,0 +1,13 @@
class CreateIpecExploit < ActiveRecord::Migration[6.0]
def change
create_table :ipec_exploit do |t|
t.text :name
t.text :protocol
t.text :os
end
end
end

View File

@@ -0,0 +1,13 @@
class CreateIpecExploitRun < ActiveRecord::Migration[6.0]
def change
create_table :ipec_exploit_run do |t|
t.boolean :launched
t.text :http_headers
t.text :junk_size
end
end
end

View File

@@ -0,0 +1,12 @@
class CreateAutoloader < ActiveRecord::Migration[6.0]
def change
create_table :autoloader do |t|
t.references :command
t.boolean :in_use
end
end
end

View File

@@ -0,0 +1,18 @@
class CreateXssraysScan < ActiveRecord::Migration[6.0]
def change
create_table :xssrays_scan do |t|
t.references :hooked_browser
t.datetime :scan_start
t.datetime :scan_finish
t.text :domain
t.text :cross_domain
t.integer :clean_timeout
t.boolean :is_started
t.boolean :is_finished
end
end
end

View File

@@ -41,7 +41,7 @@ module BeEF
hb_session = hb.session
rule_ids.each do |rule_id|
rule = BeEF::Core::AutorunEngine::Models::Rule.get(rule_id)
rule = BeEF::Core::Models::Rule.find(rule_id)
modules = JSON.parse(rule.modules)
execution_order = JSON.parse(rule.execution_order)
@@ -57,7 +57,7 @@ module BeEF
rule_token = SecureRandom.hex(5)
modules.each do |cmd_mod|
mod = BeEF::Core::Models::CommandModule.first(:name => cmd_mod['name'])
mod = BeEF::Core::Models::CommandModule.where(:name => cmd_mod['name']).first
options = []
replace_input = false
cmd_mod['options'].each do|k,v|
@@ -85,7 +85,7 @@ module BeEF
# TODO catch error, which should never happen as values are checked way before ;-)
end
are_exec = BeEF::Core::AutorunEngine::Models::Execution.new(
are_exec = BeEF::Core::Models::Execution.new(
:session => hb_session,
:mod_count => modules.length,
:mod_successful => 0,
@@ -94,7 +94,7 @@ module BeEF
:is_sent => false,
:rule_id => rule_id
)
are_exec.save
are_exec.save!
# Once Engine.check() verified that the hooked browser match a Rule, trigger the Rule ;-)
print_more "Triggering ruleset #{rule_ids.to_s} on HB #{hb_id}"
end
@@ -272,9 +272,9 @@ module BeEF
:creationdate => Time.new.to_i,
:instructions_sent => true
)
command.save
command.save!
command_module = BeEF::Core::Models::CommandModule.first(:id => mod.id)
command_module = BeEF::Core::Models::CommandModule.find(mod.id)
if (command_module.path.match(/^Dynamic/))
# metasploit and similar integrations
command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new
@@ -385,9 +385,9 @@ module BeEF
def match(browser, browser_version, os, os_version, rule_id=nil)
match_rules = []
if rule_id != nil
rules = [BeEF::Core::AutorunEngine::Models::Rule.get(rule_id)]
rules = [BeEF::Core::Models::Rule.find(rule_id)]
else
rules = BeEF::Core::AutorunEngine::Models::Rule.all()
rules = BeEF::Core::Models::Rule.all
end
return nil if rules == nil
return nil unless rules.length > 0

View File

@@ -1,31 +0,0 @@
#
# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
module BeEF
module Core
module AutorunEngine
module Models
# @note Stored info about the execution of the ARE on hooked browsers.
class Execution
include DataMapper::Resource
storage_names[:default] = 'core_areexecution'
property :id, Serial
property :session, Text # hooked browser session where a ruleset triggered
property :mod_count, Integer # number of command modules of the ruleset
property :mod_successful, Integer # number of command modules that returned with success
# By default Text is only 65K, so field length increased to 1 MB
property :mod_body, Text, :length => 1024000 # entire command module(s) body to be sent
property :exec_time, String, :length => 15 # timestamp of ruleset triggering
property :rule_token, String, :length => 10 # unique token to be appended to wrapper function names
property :is_sent, Boolean
end
end
end
end
end

View File

@@ -1,34 +0,0 @@
#
# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
module BeEF
module Core
module AutorunEngine
module Models
# @note Table stores the rules for the Distributed Engine.
class Rule
include DataMapper::Resource
storage_names[:default] = 'core_arerules'
property :id, Serial
property :name, Text # rule name
property :author, String # rule author
property :browser, String, :length => 10 # browser name
property :browser_version, String, :length => 15 # browser version
property :os, String, :length => 10 # OS name
property :os_version, String, :length => 15 # OS version
property :modules, Text # JSON stringyfied representation of the JSON rule for further parsing
property :execution_order, Text # command module execution order
property :execution_delay, Text # command module time delays
property :chain_mode, String, :length => 40 # rule chaining mode
has n, :executions
end
end
end
end
end

View File

@@ -53,7 +53,7 @@ module BeEF
# check if module names, conditions and options are ok
modules.each do |cmd_mod|
mod = BeEF::Core::Models::CommandModule.first(:name => cmd_mod['name'])
mod = BeEF::Core::Models::CommandModule.where(:name => cmd_mod['name']).first
if mod != nil
modk = BeEF::Module.get_key_by_database_id(mod.id)
mod_options = BeEF::Module.get_options(modk)

View File

@@ -52,7 +52,7 @@ module BeEF
print_more "Exec order: #{exec_order}"
print_more "Exec delay: #{exec_delay}"
end
are_rule = BeEF::Core::AutorunEngine::Models::Rule.new(
are_rule = BeEF::Core::Models::Rule.new(
:name => name,
:author => author,
:browser => browser,

View File

@@ -179,7 +179,7 @@ module BeEF
return
end
command = BeEF::Core::Models::Command.first(:id => @command_id)
command = BeEF::Core::Models::Command.find(@command_id)
@eruby = Erubis::FastEruby.new(File.read(f))
@@ -237,7 +237,7 @@ module BeEF
# @todo TODO Document
def oc_value(name)
option = BeEF::Core::Models::OptionCache.first(:name => name)
option = BeEF::Core::Models::OptionCache.where(:name => name).first
return nil unless option
option.value
end

View File

@@ -82,7 +82,7 @@ module Core
begin
id = random_hex_string(8)
BeEF::Core::Models::Dns::Rule.each { |rule| throw StandardError if id == rule.id }
BeEF::Core::Models::Dns::Rule.all.each { |rule| throw StandardError if id == rule.id }
rescue StandardError
retry
end

View File

@@ -30,7 +30,7 @@ module BeEF
# validate hook session value
session_id = get_param(@data, 'beefhook')
(self.err_msg "session id is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(session_id)
hooked_browser = HB.first(:session => session_id)
hooked_browser = HB.where(:session => session_id).first
return if not hooked_browser.nil? # browser is already registered with framework
# create the structure representing the hooked browser
@@ -73,7 +73,7 @@ module BeEF
@http_headers[key.sub(/^HTTP_/, '')] = value.force_encoding('UTF-8')
}
zombie.httpheaders = @http_headers.to_json
zombie.save
zombie.save!
#print_debug "[INIT] HTTP Headers: #{zombie.httpheaders}"
# add a log entry for the newly hooked browser
@@ -211,7 +211,7 @@ module BeEF
if config.get("beef.extension.network.enable") == true
if proxy_server =~ /^([\d\.]+):([\d]+)$/
print_debug("Hooked browser [id:#{zombie.id}] is using a proxy [ip: #{$1}]")
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => $1, :type => 'Proxy')
BeEF::Core::Models::NetworkHost.create(:hooked_browser_id => session_id, :ip => $1, :type => 'Proxy')
end
end
end
@@ -504,7 +504,7 @@ module BeEF
# add localhost as network host
if config.get('beef.extension.network.enable')
print_debug("Hooked browser has network interface 127.0.0.1")
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'host.os.name'))
BeEF::Core::Models::NetworkHost.create(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'host.os.name'))
end
# check if any ARE rules shall be triggered only if the channel is != WebSockets (XHR). If the channel

View File

@@ -24,7 +24,7 @@ module Handlers
# and deploy some command modules or extensions to the hooked browser.
get '/' do
@body = ''
@params = request.query_string
params = request.query_string
#@response = Rack::Response.new(body=[], 200, header={})
config = BeEF::Core::Configuration.instance
@@ -48,7 +48,12 @@ module Handlers
# @note get zombie if already hooked the framework
hook_session_name = config.get('beef.http.hook_session_name')
hook_session_id = request[hook_session_name]
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hook_session_id) if not hook_session_id.nil?
begin
raise ActiveRecord::RecordNotFound if hook_session_id.nil?
hooked_browser = BeEF::Core::Models::HookedBrowser.where(:session => hook_session_id).first
rescue ActiveRecord::RecordNotFound
hooked_browser = false
end
# @note is a new browser so return instructions to set up the hook
if not hooked_browser
@@ -82,21 +87,21 @@ module Handlers
end
hooked_browser.count!
hooked_browser.save
hooked_browser.save!
# @note add all available command module instructions to the response
zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
zombie_commands = BeEF::Core::Models::Command.where(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
zombie_commands.each{|command| add_command_instructions(command, hooked_browser)}
# @note Check if there are any ARE rules to be triggered. If is_sent=false rules are triggered
are_executions = BeEF::Core::AutorunEngine::Models::Execution.all(:is_sent => false, :session => hook_session_id)
are_executions = BeEF::Core::Models::Execution.where(:is_sent => false, :session_id => hook_session_id)
are_executions.each do |are_exec|
@body += are_exec.mod_body
are_exec.update(:is_sent => true, :exec_time => Time.new.to_i)
end
# @note We dynamically get the list of all browser hook handler using the API and register them
BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, @params, request, response)
BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, params, request, response)
end
# @note set response headers and body

View File

@@ -21,7 +21,7 @@ module BeEF
config = BeEF::Core::Configuration.instance
# @note get the command module
command_module = BeEF::Core::Models::CommandModule.first(:id => command.command_module_id)
command_module = BeEF::Core::Models::CommandModule.where(:id => command.command_module_id).first
(print_error "command_module is nil"; return) if command_module.nil?
(print_error "command_module.path is nil"; return) if command_module.path.nil?
@@ -70,7 +70,7 @@ module BeEF
# @note flag that the command has been sent to the hooked browser
command.instructions_sent = true
command.save
command.save!
end
end

View File

@@ -40,7 +40,7 @@ module Core
raise TypeError, '"Hooked Browser ID" needs to be an integer' unless hb.integer?
# logging the new event into the database
@logs.new(:type => from.to_s, :event => event.to_s, :date => time_now, :hooked_browser_id => hb).save
@logs.create(:logtype => from.to_s, :event => event.to_s, :date => time_now, :hooked_browser_id => hb).save!
print_debug "Event: #{event}"
# if notifications are enabled send the info there too
if @notifications

View File

@@ -27,14 +27,10 @@ module Core
def update_commands!
config = BeEF::Core::Configuration.instance
db_modules = []
BeEF::Core::Models::CommandModule.all.each do |mod|
db_modules << mod.name
end
db_modules = BeEF::Core::Models::CommandModule.all.pluck(:name)
config.get('beef.module').each do |k, v|
h = { :name => k, :path => "#{v['path']}module.rb" }
BeEF::Core::Models::CommandModule.new(h).save unless db_modules.include? k
BeEF::Core::Models::CommandModule.new(name: k, path: "#{v['path']}module.rb").save! unless db_modules.include? k
end
BeEF::Core::Models::CommandModule.all.each do |mod|

14
core/main/model.rb Normal file
View File

@@ -0,0 +1,14 @@
#
# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
module BeEF
module Core
class Model < ActiveRecord::Base
# Tell ActiveRecord that this is not a model
self.abstract_class = true
end
end
end

View File

@@ -11,20 +11,13 @@ module Models
#
# For example, the type and version of browser the hooked browsers are using.
#
class BrowserDetails
class BrowserDetails < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'core_browserdetails'
property :session_id, String, :length => 255, :key => true
property :detail_key, String, :length => 255, :lazy => false, :key => true
property :detail_value, Text, :lazy => false
#
# Returns the requested value from the data store
#
def self.get(session_id, key)
browserdetail = first(:session_id => session_id, :detail_key => key)
browserdetail = self.where(:session_id => session_id, :detail_key => key).first
return nil if browserdetail.nil?
return nil if browserdetail.detail_value.nil?
@@ -35,19 +28,20 @@ module Models
# Stores or updates an existing key->value pair in the data store
#
def self.set(session_id, detail_key, detail_value)
browserdetails = BeEF::Core::Models::BrowserDetails.all(
browserdetails = BeEF::Core::Models::BrowserDetails.where(
:session_id => session_id,
:detail_key => detail_key )
if browserdetails.nil? || browserdetails.empty?
:detail_key => detail_key ).first
if browserdetails.nil?
# store the new browser details key/value
browserdetails = BeEF::Core::Models::BrowserDetails.new(
:session_id => session_id,
:detail_key => detail_key,
:detail_value => detail_value || '')
result = browserdetails.save
result = browserdetails.save!
else
# update the browser details key/value
result = browserdetails.update(:detail_value => detail_value || '')
browserdetails.detail_value = detail_value || ''
result = browserdetails.save!
print_debug "Browser has updated '#{detail_key}' to '#{detail_value}'"
end

View File

@@ -9,19 +9,11 @@ module Core
module Models
# @note Table stores the commands that have been sent to the Hooked Browsers.
class Command
class Command < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'commands'
property :id, Serial
property :data, Text
property :creationdate, String, :length => 15, :lazy => false
property :label, Text, :lazy => false
property :instructions_sent, Boolean, :default => false
has n, :results
has_many :results
has_one :command_module
has_one :hooked_browser
#
# Save results and flag that the command has been run on the hooked browser
@@ -40,22 +32,22 @@ module Models
raise TypeError, '"status" needs to be an integer' unless status.integer?
# @note get the hooked browser structure and id from the database
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hook_session_id) || nil
hooked_browser = BeEF::Core::Models::HookedBrowser.where(:session => hook_session_id).first || nil
raise TypeError, "hooked_browser is nil" if hooked_browser.nil?
raise TypeError, "hooked_browser.id is nil" if hooked_browser.id.nil?
# @note get the command module data structure from the database
command = first(:id => command_id, :hooked_browser_id => hooked_browser.id) || nil
command = self.where(:id => command_id, :hooked_browser_id => hooked_browser.id).first || nil
raise TypeError, "command is nil" if command.nil?
# @note create the entry for the results
command.results.new(
BeEF::Core::Models::Result.create(
:hooked_browser_id => hooked_browser.id,
:command_id => command.id,
:data => result.to_json,
:status => status,
:date => Time.now.to_i
)
command.save
s = show_status(status)
log = "Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}]"

View File

@@ -7,22 +7,10 @@ module BeEF
module Core
module Models
class CommandModule
class CommandModule < BeEF::Core::Model
include DataMapper::Resource
has_many :commands
storage_names[:default] = 'core_commandmodules'
# @note command module ID
property :id, Serial
# @note command module name
property :name, Text, :lazy => false
# @note command module path
property :path, Text, :lazy => false
has n, :commands
end
end

View File

@@ -0,0 +1,14 @@
#
# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
module BeEF
module Core
module Models # @note Stored info about the execution of the ARE on hooked browsers.
class Execution < BeEF::Core::Model
end
end
end
end

View File

@@ -9,45 +9,11 @@ module Models
#
#
#
class HookedBrowser
class HookedBrowser < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'core_hookedbrowsers'
# @note zombie ID
property :id, Serial
# @note hooked browser session ID
property :session, Text, :lazy => false
# @note IP address of the hooked browser
property :ip, Text, :lazy => false
# @note timestamp first time the browser communicated with BeEF
property :firstseen, String, :length => 15
# @note timestamp last time the browser communicated with BeEF
property :lastseen, String, :length => 15
# @note HTTP headers sent be the browser to the BeEF server upon first hook
property :httpheaders, Text, :lazy => false
# @note the domain originating the hook request
property :domain, Text, :lazy => false
# @note the port on the domain originating the hook request
property :port, Integer, :default => 80
# @note number of times the zombie has polled
property :count, Integer, :lazy => false
# @note if true the HB is used as a tunneling proxy
property :is_proxy, Boolean, :default => false
has n, :commands
has n, :results
has n, :logs
has_many :commands
has_many :results
has_many :logs
# @note Increases the count of a zombie
def count!

View File

@@ -7,17 +7,10 @@ module BeEF
module Core
module Models
class Log
class Log < BeEF::Core::Model
has_one :hooked_browser
include DataMapper::Resource
storage_names[:default] = 'core_logs'
property :id, Serial
property :type, Text, :lazy => false
property :event, Text, :lazy => false
property :date, DateTime, :lazy => false
property :hooked_browser_id, Text, :lazy => false
end
end

View File

@@ -7,15 +7,7 @@ module BeEF
module Core
module Models
class OptionCache
include DataMapper::Resource
storage_names[:default] = 'core_optioncache'
property :id, Serial
property :name, Text
property :value, Text
class OptionCache < BeEF::Core::Model
end

View File

@@ -7,16 +7,10 @@ module BeEF
module Core
module Models
class Result
include DataMapper::Resource
storage_names[:default] = 'core_results'
property :id, Serial
property :date, String, :length => 15, :lazy => false
property :status, Integer
property :data, Text
class Result < BeEF::Core::Model
has_one :command
has_one :hooked_browser
end

16
core/main/models/rule.rb Normal file
View File

@@ -0,0 +1,16 @@
#
# Copyright (c) 2006-2019 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
module BeEF
module Core
module Models
# @note Table stores the rules for the Distributed Engine.
class Rule < BeEF::Core::Model
has_many :executions
end
end
end
end

View File

@@ -108,7 +108,7 @@ module BeEF
print_debug("[WebSocket] activeSocket content [#{@@activeSocket}]")
hb_session = msg_hash["cookie"]
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hb_session)
hooked_browser = BeEF::Core::Models::HookedBrowser.where(:session => hb_session).first
if hooked_browser.nil?
print_error '[WebSocket] Fingerprinting not finished yet.'
print_more 'ARE rules were not triggered. You may want to trigger them manually via REST API.'
@@ -126,7 +126,7 @@ module BeEF
# polling zombie
unless msg_hash['alive'].nil?
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
hooked_browser = BeEF::Core::Models::HookedBrowser.where(:session => msg_hash["alive"]).first
# This will happen if you reset BeEF database (./beef -x),
# and existing zombies try to connect. These zombies will be ignored,
@@ -141,15 +141,15 @@ module BeEF
hooked_browser.lastseen = Time.new.to_i
hooked_browser.count!
hooked_browser.save
hooked_browser.save!
# Check if new modules need to be sent
zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
zombie_commands = BeEF::Core::Models::Command.where(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
zombie_commands.each { |command| add_command_instructions(command, hooked_browser) }
# Check if there are any ARE rules to be triggered. If is_sent=false rules are triggered
are_body = ''
are_executions = BeEF::Core::AutorunEngine::Models::Execution.all(:is_sent => false, :session => hooked_browser.session)
are_executions = BeEF::Core::Models::Execution.where(:is_sent => false, :session => hooked_browser.session)
are_executions.each do |are_exec|
are_body += are_exec.mod_body
are_exec.update(:is_sent => true, :exec_time => Time.new.to_i)

View File

@@ -38,7 +38,7 @@ module BeEF
get '/rule/delete/:rule_id' do
begin
rule_id = params[:rule_id]
rule = BeEF::Core::AutorunEngine::Models::Rule.get(rule_id)
rule = BeEF::Core::AutorunEngine::Models::Rule.find(rule_id)
rule.destroy
{ 'success' => true}.to_json
rescue => e
@@ -53,13 +53,13 @@ module BeEF
begin
rule_id = params[:rule_id]
online_hooks = BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 15))
online_hooks = BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 15))
are = BeEF::Core::AutorunEngine::Engine.instance
if online_hooks != nil
online_hooks.each do |hb|
hb_details = BeEF::Core::Models::BrowserDetails
browser_name = hb_details.get(hb.session, 'browser.name')
browser_name = hb_details.get(hb.session, 'browser.name')
browser_version = hb_details.get(hb.session, 'browser.version')
os_name = hb_details.get(hb.session, 'host.os.name')
os_version = hb_details.get(hb.session, 'host.os.version')

View File

@@ -24,10 +24,10 @@ module BeEF
# @note Get all browser details for the specified session
#
get '/:session' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 404 if hb.nil?
details = BeEF::Core::Models::BrowserDetails.all(:session_id => hb.session)
details = BeEF::Core::Models::BrowserDetails.where(:session_id => hb.session)
error 404 if details.nil?
result = []

View File

@@ -24,8 +24,8 @@ module BeEF
# @note Get online and offline hooked browsers details (like name, version, os, ip, port, ...)
#
get '/' do
online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 15)))
offline_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 15)))
online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 15)))
offline_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen <= ?', (Time.new.to_i - 15)))
output = {
'hooked-browsers' => {
@@ -37,33 +37,33 @@ module BeEF
end
get '/:session/delete' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
details = BeEF::Core::Models::BrowserDetails.all(:session_id => hb.session)
details = BeEF::Core::Models::BrowserDetails.where(:session_id => hb.session)
details.destroy
logs = BeEF::Core::Models::Log.all(:hooked_browser_id => hb.id)
logs = BeEF::Core::Models::Log.where(:hooked_browser_id => hb.id)
logs.destroy
commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hb.id)
commands = BeEF::Core::Models::Command.where(:hooked_browser_id => hb.id)
commands.destroy
results = BeEF::Core::Models::Result.all(:hooked_browser_id => hb.id)
results = BeEF::Core::Models::Result.where(:hooked_browser_id => hb.id)
results.destroy
begin
requester = BeEF::Core::Models::Http.all(:hooked_browser_id => hb.id)
requester = BeEF::Core::Models::Http.where(:hooked_browser_id => hb.id)
requester.destroy
rescue => e
#the requester module may not be enabled
end
begin
xssraysscans = BeEF::Core::Models::Xssraysscan.all(:hooked_browser_id => hb.id)
xssraysscans = BeEF::Core::Models::Xssraysscan.where(:hooked_browser_id => hb.id)
xssraysscans.destroy
xssraysdetails = BeEF::Core::Models::Xssraysdetail.all(:hooked_browser_id => hb.id)
xssraysdetails = BeEF::Core::Models::Xssraysdetail.where(:hooked_browser_id => hb.id)
xssraysdetails.destroy
rescue => e
#the xssraysscan module may not be enabled
@@ -96,7 +96,7 @@ module BeEF
# Useful if you need to query the API via jQuery.dataTable < 1.10 which is currently used in PhishingFrenzy
#
get '/pf/online' do
online_hooks = hbs_to_array(BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 15)))
online_hooks = hbs_to_array(BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 15)))
output = {
'aaData' => online_hooks
@@ -109,7 +109,7 @@ module BeEF
# Useful if you need to query the API via jQuery.dataTable < 1.10 which is currently used in PhishingFrenzy
#
get '/pf/offline' do
offline_hooks = hbs_to_array(BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 15)))
offline_hooks = hbs_to_array(BeEF::Core::Models::HookedBrowser.where('lastseen <= ?', (Time.new.to_i - 15)))
output = {
'aaData' => offline_hooks
@@ -121,10 +121,10 @@ module BeEF
# @note Get all the hooked browser details (plugins enabled, technologies enabled, cookies)
#
get '/:session' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
details = BeEF::Core::Models::BrowserDetails.all(:session_id => hb.session)
details = BeEF::Core::Models::BrowserDetails.where(:session_id => hb.session)
result = {}
details.each do |property|
result[property.detail_key] = property.detail_value
@@ -140,16 +140,16 @@ module BeEF
os_version = body['os_version']
arch = body['arch']
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
BeEF::Core::Models::BrowserDetails.first(:session_id => hb.session, :detail_key => 'host.os.name').destroy
BeEF::Core::Models::BrowserDetails.first(:session_id => hb.session, :detail_key => 'host.os.version').destroy
BeEF::Core::Models::BrowserDetails.where(:session_id => hb.session, :detail_key => 'host.os.name').destroy
BeEF::Core::Models::BrowserDetails.where(:session_id => hb.session, :detail_key => 'host.os.version').destroy
#BeEF::Core::Models::BrowserDetails.first(:session_id => hb.session, :detail_key => 'Arch').destroy
BeEF::Core::Models::BrowserDetails.new(:session_id => hb.session, :detail_key => 'host.os.name', :detail_value => os).save
BeEF::Core::Models::BrowserDetails.new(:session_id => hb.session, :detail_key => 'host.os.version', :detail_value => os_version).save
BeEF::Core::Models::BrowserDetails.new(:session_id => hb.session, :detail_key => 'Arch', :detail_value => arch).save
BeEF::Core::Models::BrowserDetails.create(:session_id => hb.session, :detail_key => 'host.os.name', :detail_value => os)
BeEF::Core::Models::BrowserDetails.create(:session_id => hb.session, :detail_key => 'host.os.version', :detail_value => os_version)
BeEF::Core::Models::BrowserDetails.create(:session_id => hb.session, :detail_key => 'Arch', :detail_value => arch)
# TODO if there where any ARE rules defined for this hooked browser,
# after updating OS/arch, force a retrigger of the rule.

View File

@@ -24,7 +24,7 @@ module BeEF
# @note Get all global logs
#
get '/' do
logs = BeEF::Core::Models::Log.all()
logs = BeEF::Core::Models::Log.all
logs_to_json(logs)
end
@@ -44,10 +44,10 @@ module BeEF
# @note Get hooked browser logs
#
get '/:session' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
logs = BeEF::Core::Models::Log.all(:hooked_browser_id => hb.id)
logs = BeEF::Core::Models::Log.where(:hooked_browser_id => hb.id)
logs_to_json(logs)
end
@@ -62,7 +62,7 @@ module BeEF
'id' => log.id.to_i,
'date' => log.date.to_s,
'event' => log.event.to_s,
'type' => log.type.to_s,
'logtype' => log.logtype.to_s,
'hooked_browser_id' => log.hooked_browser_id.to_s
}
end
@@ -84,7 +84,7 @@ module BeEF
logs.reverse.each do |log|
maker.items.new_item do |item|
item.id = log.id.to_s
item.title = "[#{log.type}] #{log.event}"
item.title = "[#{log.logtype}] #{log.event}"
item.updated = log.date.to_s
end
end

View File

@@ -43,7 +43,7 @@ module BeEF
end
get '/search/:mod_name' do
mod = BeEF::Core::Models::CommandModule.first(:name => params[:mod_name])
mod = BeEF::Core::Models::CommandModule.where(:name => params[:mod_name]).first
result = {}
if mod != nil
result = {'id' => mod.id}
@@ -55,7 +55,7 @@ module BeEF
# @note Get the module definition (info, options)
#
get '/:mod_id' do
cmd = BeEF::Core::Models::CommandModule.get(params[:mod_id])
cmd = BeEF::Core::Models::CommandModule.find(params[:mod_id])
error 404 unless cmd != nil
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
error 404 unless modk != nil
@@ -81,12 +81,12 @@ module BeEF
#{"date":"1331637093","data":"{\"data\":\"text=michele\"}"}
#
get '/:session/:mod_id/:cmd_id' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
cmd = BeEF::Core::Models::Command.first(:hooked_browser_id => hb.id,
:command_module_id => params[:mod_id], :id => params[:cmd_id])
cmd = BeEF::Core::Models::Command.where(:hooked_browser_id => hb.id,
:command_module_id => params[:mod_id], :id => params[:cmd_id]).first
error 404 unless cmd != nil
results = BeEF::Core::Models::Result.all(:hooked_browser_id => hb.id, :command_id => cmd.id)
results = BeEF::Core::Models::Result.where(:hooked_browser_id => hb.id, :command_id => cmd.id)
error 404 unless results != nil
results_hash = {}
@@ -137,7 +137,7 @@ module BeEF
#{"success":"true","command_id":"not_available"}
#
post '/:session/:mod_id' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
hb = BeEF::Core::Models::HookedBrowser.where(:session => params[:session]).first
error 401 unless hb != nil
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
error 404 unless modk != nil
@@ -198,7 +198,7 @@ module BeEF
# run on all hooked browsers currently online?
if hb_ids.first =~ /\Aall_online\z/i
hb_ids = []
BeEF::Core::Models::HookedBrowser.all(
BeEF::Core::Models::HookedBrowser.where(
:lastseen.gte => (Time.new.to_i - 15)).each {|hb| hb_ids << hb.id }
# run on all hooked browsers?
elsif hb_ids.first =~ /\Aall\z/i
@@ -208,7 +208,7 @@ module BeEF
# run modules
hb_ids.each do |hb_id|
hb = BeEF::Core::Models::HookedBrowser.first(:id => hb_id)
hb = BeEF::Core::Models::HookedBrowser.find(hb_id)
if hb == nil
results[hb_id] = 0
next
@@ -256,7 +256,7 @@ module BeEF
request.body.rewind
begin
body = JSON.parse request.body.read
hb = BeEF::Core::Models::HookedBrowser.first(:session => body["hb"])
hb = BeEF::Core::Models::HookedBrowser.where(:session => body["hb"]).first
error 401 unless hb != nil
results = Hash.new

View File

@@ -162,7 +162,9 @@ module BeEF
# Starts the BeEF http server
#
def start
@http_server.start
@http_server.start do
use OTR::ActiveRecord::ConnectionManagement
end
rescue RuntimeError => e
# port is in use
raise unless e.message.include? 'no acceptor'

View File

@@ -48,7 +48,7 @@ module BeEF
# Get all modules currently stored in the database
# @return [Array] DataMapper array of all BeEF::Core::Models::CommandModule's in the database
def self.get_stored_in_db
BeEF::Core::Models::CommandModule.all(:order => [:id.asc])
BeEF::Core::Models::CommandModule.all.order(:id)
end
# Loads all enabled modules

View File

@@ -7,14 +7,14 @@
# Function used to print errors to the console
# @param [String] s String to be printed
def print_error(s)
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[!]'+' '+s
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[!]'+' '+s.to_s
BeEF.logger.error s.to_s
end
# Function used to print information to the console
# @param [String] s String to be printed
def print_info(s)
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[*]'+' '+s
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[*]'+' '+s.to_s
BeEF.logger.info s.to_s
end
@@ -45,7 +45,7 @@ end
# Function used to print successes to the console
# @param [String] s String to be printed
def print_success(s)
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[+]'+' '+s
puts Time.now.localtime.strftime("[%k:%M:%S]")+'[+]'+' '+s.to_s
BeEF.logger.info s.to_s
end

View File

@@ -225,10 +225,10 @@ class Modules < BeEF::Extension::AdminUI::HttpController
# if dynamic modules are found in the DB, then we don't have yaml config for them
# and loading must proceed in a different way.
dynamic_modules = BeEF::Core::Models::CommandModule.all(:path.like => "Dynamic/")
dynamic_modules = BeEF::Core::Models::CommandModule.where('path LIKE ?', 'Dynamic/')
if(dynamic_modules != nil)
all_modules = BeEF::Core::Models::CommandModule.all(:order => [:id.asc])
all_modules = BeEF::Core::Models::CommandModule.all.order(:id)
all_modules.each{|dyn_mod|
next if !dyn_mod.path.split('/')[1].match(/^metasploit/)
command_mod_name = dyn_mod["name"]
@@ -257,7 +257,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController
def select_command_module
command_module_id = @params['command_module_id'] || nil
(print_error "command_module_id is nil";return) if command_module_id.nil?
command_module = BeEF::Core::Models::CommandModule.get(command_module_id)
command_module = BeEF::Core::Models::CommandModule.find(command_module_id)
key = BeEF::Module.get_key_by_database_id(command_module_id)
payload_name = @params['payload_name'] || nil
@@ -284,12 +284,12 @@ class Modules < BeEF::Extension::AdminUI::HttpController
(print_error "nonce incorrect";return) if @session.get_nonce != nonce
# get the browser id
zombie = Z.first(:session => zombie_session)
zombie = Z.where(:session => zombie_session).first
(print_error "Zombie is nil";return) if zombie.nil?
zombie_id = zombie.id
(print_error "Zombie id is nil";return) if zombie_id.nil?
C.all(:command_module_id => command_module_id, :hooked_browser_id => zombie_id).each do |command|
C.where(:command_module_id => command_module_id, :hooked_browser_id => zombie_id).each do |command|
commands.push({
'id' => i,
'object_id' => command.id,
@@ -346,7 +346,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController
# get params
command_id = @params['command_id'] || nil
(print_error "Command id is nil";return) if command_id.nil?
command = BeEF::Core::Models::Command.first(:id => command_id.to_i) || nil
command = BeEF::Core::Models::Command.find(command_id.to_i) || nil
(print_error "Command is nil";return) if command.nil?
# validate nonce
nonce = @params['nonce'] || nil
@@ -382,11 +382,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController
oc.save
}
zombie = Z.first(:session => zombie_session)
zombie = Z.where(:session => zombie_session).first
(print_error "Zombie is nil";return) if zombie.nil?
zombie_id = zombie.id
(print_error "Zombie id is nil";return) if zombie_id.nil?
command_module = BeEF::Core::Models::CommandModule.get(command_module_id)
command_module = BeEF::Core::Models::CommandModule.find(command_module_id)
if(command_module != nil && command_module.path.match(/^Dynamic/))
dyn_mod_name = command_module.path.split('/').last
@@ -423,14 +423,14 @@ class Modules < BeEF::Extension::AdminUI::HttpController
# get params
command_id = @params['command_id']|| nil
(print_error "Command id is nil";return) if command_id.nil?
command = BeEF::Core::Models::Command.first(:id => command_id.to_i) || nil
command = BeEF::Core::Models::Command.find(command_id.to_i) || nil
(print_error "Command is nil";return) if command.nil?
# get command_module
command_module = BeEF::Core::Models::CommandModule.first(:id => command.command_module_id)
command_module = BeEF::Core::Models::CommandModule.find(command.command_module_id)
(print_error "command_module is nil";return) if command_module.nil?
resultsdb = BeEF::Core::Models::Result.all(:command_id => command_id)
resultsdb = BeEF::Core::Models::Result.where(:command_id => command_id)
(print_error "Command id result is nil";return) if resultsdb.nil?
resultsdb.each{ |result| results.push({'date' => result.date, 'data' => JSON.parse(result.data)}) }
@@ -450,10 +450,10 @@ class Modules < BeEF::Extension::AdminUI::HttpController
# get params
command_id = @params['command_id'] || nil
(print_error "Command id is nil";return) if command_id.nil?
command = BeEF::Core::Models::Command.first(:id => command_id.to_i) || nil
command = BeEF::Core::Models::Command.find(command_id.to_i) || nil
(print_error "Command is nil";return) if command.nil?
command_module = BeEF::Core::Models::CommandModule.get(command.command_module_id)
command_module = BeEF::Core::Models::CommandModule.find(command.command_module_id)
(print_error "command_module is nil";return) if command_module.nil?
if(command_module.path.split('/').first.match(/^Dynamic/))
@@ -503,7 +503,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController
def dynamic_modules2json(id)
command_modules_json = {}
mod = BeEF::Core::Models::CommandModule.first(:id => id)
mod = BeEF::Core::Models::CommandModule.find(id)
# if the module id is not in the database return false
return {'success' => 'false'}.to_json if(not mod)
@@ -525,7 +525,7 @@ class Modules < BeEF::Extension::AdminUI::HttpController
def dynamic_payload2json(id, payload_name)
command_modules_json = {}
command_module = BeEF::Core::Models::CommandModule.get(id)
command_module = BeEF::Core::Models::CommandModule.find(id)
(print_error "Module does not exists";return 'success' => 'false') if command_module.nil?
payload_options = BeEF::Module.get_payload_options(command_module.name,payload_name)

View File

@@ -7,19 +7,12 @@ module BeEF
module Core
module Models
class Autoloading
include DataMapper::Resource
storage_names[:default] = 'autoloading'
property :id, Serial
property :in_use, Boolean
belongs_to :command
class Autoloading < BeEF::Core::Model
belongs_to :command
end
end
end
end
end

View File

@@ -150,7 +150,7 @@ class Core
'Hardware'
])
BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 30)).each do |zombie|
BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 30)).each do |zombie|
tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session,"HostName").to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName').to_s+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion').to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'Hardware')]
end
@@ -184,7 +184,7 @@ class Core
'Hardware'
])
BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie|
BeEF::Core::Models::HookedBrowser.where('lastseen < ?', (Time.new.to_i - 30)).each do |zombie|
tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session,"HostName").to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName').to_s+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion').to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'Hardware')]
end
@@ -213,7 +213,7 @@ class Core
end
onlinezombies = []
BeEF::Core::Models::HookedBrowser.all(:lastseen.gt => (Time.new.to_i - 30)).each do |zombie|
BeEF::Core::Models::HookedBrowser.where('lastseen > ?', (Time.new.to_i - 30)).each do |zombie|
onlinezombies << zombie.id
end
@@ -268,7 +268,7 @@ class Core
end
onlinezombies = []
BeEF::Core::Models::HookedBrowser.all(:lastseen.gt => (Time.new.to_i - 30)).each do |z|
BeEF::Core::Models::HookedBrowser.where('lastseen > ?' (Time.new.to_i - 30)).each do |z|
onlinezombies << z.id
end
@@ -400,7 +400,7 @@ class Core
end
offlinezombies = []
BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie|
BeEF::Core::Models::HookedBrowser.where('lastseen < ?', (Time.new.to_i - 30)).each do |zombie|
offlinezombies << zombie.id
end

View File

@@ -18,8 +18,8 @@ class ShellInterface
def settarget(id)
begin
self.targetsession = BeEF::Core::Models::HookedBrowser.first(:id => id).session
self.targetip = BeEF::Core::Models::HookedBrowser.first(:id => id).ip
self.targetsession = BeEF::Core::Models::HookedBrowser.find(id).session
self.targetip = BeEF::Core::Models::HookedBrowser.find(id).ip
self.targetid = id
rescue
return nil
@@ -28,8 +28,8 @@ class ShellInterface
def setofflinetarget(id)
begin
self.targetsession = BeEF::Core::Models::HookedBrowser.first(:id => id).session
self.targetip = "(OFFLINE) " + BeEF::Core::Models::HookedBrowser.first(:id => id).ip
self.targetsession = BeEF::Core::Models::HookedBrowser.find(id).session
self.targetip = "(OFFLINE) " + BeEF::Core::Models::HookedBrowser.find(id).ip
self.targetid = id
rescue
return nil
@@ -80,10 +80,10 @@ class ShellInterface
# if dynamic modules are found in the DB, then we don't have yaml config for them
# and loading must proceed in a different way.
dynamic_modules = BeEF::Core::Models::CommandModule.all(:path.like => "Dynamic/")
dynamic_modules = BeEF::Core::Models::CommandModule.where('path LIKE ?', 'Dynamic/')
if(dynamic_modules != nil)
all_modules = BeEF::Core::Models::CommandModule.all(:order => [:id.asc])
all_modules = BeEF::Core::Models::CommandModule.all.order(:id)
all_modules.each{|dyn_mod|
next if !dyn_mod.path.split('/').first.match(/^Dynamic/)
@@ -151,7 +151,7 @@ class ShellInterface
commands = []
i = 0
BeEF::Core::Models::Command.all(:command_module_id => cmdid, :hooked_browser_id => self.targetid).each do |command|
BeEF::Core::Models::Command.where(:command_module_id => cmdid, :hooked_browser_id => self.targetid).each do |command|
commands.push({
'id' => i,
'object_id' => command.id,
@@ -167,7 +167,7 @@ class ShellInterface
def getindividualresponse(cmdid)
results = []
begin
BeEF::Core::Models::Result.all(:command_id => cmdid).each { |result|
BeEF::Core::Models::Result.where(:command_id => cmdid).each { |result|
results.push({'date' => result.date, 'data' => JSON.parse(result.data)})
}
rescue
@@ -380,7 +380,7 @@ class ShellInterface
'results' => []
}
@nh = BeEF::Core::Models::NetworkHost
hosts = @nh.all(:hooked_browser_id => self.targetsession)
hosts = @nh.where(:hooked_browser_id => self.targetsession)
# add property to summary hash
if not hosts.empty?
@@ -418,7 +418,7 @@ class ShellInterface
'results' => []
}
@ns = BeEF::Core::Models::NetworkService
services = @ns.all(:hooked_browser_id => self.targetsession)
services = @ns.where(:hooked_browser_id => self.targetsession)
# add property to summary hash
if not services.empty?

View File

@@ -7,6 +7,7 @@
-->
<head>
<title>BeEF Basic Demo</title>
<meta charset="utf-8"/>
<script>
var commandModuleStr = '<script src="<%= @hook_uri %>" type="text/javascript"><\/script>';
document.write(commandModuleStr);

View File

@@ -48,9 +48,10 @@ module BeEF
pattern = Regexp.new(rule[:pattern], Regexp::IGNORECASE)
$VERBOSE = verbose
@database.first_or_create(
{ :resource => rule[:resource], :pattern => pattern.source },
{ :response => rule[:response] }
@database.find_or_create_by(
:resource => rule[:resource].to_s,
:pattern => pattern.source,
:response => rule[:response]
).id
end
end
@@ -62,9 +63,11 @@ module BeEF
# @return [Hash] hash representation of rule (empty hash if rule wasn't found)
def get_rule(id)
@lock.synchronize do
if is_valid_id?(id)
rule = @database.get(id)
rule.nil? ? {} : to_hash(rule)
begin
rule = @database.find(id)
return to_hash(rule)
rescue ActiveRecord::RecordNotFound
return nil
end
end
end
@@ -76,10 +79,15 @@ module BeEF
# @return [Boolean] true if rule was removed, otherwise false
def remove_rule!(id)
@lock.synchronize do
if is_valid_id?(id)
rule = @database.get(id)
rule.nil? ? false : rule.destroy
begin
rule = @database.find(id)
if not rule.nil? and rule.destroy
return true
end
rescue ActiveRecord::RecordNotFound
return nil
end
return false
end
end
@@ -94,14 +102,18 @@ module BeEF
#
# @return [Array<Hash>] DNS ruleset (empty array if no rules are currently defined)
def get_ruleset
@lock.synchronize { @database.collect { |rule| to_hash(rule) } }
@lock.synchronize { @database.all { |rule| to_hash(rule) } }
end
# Removes the entire DNS ruleset.
#
# @return [Boolean] true if ruleset was destroyed, otherwise false
def remove_ruleset!
@lock.synchronize { @database.destroy }
@lock.synchronize do
if @database.destroy_all
return true
end
end
end
# Starts the DNS server.
@@ -161,7 +173,7 @@ module BeEF
catch (:done) do
# Find rules matching the requested resource class
resources = @database.all(:resource => resource)
resources = @database.where(:resource => resource)
throw :done if resources.length == 0
# Narrow down search by finding a matching pattern
@@ -257,7 +269,7 @@ module BeEF
#
# @return [String] resource name stripped of any module/class names
def format_resource(resource)
/::(\w+)$/.match(resource.name)[1]
/::(\w+)$/.match(resource)[1]
end
end

View File

@@ -9,31 +9,28 @@ module BeEF
module Dns
# Represents an individual DNS rule.
class Rule
include DataMapper::Resource
storage_names[:default] = 'extension_dns_rules'
property :id, String, :key => true
property :pattern, Object, :required => true
property :resource, Object, :required => true
property :response, Object, :required => true
property :callback, Object, :required => true
class Rule < BeEF::Core::Model
# Hooks the model's "save" event. Validates pattern/response and generates a rule identifier.
before :save do |rule|
before_save :check_rule
self.table_name = 'dns_rule'
serialize :response, Array
private
def check_rule
begin
validate_pattern(rule.pattern)
rule.callback = format_callback(rule.resource, rule.response)
validate_pattern(self.pattern)
self.callback = format_callback(self.resource.constantize, self.response)
rescue InvalidDnsPatternError, UnknownDnsResourceError, InvalidDnsResponseError => e
print_error e.message
throw :halt
end
rule.id = BeEF::Core::Crypto.dns_rule_id
#self.id = BeEF::Core::Crypto.dns_rule_id
end
private
# Verifies that the given pattern is valid (i.e. non-empty, no null's or printable characters).
def validate_pattern(pattern)
raise InvalidDnsPatternError unless BeEF::Filters.is_non_empty_string?(pattern) &&

View File

@@ -32,7 +32,7 @@ module Events
end
# validates that a hooked browser with the beef_hook token exists in the db
zombie = Z.first(:session => beef_hook) || nil
zombie = Z.where(:session => beef_hook).first || nil
if zombie.nil?
print_error "[EVENTS] Invalid beef hook id: the hooked browser cannot be found in the database"
return

View File

@@ -6,19 +6,9 @@
module BeEF
module Core
module Models
class IpecExploits
class IpecExploits < BeEF::Core::Model
include DataMapper::Resource
#todo: use this table when we'll have a bigger IPEC exploits choice
storage_names[:default] = 'extension_ipec_exploits'
property :id, Serial
property :name, Text, :lazy => false
property :protocol, String, :lazy => false
property :os, String, :lazy => false
has n, :extension_ipec_exploits_run, 'IpecExploitsRun'
has_many :ipec_exploits_run
end

View File

@@ -6,18 +6,9 @@
module BeEF
module Core
module Models
class IpecExploitsRun
class IpecExploitsRun < BeEF::Core::Model
include DataMapper::Resource
#todo: use this table when we'll have a bigger IPEC exploits choice
storage_names[:default] = 'extension_ipec_exploits_run'
property :id, Serial
property :launched, Boolean, :lazy => false
property :http_headers, Text, :lazy => false
property :junk_size, String, :length => 3, :lazy => false
belongs_to :ipec_exploits
belongs_to :ipec_exploit
end

View File

@@ -118,7 +118,7 @@ module BeEF
msf = BeEF::Extension::Metasploit::RpcClient.instance
if msf_key != nil && msf.login
msf_module_options = msf.call('module.options', 'exploit', msf_key)
com = BeEF::Core::Models::CommandModule.first(:name => mod)
com = BeEF::Core::Models::CommandModule.where(:name => mod).first
if msf_module_options
options = BeEF::Extension::Metasploit.translate_options(msf_module_options)
options << {
@@ -193,7 +193,7 @@ module BeEF
if msf_key != nil && msf.login
msf_module_options = msf.call('module.options', 'payload', payload)
com = BeEF::Core::Models::CommandModule.first(:name => mod)
com = BeEF::Core::Models::CommandModule.where(:name => mod).first
if msf_module_options
options = BeEF::Extension::Metasploit.translate_options(msf_module_options)
return options

View File

@@ -8,7 +8,7 @@
class Msf_module < BeEF::Core::Command
def output
command = BeEF::Core::Models::Command.first(:id => @command_id)
command = BeEF::Core::Models::Command.find(@command_id)
data = JSON.parse(command['data'])
sploit_url = data[0]['sploit_url']

View File

@@ -9,19 +9,8 @@ module BeEF
#
# Table stores each host identified on the zombie browser's network(s)
#
class NetworkHost
include DataMapper::Resource
storage_names[:default] = 'network_host'
property :id, Serial
property :hooked_browser_id, Text, lazy: false
property :ip, Text, lazy: false
property :hostname, String, lazy: false
property :type, String, lazy: false # proxy, router, gateway, dns, etc
property :os, String, lazy: false
property :mac, String, lazy: false
property :lastseen, String, length: 15
class NetworkHost < BeEF::Core::Model
belongs_to :hooked_browser
#
# Stores a network host in the data store
@@ -50,23 +39,24 @@ module BeEF
new_host[:hooked_browser_id] = host[:hooked_browser_id]
new_host[:ip] = host[:ip]
new_host[:hostname] = host[:hostname] unless host[:hostname].nil?
new_host[:type] = host[:type] unless host[:type].nil?
new_host[:ntype] = host[:ntype] unless host[:ntype].nil?
new_host[:os] = host[:os] unless host[:os].nil?
new_host[:mac] = host[:mac] unless host[:mac].nil?
# if host already exists in data store with the same details
# then update lastseen and return
existing_host = BeEF::Core::Models::NetworkHost.all(new_host)
existing_host = BeEF::Core::Models::NetworkHost.where(hooked_browser_id: new_host[:hooked_browser_id], ip: new_host[:ip]).limit(1)
unless existing_host.empty?
existing_host.update(lastseen: Time.new.to_i)
existing_host = existing_host.first
existing_host.lastseen = Time.new.to_i
existing_host.save!
return
end
# store the new network host details
new_host[:lastseen] = Time.new.to_i
network_host = BeEF::Core::Models::NetworkHost.new(new_host)
result = network_host.save
if result.nil?
if network_host.save
print_error 'Failed to save network host'
return
end
@@ -83,7 +73,7 @@ module BeEF
return
end
host = BeEF::Core::Models::NetworkHost.get(id.to_i)
host = BeEF::Core::Models::NetworkHost.find(id.to_i)
if host.nil?
print_error "Failed to remove network host [id: #{id}]. Host does not exist."
return
@@ -100,7 +90,7 @@ module BeEF
hooked_browser_id: hooked_browser_id,
ip: ip,
hostname: hostname,
type: type,
ntype: ntype,
os: os,
mac: mac,
lastseen: lastseen

View File

@@ -9,17 +9,9 @@ module BeEF
#
# Table stores each open port identified on the zombie browser's network(s)
#
class NetworkService
include DataMapper::Resource
storage_names[:default] = 'network_service'
class NetworkService < BeEF::Core::Model
belongs_to :hooked_browser
property :id, Serial
property :hooked_browser_id, Text, lazy: false
property :proto, String, lazy: false
property :ip, Text, lazy: false
property :port, String, lazy: false
property :type, String, lazy: false
#
# Stores a network service in the data store
@@ -48,19 +40,20 @@ module BeEF
end
# store the returned network host details
BeEF::Core::Models::NetworkHost.add(
BeEF::Core::Models::NetworkHost.create(
hooked_browser_id: service[:hooked_browser_id],
ip: service[:ip]
)
# prevent duplicates
return unless BeEF::Core::Models::NetworkService.all(
total = BeEF::Core::Models::NetworkService.where(
hooked_browser_id: service[:hooked_browser_id],
proto: service[:proto],
ip: service[:ip],
port: service[:port],
type: service[:type]
).empty?
ntype: service[:ntype]
).length
return if total > 0
# store the returned network service details
network_service = BeEF::Core::Models::NetworkService.new(
@@ -68,10 +61,9 @@ module BeEF
proto: service[:proto],
ip: service[:ip],
port: service[:port],
type: service[:type]
ntype: service[:ntype]
)
result = network_service.save
if result.nil?
if network_service.save
print_error 'Failed to save network service'
return
end
@@ -87,7 +79,7 @@ module BeEF
proto: proto,
ip: ip,
port: port,
type: type
ntype: ntype
}
end
end

View File

@@ -27,7 +27,7 @@ module BeEF
# Returns the entire list of network hosts for all zombies
get '/hosts' do
begin
hosts = @nh.all(unique: true, order: [:id.asc])
hosts = @nh.all.distinct.order(:id)
count = hosts.length
result = {}
@@ -47,7 +47,7 @@ module BeEF
# Returns the entire list of network services for all zombies
get '/services' do
begin
services = @ns.all(unique: true, order: [:id.asc])
services = @ns.all.distinct.order(:id)
count = services.length
result = {}
@@ -69,7 +69,7 @@ module BeEF
begin
id = params[:id]
hosts = @nh.all(hooked_browser_id: id, unique: true, order: [:id.asc])
hosts = @nh.where(hooked_browser_id: id).distinct.order(:id)
count = hosts.length
result = {}
@@ -94,7 +94,7 @@ module BeEF
begin
id = params[:id]
services = @ns.all(hooked_browser_id: id, unique: true, order: [:id.asc])
services = @ns.where(hooked_browser_id: id).distinct.order(:id)
count = services.length
result = {}
@@ -119,7 +119,7 @@ module BeEF
begin
id = params[:id]
host = @nh.all(id: id)
host = @nh.find(id)
raise InvalidParamError, 'id' if host.nil?
halt 404 if host.empty?
@@ -139,7 +139,7 @@ module BeEF
id = params[:id]
raise InvalidParamError, 'id' unless BeEF::Filters.nums_only?(id)
host = @nh.all(id: id)
host = @nh.find(id)
halt 404 if host.nil?
result = {}
@@ -159,7 +159,7 @@ module BeEF
begin
id = params[:id]
service = @ns.all(id: id)
service = @ns.find(id)
raise InvalidParamError, 'id' if service.nil?
halt 404 if service.empty?

View File

@@ -137,10 +137,10 @@ module BeEF
# Wait for the HTTP response to be stored in the db.
# TODO: re-implement this with EventMachine or with the Observer pattern.
while H.first(:id => http.id).has_ran != "complete"
while H.find(http.id).has_ran != "complete"
sleep 0.5
end
@response = H.first(:id => http.id)
@response = H.find(http.id)
print_debug "[PROXY] <-- Response for request ##{@response.id} to [#{@response.path}] on domain [#{@response.domain}:#{@response.port}] correctly processed"
response_body = @response['response_data']
@@ -191,7 +191,7 @@ module BeEF
end
def get_tunneling_proxy
proxy_browser = HB.first(:is_proxy => true)
proxy_browser = HB.where(:is_proxy => true).first
unless proxy_browser.nil?
return proxy_browser.session.to_s
end

View File

@@ -35,8 +35,8 @@ module BeEF
result['success'] = false
return result.to_json if hb_id.nil?
hooked_browser = @hb.first(:session => hb_id)
previous_proxy_hb = @hb.first(:is_proxy => true)
hooked_browser = @hb.where(:session => hb_id).first
previous_proxy_hb = @hb.where(:is_proxy => true).first
# if another HB is currently set as tunneling proxy, unset it
unless previous_proxy_hb.nil?

View File

@@ -20,7 +20,7 @@ module BeEF
@body = body
# Generate all the requests and output them to the hooked browser
output = []
BeEF::Core::Models::Http.all(:hooked_browser_id => hb.session, :has_ran => "waiting").each { |h|
BeEF::Core::Models::Http.where(:hooked_browser_id => hb.session, :has_ran => "waiting").each { |h|
output << self.requester_parse_db_request(h)
}

View File

@@ -41,11 +41,11 @@ module BeEF
end
# validates that a hooked browser with the beef_hook token exists in the db
zombie_db = Z.first(:session => beef_hook) || nil
zombie_db = Z.where(:session => beef_hook).first || nil
(print_error "Invalid beefhook id: the hooked browser cannot be found in the database";return) if zombie_db.nil?
# validates that we have such a http request saved in the db
http_db = H.first(:id => request_id.to_i, :hooked_browser_id => zombie_db.session) || nil
http_db = H.where(:id => request_id.to_i, :hooked_browser_id => zombie_db.session).first || nil
if http_db.nil?
print_error "Invalid http_db: no such request found in the database"
return

View File

@@ -9,72 +9,14 @@ module Models
#
# Table stores the http requests and responses from the requester.
#
class Http
class Http < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_requester_http'
property :id, Serial
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The http request to perform. In clear text.
property :request, Text, :lazy => true
# Boolean value as string to say whether cross-domain requests are allowed
property :allow_cross_domain, Text, :lazy => false, :default => "true"
# The http response body received. In clear text.
property :response_data, Binary, :lazy => true, :length => 2097152
# The http response code. Useful to handle cases like 404, 500, 302, ...
property :response_status_code, Integer, :lazy => true
# The http response code. Human-readable code: success, error, ecc..
property :response_status_text, Text, :lazy => true
# The port status. closed, open or not http
property :response_port_status, Text, :lazy => true
# The XHR Http response raw headers
property :response_headers, Text, :lazy => true
# The http response method. GET or POST.
property :method, Text, :lazy => false
# The content length for the request.
property :content_length, Text, :lazy => false, :default => 0
# The request protocol/scheme (http/https)
property :proto, Text, :lazy => false
# The domain on which perform the request.
property :domain, Text, :lazy => false
# The port on which perform the request.
property :port, Text, :lazy => false
# Boolean value to say if the request was cross-domain
property :has_ran, Text, :lazy => false, :default => "waiting"
# The path of the request.
# Example: /secret.html
property :path, Text, :lazy => false
# The date at which the http response has been saved.
property :response_date, DateTime, :lazy => false
# The date at which the http request has been saved.
property :request_date, DateTime, :lazy => false
#
# Removes a request/response from the data store
#
def self.delete(id)
(print_error "Failed to remove response. Invalid response ID."; return) if id.to_s !~ /\A\d+\z/
r = BeEF::Core::Models::Http.get(id.to_i)
r = BeEF::Core::Models::Http.find(id.to_i)
(print_error "Failed to remove response [id: #{id}]. Response does not exist."; return) if r.nil?
r.destroy
end

View File

@@ -33,7 +33,7 @@ module BeEF
id = params[:id]
raise InvalidParamError, 'id' unless BeEF::Filters::nums_only?(id)
requests = H.all(:id => id)
requests = H.find(id)
halt 404 if requests.nil?
result = {}
@@ -59,7 +59,7 @@ module BeEF
id = params[:id]
raise InvalidParamError, 'id' unless BeEF::Filters.is_valid_hook_session_id?(id)
requests = H.all(:hooked_browser_id => id)
requests = H.where(:hooked_browser_id => id)
halt 404 if requests.nil?
result = {}
@@ -85,7 +85,7 @@ module BeEF
id = params[:id]
raise InvalidParamError, 'id' unless BeEF::Filters::nums_only?(id)
responses = H.first(:id => id) || nil
responses = H.find(id) || nil
halt 404 if responses.nil?
result = {}
@@ -108,7 +108,7 @@ module BeEF
id = params[:id]
raise InvalidParamError, 'id' unless BeEF::Filters::nums_only?(id)
responses = H.first(:id => id) || nil
responses = H.find(id) || nil
halt 404 if responses.nil?
result = {}
@@ -130,7 +130,7 @@ module BeEF
proto = params[:proto].to_s || 'http'
raw_request = params['raw_request'].to_s
zombie = HB.first(:session => id) || nil
zombie = HB.where(:session => id).first || nil
halt 404 if zombie.nil?

View File

@@ -6,15 +6,7 @@
module BeEF
module Core
module Models
class Interceptor
include DataMapper::Resource
storage_names[:default] = 'extension_seng_interceptor'
property :id, Serial
property :ip, Text, :lazy => false
property :post_data, Text, :lazy => false
class Interceptor < BeEF::Core::Model
belongs_to :webcloner

View File

@@ -7,15 +7,8 @@ module BeEF
module Core
module Models
class Massmailer
class Massmailer < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_seng_massmailer'
property :id, Serial
#todo fields
end
end

View File

@@ -6,18 +6,9 @@
module BeEF
module Core
module Models
class Webcloner
class Webcloner < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_seng_webcloner'
property :id, Serial
property :uri, Text, :lazy => false
property :mount, Text, :lazy => false
has n, :extension_seng_interceptor, 'Interceptor'
has_many :interceptors
end

View File

@@ -29,7 +29,7 @@ module BeEF
rtcmanagementoutput = []
# Get all RTCSignals for this browser
BeEF::Core::Models::Rtcsignal.all(:target_hooked_browser_id => hb.id, :has_sent => "waiting").each { |h|
BeEF::Core::Models::Rtcsignal.where(:target_hooked_browser_id => hb.id, :has_sent => "waiting").each { |h|
# output << self.requester_parse_db_request(h)
rtcsignaloutput << h.signal
h.has_sent = "sent"
@@ -37,7 +37,7 @@ module BeEF
}
# Get all RTCManagement messages for this browser
BeEF::Core::Models::Rtcmanage.all(:hooked_browser_id => hb.id, :has_sent => "waiting").each {|h|
BeEF::Core::Models::Rtcmanage.where(:hooked_browser_id => hb.id, :has_sent => "waiting").each {|h|
rtcmanagementoutput << h.message
h.has_sent = "sent"
h.save

View File

@@ -9,23 +9,8 @@ module Models
#
# Table stores the queued up JS commands for managing the client-side webrtc logic.
#
class Rtcmanage
class Rtcmanage < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_webrtc_rtcmanage'
property :id, Serial
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The message
property :message, Text, :lazy => true
# Boolean value to say if the signal has been sent to the target peer
property :has_sent, Text, :lazy => false, :default => "waiting"
# Starts the RTCPeerConnection process, establishing a WebRTC connection between the caller and the receiver
def self.initiate(caller, receiver, verbosity = false)
stunservers = BeEF::Core::Configuration.instance.get("beef.extension.webrtc.stunservers")
@@ -34,25 +19,25 @@ module Models
# Add the beef.webrtc.start() JavaScript call into the Rtcmanage table - this will be picked up by the browser on next hook.js poll
# This is for the Receiver
r = BeEF::Core::Models::Rtcmanage.new(:hooked_browser_id => receiver, :message => "beef.webrtc.start(0,#{caller},JSON.stringify(#{turnservers}),JSON.stringify(#{stunservers}),#{verbosity});")
r.save
r.save!
# This is the same beef.webrtc.start() JS call, but for the Caller
r = BeEF::Core::Models::Rtcmanage.new(:hooked_browser_id => caller, :message => "beef.webrtc.start(1,#{receiver},JSON.stringify(#{turnservers}),JSON.stringify(#{stunservers}),#{verbosity});")
r.save
r.save!
end
# Advises a browser to send an RTCDataChannel message to its peer
# Similar to the initiate method, this loads up a JavaScript call to the beefrtcs[peerid].sendPeerMsg() function call
def self.sendmsg(from, to, message)
r = BeEF::Core::Models::Rtcmanage.new(:hooked_browser_id => from, :message => "beefrtcs[#{to}].sendPeerMsg('#{message}');")
r.save
r.save!
end
# Gets the browser to run the beef.webrtc.status() JavaScript function
# This JS function will return it's values to the /rtcmessage handler
def self.status(id)
r = BeEF::Core::Models::Rtcmanage.new(:hooked_browser_id => id, :message => "beef.webrtc.status(#{id});")
r.save
r.save!
end
end

View File

@@ -13,32 +13,11 @@ module Models
#
class Rtcmodulestatus
class Rtcmodulestatus < BeEF::Core::Model
belongs_to :hooked_browser
belongs_to :command_module
include DataMapper::Resource
storage_names[:default] = 'extension_webrtc_rtcmodulestatus'
property :id, Serial
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The hooked browser's IP
# property :hooked_browser_ip, Text, :lazy => false
# The target hooked browser id
property :target_hooked_browser_id, Text, :lazy => false
# The command module ID
property :command_module_id, Text, :lazy => false
# The status field
property :status, Text, :lazy => true
# Timestamps
property :created_at, DateTime
property :updated_at, DateTime
end

View File

@@ -9,25 +9,9 @@ module Models
#
# Table stores the webrtc signals from a hooked_browser, directed to a target_hooked_browser
#
class Rtcsignal
include DataMapper::Resource
storage_names[:default] = 'extension_webrtc_rtcsignals'
property :id, Serial
class Rtcsignal < BeEF::Core::Model
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The target hooked browser id
property :target_hooked_browser_id, Text, :lazy => false
# The WebRTC signal to submit. In clear text.
property :signal , Text, :lazy => true
# Boolean value to say if the signal has been sent to the target peer
property :has_sent, Text, :lazy => false, :default => "waiting"
belongs_to :hooked_browser
end

View File

@@ -13,32 +13,9 @@ module Models
#
class Rtcstatus
class Rtcstatus < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_webrtc_rtcstatus'
property :id, Serial
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The hooked browser's IP
# property :hooked_browser_ip, Text, :lazy => false
# The target hooked browser id
property :target_hooked_browser_id, Text, :lazy => false
# The target hooked browser's IP
# property :target_hooked_browser_ip, Text, :lazy => false
# The status field
property :status, Text, :lazy => true
# Timestamps
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :hooked_browser
end

View File

@@ -177,7 +177,7 @@ module BeEF
begin
id = params[:id]
events = BeEF::Core::Models::Rtcstatus.all(:hooked_browser_id => id)
events = BeEF::Core::Models::Rtcstatus.where(:hooked_browser_id => id)
events_json = []
count = events.length
@@ -227,7 +227,7 @@ module BeEF
begin
id = params[:id]
events = BeEF::Core::Models::Rtcmodulestatus.all(:hooked_browser_id => id)
events = BeEF::Core::Models::Rtcmodulestatus.where(:hooked_browser_id => id)
events_json = []
count = events.length
@@ -301,13 +301,13 @@ module BeEF
raise InvalidParamError, 'message' if message.nil?
if message === "!gostealth"
stat = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => fromhb.to_i, :target_hooked_browser_id => tohb.to_i) || nil
stat = BeEF::Core::Models::Rtcstatus.where(:hooked_browser_id => fromhb.to_i, :target_hooked_browser_id => tohb.to_i).first || nil
unless stat.nil?
stat.status = "Selected browser has commanded peer to enter stealth"
stat.updated_at = Time.now
stat.save
end
stat2 = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => tohb.to_i, :target_hooked_browser_id => fromhb.to_i) || nil
stat2 = BeEF::Core::Models::Rtcstatus.where(:hooked_browser_id => tohb.to_i, :target_hooked_browser_id => fromhb.to_i).first || nil
unless stat2.nil?
stat2.status = "Peer has commanded selected browser to enter stealth"
stat2.updated_at = Time.now
@@ -382,8 +382,7 @@ module BeEF
# Find the module, modify it, send it to be executed on the tohb
# Validate the command module by ID
command_module = BeEF::Core::Models::CommandModule.first(
:id => cmdid)
command_module = BeEF::Core::Models::CommandModule.find(cmdid)
error 404 if command_module.nil?
error 404 if command_module.path.nil?

View File

@@ -18,10 +18,10 @@ module BeEF
def start_scan(hb, body)
@body = body
config = BeEF::Core::Configuration.instance
hb = BeEF::Core::Models::HookedBrowser.first(:id => hb.id)
hb = BeEF::Core::Models::HookedBrowser.find(hb.id)
#TODO: we should get the xssrays_scan table with more accuracy, if for some reasons we requested
#TODO: 2 scans on the same hooked browsers, "first" could not get the right result we want
xs = BeEF::Core::Models::Xssraysscan.first(:hooked_browser_id => hb.id, :is_started => false)
xs = BeEF::Core::Models::Xssraysscan.where(:hooked_browser_id => hb.id, :is_started => false).first
# stop here if there are no XssRays scans to be started
return if xs == nil || xs.is_started == true

View File

@@ -18,7 +18,7 @@ module BeEF
# raise an error if it's null or not found in the DB
beef_hook = params[:hbsess] || nil
if beef_hook.nil? || HB.first(:session => beef_hook).nil?
if beef_hook.nil? || HB.where(:session => beef_hook).first.nil?
print_error "[XSSRAYS] Invalid beef hook ID: the hooked browser cannot be found in the database"
return
end
@@ -53,8 +53,8 @@ module BeEF
# parse incoming rays: rays are verified XSS, as the attack vector is calling back BeEF when executed.
def parse_rays(rays_scan_id)
xssrays_scan = XS.first(:id => rays_scan_id)
hooked_browser = HB.first(:session => params[:hbsess])
xssrays_scan = XS.find(rays_scan_id)
hooked_browser = HB.where(:session => params[:hbsess]).first
if xssrays_scan.nil?
print_error "[XSSRAYS] Invalid scan"
@@ -76,7 +76,7 @@ module BeEF
# finalize the XssRays scan marking the scan as finished in the db
def finalize_scan(rays_scan_id)
xssrays_scan = BeEF::Core::Models::Xssraysscan.first(:id => rays_scan_id)
xssrays_scan = BeEF::Core::Models::Xssraysscan.find(rays_scan_id)
if xssrays_scan.nil?
print_error "[XSSRAYS] Invalid scan"

View File

@@ -9,26 +9,8 @@ module Models
#
# Store the rays details, basically verified XSS vulnerabilities
#
class Xssraysdetail
include DataMapper::Resource
storage_names[:default] = 'extension_xssrays_details'
property :id, Serial
# The hooked browser id
property :hooked_browser_id, Text, :lazy => false
# The XssRays vector name for the vulnerability
property :vector_name, Text, :lazy => true
# The XssRays vector method (GET or POST) for the vulnerability
property :vector_method, Text, :lazy => true
# The XssRays Proof of Concept for the vulnerability
property :vector_poc, Text, :lazy => true
class Xssraysdetail < BeEF::Core::Model
belongs_to :hooked_browser
belongs_to :xssraysscan
end

View File

@@ -9,27 +9,9 @@ module Models
#
# Store the XssRays scans started and finished, with relative ID
#
class Xssraysscan
class Xssraysscan < BeEF::Core::Model
include DataMapper::Resource
storage_names[:default] = 'extension_xssrays_scans'
property :id, Serial
property :hooked_browser_id, Text, :lazy => false
property :scan_start, DateTime, :lazy => true
property :scan_finish, DateTime, :lazy => true
property :domain, Text, :lazy => true
property :cross_domain, Text, :lazy => true
property :clean_timeout, Integer, :lazy => false
property :is_started, Boolean, :lazy => false, :default => false
property :is_finished, Boolean, :lazy => false, :default => false
has n, :extension_xssrays_details, 'Xssraysdetail'
has_many :xssrays_details
end

View File

@@ -34,7 +34,7 @@ module BeEF
# Returns the entire list of rays for all zombies
get '/rays' do
begin
rays = XD.all(:unique => true, :order => [:id.asc])
rays = XD.all.distinct.order(:id)
count = rays.length
result = {}
@@ -55,7 +55,7 @@ module BeEF
begin
id = params[:id]
rays = XD.all(:hooked_browser_id => id, :unique => true, :order => [:id.asc])
rays = XD.where(:hooked_browser_id => id).distinct.order(:id)
count = rays.length
result = {}
@@ -77,7 +77,7 @@ module BeEF
# Returns the entire list of scans for all zombies
get '/scans' do
begin
scans = XS.all(:unique => true, :order => [:id.asc])
scans = XS.distinct.order(:id)
count = scans.length
result = {}
@@ -98,7 +98,7 @@ module BeEF
begin
id = params[:id]
scans = XS.all(:hooked_browser_id => id, :unique => true, :order => [:id.asc])
scans = XS.where(:hooked_browser_id => id).distinct.order(:id)
count = scans.length
result = {}
@@ -122,7 +122,7 @@ module BeEF
begin
id = params[:id]
hooked_browser = HB.first(:session => id, :unique => true, :order => [:id.asc])
hooked_browser = HB.where(:session => id).distinct.order(:id)
if hooked_browser.nil?
print_error "[XSSRAYS] Invalid hooked browser ID"

Some files were not shown because too many files have changed in this diff Show More