Refactored WebSocket code.

This commit is contained in:
antisnatchor
2012-08-25 10:18:56 +01:00
parent 5400696c40
commit 50e7a1c206
4 changed files with 141 additions and 77 deletions

4
beef
View File

@@ -124,9 +124,9 @@ print_info "RESTful API key: #{BeEF::Core::Crypto::api_token}"
#@note Starts the WebSocket server
if config.get("beef.http.websocket.enable")
BeEF::Core::Websocket::Websocket.instance
print_info "Starting WebSocket server on port [#{config.get("beef.http.websocket.port").to_i}], secure [#{config.get("beef.http.websocket.secure")}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
print_info "Starting WebSocket server on port [#{config.get("beef.http.websocket.port").to_i}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
if config.get("beef.http.websocket.secure")
print_info "Starting WebSocket-Secured server on port [#{config.get("beef.http.websocket.secure_port").to_i}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
print_info "Starting WebSocketSecure server on port [#{config.get("beef.http.websocket.secure_port").to_i}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
end
end

View File

@@ -17,7 +17,7 @@
beef:
version: '0.4.3.7-alpha'
debug: true
debug: false
restrictions:
# subnet of browser ip addresses that can hook to the framework
@@ -42,9 +42,9 @@ beef:
# Prefer WebSockets over XHR-polling when possible.
websocket:
enable: false
secure: false # use WebSocketSecure work only on https domain and whit https support enabled in BeEF
port: 61985 # good success rate through proxies
secure_port: 61986 #to accept wss connection
secure: true # use WebSocketSecure work only on https domain and whit https support enabled in BeEF
port: 61985 # WS: good success rate through proxies
secure_port: 61986 # WSS
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

