Add scanner for the open proxy from 'SharknAT&To'
parent
a5be16f74e
commit
37bf68869f
|
@ -0,0 +1,99 @@
|
|||
import socket, re, functools
|
||||
import asyncio
|
||||
|
||||
from metasploit import module
|
||||
from async_timeout import timeout
|
||||
|
||||
|
||||
def make_study(payload='', pattern='', onmatch=None, connect_timeout=3, read_timeout=10):
|
||||
return lambda args: start_study(payload, pattern, args, onmatch, connect_timeout=connect_timeout, read_timeout=read_timeout)
|
||||
|
||||
|
||||
def start_study(payload, pattern, args, onmatch, **timeouts):
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(run_study(payload, pattern, args, onmatch, **timeouts))
|
||||
|
||||
|
||||
async def run_study(payload, pattern, args, onmatch, **timeouts):
|
||||
runs = [study_host(host, int(args['rport']), payload, **timeouts) for host in args['rhosts']]
|
||||
async for (target, res) in Study(runs):
|
||||
if isinstance(res, Exception):
|
||||
module.log('{}:{} - Error connecting: {}'.format(*target, res), level='error')
|
||||
elif res and re.search(pattern, res):
|
||||
module.log('{}:{} - Matches'.format(*target), level='good')
|
||||
module.log('{}:{} - Matches with: {}'.format(*target, res), level='debug')
|
||||
onmatch(target, res)
|
||||
else:
|
||||
module.log('{}:{} - Does not match'.format(*target), level='info')
|
||||
module.log('{}:{} - Does not match with: {}'.format(*target, res), level='debug')
|
||||
|
||||
|
||||
class Study:
|
||||
def __init__(self, runs):
|
||||
self.queue = asyncio.queues.Queue()
|
||||
self.total = len(runs)
|
||||
self.done = 0
|
||||
|
||||
for r in runs:
|
||||
f = asyncio.ensure_future(r)
|
||||
args = r.cr_frame.f_locals
|
||||
target = (args['host'], args['port'])
|
||||
f.add_done_callback(functools.partial(self.__queue_result, target))
|
||||
|
||||
|
||||
def __queue_result(self, target, f):
|
||||
res = None
|
||||
|
||||
try:
|
||||
res = f.result()
|
||||
except Exception as e:
|
||||
res = e
|
||||
|
||||
self.queue.put_nowait((target, res))
|
||||
|
||||
|
||||
async def __aiter__(self):
|
||||
return self
|
||||
|
||||
|
||||
async def __anext__(self):
|
||||
if self.done == self.total:
|
||||
raise StopAsyncIteration
|
||||
|
||||
res = await self.queue.get()
|
||||
self.done += 1
|
||||
return res
|
||||
|
||||
|
||||
async def study_host(host, port, payload, connect_timeout, read_timeout):
|
||||
r = None
|
||||
w = None
|
||||
buf = bytearray()
|
||||
|
||||
async with timeout(connect_timeout):
|
||||
r, w = await asyncio.open_connection(host, port)
|
||||
remote = w.get_extra_info('peername')
|
||||
if remote[0] == host:
|
||||
module.log('{}:{} - Connected'.format(host, port), level='debug')
|
||||
else:
|
||||
module.log('{}({}):{} - Connected'.format(host, *remote), level='debug')
|
||||
w.write(payload)
|
||||
await w.drain()
|
||||
|
||||
try:
|
||||
async with timeout(read_timeout):
|
||||
while len(buf) < 4096:
|
||||
data = await r.read(4096)
|
||||
if data:
|
||||
module.log('{}:{} - Received {} bytes'.format(host, port, len(data)), level='debug')
|
||||
buf.extend(data)
|
||||
else:
|
||||
break
|
||||
except asyncio.TimeoutError:
|
||||
if buf:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
w.close()
|
||||
return buf
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from metasploit import module, sonar
|
||||
|
||||
|
||||
metadata = {
|
||||
'name': 'Open WAN-to-LAN proxy on AT&T routers',
|
||||
'description': '''
|
||||
The Arris NVG589 and NVG599 routers configured with AT&T U-verse
|
||||
firmware 9.2.2h0d83 expose an un-authenticated proxy that allows
|
||||
connecting from WAN to LAN by MAC address.
|
||||
''',
|
||||
'authors': [
|
||||
'Joseph Hutchins' # Initial disclosure
|
||||
'Jon Hart <jon_hart[AT]rapid7.com>', # Dummy payload and response pattern
|
||||
'Adam Cammack <adam_cammack[AT]rapid7.com>' # Metasploit module
|
||||
],
|
||||
'date': '2017-08-31',
|
||||
'references': [
|
||||
{'type': 'cve', 'ref': '2017-14117'},
|
||||
{'type': 'url', 'ref': 'https://www.nomotion.net/blog/sharknatto/'},
|
||||
{'type': 'url', 'ref': 'https://blog.rapid7.com/2017/09/07/measuring-sharknat-to-exposures/#vulnerability5port49152tcpexposure'},
|
||||
{'type': 'aka', 'ref': 'SharknAT&To'},
|
||||
{'type': 'aka', 'ref': 'sharknatto'}
|
||||
],
|
||||
'type': 'scanner.multi',
|
||||
'options': {
|
||||
'rhosts': {'type': 'address_range', 'description': 'The target address', 'required': True, 'default': None},
|
||||
'rport': {'type': 'port', 'description': 'The target port', 'required': True, 'default': 49152},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def report_wproxy(target, response):
|
||||
module.report_vuln(target[0], 'wproxy', port=target[0])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
module.run(metadata, sonar.make_study(payload = b'\x2a\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00', pattern = b'^\\*\xce.{3}$', onmatch = report_wproxy))
|
Loading…
Reference in New Issue