Files
beef/core/main/rest/handlers/modules.rb

147 lines
6.1 KiB
Ruby

#
# Copyright 2012 Wade Alcorn wade@bindshell.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module BeEF
module Core
module Rest
class Modules < BeEF::Core::Router::Router
config = BeEF::Core::Configuration.instance
before do
error 401 unless params[:token] == config.get('beef.api_token')
halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip)
headers 'Content-Type' => 'application/json; charset=UTF-8',
'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0'
end
# @note Get all available and enabled modules (id, name, category)
get '/' do
mods = BeEF::Core::Models::CommandModule.all
mods_hash = {}
i = 0
mods.each do |mod|
modk = BeEF::Module.get_key_by_database_id(mod.id)
next if !BeEF::Module.is_enabled(modk)
mods_hash[i] = {
'id' => mod.id,
'class' => config.get("beef.module.#{modk}.class"),
'name' => config.get("beef.module.#{modk}.name"),
'category' => config.get("beef.module.#{modk}.category")
}
i+=1
end
mods_hash.to_json
end
# @note Get the module definition (info, options)
get '/:mod_id' do
cmd = BeEF::Core::Models::CommandModule.get(params[:mod_id])
error 404 unless cmd != nil
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
error 404 unless modk != nil
#todo check if it's possible to also retrieve the TARGETS supported
{
'name' => cmd.name,
'description' => config.get("beef.module.#{cmd.name}.description"),
'category'=> config.get("beef.module.#{cmd.name}.category"),
'options' => BeEF::Module.get_options(modk) #todo => get also payload options..get_payload_options(modk,text)
}.to_json
end
# @note Get the module result for the specific executed command
#
# Example with the Alert Dialog
#GET /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86/1?token=0a931a461d08b86bfee40df987aad7e9cfdeb050 HTTP/1.1
#Host: 127.0.0.1:3000
#===response (snip)===
#HTTP/1.1 200 OK
#Content-Type: application/json; charset=UTF-8
#
#{"date":"1331637093","data":"{\"data\":\"text=michele\"}"}
get '/:session/:mod_id/:cmd_id' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
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])
error 404 unless cmd != nil
result = BeEF::Core::Models::Result.first(:hooked_browser_id => hb.id, :command_id => cmd.id)
error 404 unless result != nil
{
'date' => result.date,
'data' => result.data
}.to_json
end
# @note Fire a new command module to the specified hooked browser.
# Return the command_id of the executed module if it has been fired correctly.
# Input must be specified in JSON format
#
# +++ Example with the Alert Dialog: +++
#POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1
#Host: 127.0.0.1:3000
#Content-Type: application/json; charset=UTF-8
#Content-Length: 18
#
#{"text":"michele"}
#===response (snip)===
#HTTP/1.1 200 OK
#Content-Type: application/json; charset=UTF-8
#Content-Length: 35
#
#{"success":"true","command_id":"1"}
#
# +++ Example with a Metasploit module (Adobe FlateDecode Stream Predictor 02 Integer Overflow) +++
# +++ note that in this case we cannot query BeEF/Metasploit if module execution was successful or not.
# +++ this is why there is "command_id":"not_available" in the response
#POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/236?token=83f13036060fd7d92440432dd9a9b5e5648f8d75 HTTP/1.1
#Host: 127.0.0.1:3000
#Content-Type: application/json; charset=UTF-8
#Content-Length: 81
#
#{"SRVPORT":"3992", "URIPATH":"77345345345dg", "PAYLOAD":"generic/shell_bind_tcp"}
#===response (snip)===
#HTTP/1.1 200 OK
#Content-Type: application/json; charset=UTF-8
#Content-Length: 35
#
#{"success":"true","command_id":"not_available"}
post '/:session/:mod_id' do
hb = BeEF::Core::Models::HookedBrowser.first(:session => params[:session])
error 401 unless hb != nil
modk = BeEF::Module.get_key_by_database_id(params[:mod_id])
error 404 unless modk != nil
request.body.rewind
begin
data = JSON.parse request.body.read
options = []
data.each{|k,v| options.push({'name' => k, 'value' => v})}
exec_results = BeEF::Module.execute(modk, params[:session], options)
exec_results != nil ? '{"success":"true","command_id":"'+exec_results.to_s+'"}' : '{"success":"false"}'
rescue Exception => e
print_error "Invalid JSON input for module '#{params[:mod_id]}'"
error 400 # Bad Request
end
end
end
end
end
end