@@ -28,7 +28,7 @@ beef.websocket = {
var webSocketSecure = <%= @websocket_secure %>;
var protocol = "ws://";
//console.log("We are inside init");
/*use wss only if hooked domain is under tls*/
/*use wss only if hooked domain is under https. Mixed-content in WS is quite different from a non-WS context*/
if(webSocketSecure && window.location.protocol=="https:"){
protocol = "wss://";
webSocketPort= <%= @websocket_sec_port %>;

View File

@@ -33,84 +33,150 @@ module BeEF
def initialize
secure = @@config.get("beef.http.websocket.secure") #&& @@config.get("beef.http.https.enable")
secure = @@config.get("beef.http.websocket.secure")
@root_dir = File.expand_path('../../../../../', __FILE__)
if (secure)
#Thread for websocket-secure
Thread.new {
port = @@config.get("beef.http.websocket.secure_port")
sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
EventMachine.run {
wsopt = {:host => "0.0.0.0", :port => port, :secure => true,
:tls_options => {
:private_key_file => @root_dir+"/"+@@config.get("beef.http.https.key"),
:cert_chain_file => @root_dir+"/"+ @@config.get("beef.http.https.cert")
}
}
EventMachine::WebSocket.start(wsopt) do |ws|
begin
print_debug "New WebSocket-secured channel open."
ws.onmessage { |msg|
msg_hash = JSON.parse("#{msg}")
#@note messageHash[result] is Base64 encoded
if (msg_hash["cookie"]!= nil)
print_debug("WebSocket-secured - Browser says helo! WebSocket is running")
#insert new connection in activesocket
@@activeSocket["#{msg_hash["cookie"]}"] = ws
print_debug("WebSocket-secured - activeSocket content [#{@@activeSocket}]")
elsif msg_hash["alive"] != nil
hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
unless hooked_browser.nil?
hooked_browser.lastseen = Time.new.to_i
hooked_browser.count!
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.each { |command| add_command_instructions(command, hooked_browser) }
#@todo antisnatchor:
#@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions
#Check if new forged requests need to be sent (Requester/TunnelingProxy)
dhook = BeEF::Extension::Requester::API::Hook.new
dhook.requester_run(hooked_browser, '')
#Check if new XssRays scan need to be started
xssrays = BeEF::Extension::Xssrays::API::Scan.new
xssrays.start_scan(hooked_browser, '')
end
else
#json recv is a cmd response decode and send all to
#we have to call dynamicreconstructor handler camp must be websocket
#print_debug("Received from WebSocket #{messageHash}")
execute(msg_hash)
end
}
rescue Exception => e
print_error "WebSocket-secured error: #{e}"
end
end
}
ws_secure_options = {:host => "0.0.0.0", :port => @@config.get("beef.http.websocket.secure_port"), :secure => true,
:tls_options => {
:private_key_file => @root_dir+"/"+@@config.get("beef.http.https.key"),
:cert_chain_file => @root_dir+"/"+ @@config.get("beef.http.https.cert")
}
}
# @note Start a WSS server socket
start_websocket_server(ws_secure_options, true)
end
#Thread for websocket
# @note Start a WS server socket
ws_options = {:host => "0.0.0.0", :port => @@config.get("beef.http.websocket.port")}
start_websocket_server(ws_options,false)
# #Thread for websocket-secure
# Thread.new {
# port = @@config.get("beef.http.websocket.secure_port")
# sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
# EventMachine.run {
#
# wsopt = {:host => "0.0.0.0", :port => port, :secure => true,
# :tls_options => {
# :private_key_file => @root_dir+"/"+@@config.get("beef.http.https.key"),
# :cert_chain_file => @root_dir+"/"+ @@config.get("beef.http.https.cert")
# }
# }
#
#
# EventMachine::WebSocket.start(wsopt) do |ws|
# begin
# print_debug "New WebSocket-secured channel open."
# ws.onmessage { |msg|
# msg_hash = JSON.parse("#{msg}")
# #@note messageHash[result] is Base64 encoded
# if (msg_hash["cookie"]!= nil)
# print_debug("WebSocket-secured - Browser says helo! WebSocket is running")
# #insert new connection in activesocket
# @@activeSocket["#{msg_hash["cookie"]}"] = ws
# print_debug("WebSocket-secured - activeSocket content [#{@@activeSocket}]")
# elsif msg_hash["alive"] != nil
# hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
# unless hooked_browser.nil?
# hooked_browser.lastseen = Time.new.to_i
# hooked_browser.count!
# 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.each { |command| add_command_instructions(command, hooked_browser) }
#
# #@todo antisnatchor:
# #@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions
# #Check if new forged requests need to be sent (Requester/TunnelingProxy)
# dhook = BeEF::Extension::Requester::API::Hook.new
# dhook.requester_run(hooked_browser, '')
#
# #Check if new XssRays scan need to be started
# xssrays = BeEF::Extension::Xssrays::API::Scan.new
# xssrays.start_scan(hooked_browser, '')
# end
# else
# #json recv is a cmd response decode and send all to
# #we have to call dynamicreconstructor handler camp must be websocket
# #print_debug("Received from WebSocket #{messageHash}")
# execute(msg_hash)
# end
# }
# rescue Exception => e
# print_error "WebSocket-secured error: #{e}"
# end
# end
# }
#
# }
#
##Thread for websocket
#Thread.new {
# port = @@config.get("beef.http.websocket.port")
# sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
# EventMachine.run {
#
# wsopt = {:host => "0.0.0.0", :port => port}
#
#
# EventMachine::WebSocket.start(wsopt) do |ws|
# begin
# print_debug "New WebSocket channel open."
# ws.onmessage { |msg|
# msg_hash = JSON.parse("#{msg}")
# #@note messageHash[result] is Base64 encoded
# if (msg_hash["cookie"]!= nil)
# print_debug("WebSocket - Browser says helo! WebSocket is running")
# #insert new connection in activesocket
# @@activeSocket["#{msg_hash["cookie"]}"] = ws
# print_debug("WebSocket - activeSocket content [#{@@activeSocket}]")
# elsif msg_hash["alive"] != nil
# hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
# unless hooked_browser.nil?
# hooked_browser.lastseen = Time.new.to_i
# hooked_browser.count!
# 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.each { |command| add_command_instructions(command, hooked_browser) }
#
# #@todo antisnatchor:
# #@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions
# #Check if new forged requests need to be sent (Requester/TunnelingProxy)
# dhook = BeEF::Extension::Requester::API::Hook.new
# dhook.requester_run(hooked_browser, '')
#
# #Check if new XssRays scan need to be started
# xssrays = BeEF::Extension::Xssrays::API::Scan.new
# xssrays.start_scan(hooked_browser, '')
# end
# else
# #json recv is a cmd response decode and send all to
# #we have to call dynamicreconstructor handler camp must be websocket
# #print_debug("Received from WebSocket #{messageHash}")
# execute(msg_hash)
# end
# }
# rescue Exception => e
# print_error "WebSocket error: #{e}"
# end
# end
# }
#}
end
def start_websocket_server(ws_options, secure)
Thread.new {
port = @@config.get("beef.http.websocket.port")
sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
EventMachine.run {
wsopt = {:host => "0.0.0.0", :port => port}
EventMachine::WebSocket.start(wsopt) do |ws|
EventMachine::WebSocket.start(ws_options) do |ws|
begin
print_debug "New WebSocket channel open."
secure ? print_debug("New WebSocketSecure channel open.") : print_debug("New WebSocket channel open.")
ws.onmessage { |msg|
msg_hash = JSON.parse("#{msg}")
#@note messageHash[result] is Base64 encoded
@@ -153,8 +219,6 @@ module BeEF
end
}
}
end
#@note retrieve the right websocket channel given an hooked browser session