def check_token(self): if self.token_is_available(): return True else: user = input("Fofa API user:"******"Fofa API token:") self.token = new_token self.user = user if self.token_is_available(): self.write_conf() return True else: logger.error("The Fofa api token is incorrect. " "Please enter the correct api token.") self.check_token()
def token_is_available(self): if self.token: try: self.headers['X-QuakeToken'] = self.token resp = requests.get('https://quake.360.cn/api/v3/user/info', headers=self.headers) if 'month_remaining_credit' not in resp.text: logger.info(resp.text) if resp and resp.status_code == 200 and resp.json( )['code'] == 0: return True except Exception as ex: logger.error(str(ex)) return False
def new_token(self): data = '{{"username": "******", "password": "******"}}'.format( self.username, self.password) try: resp = requests.post('https://api.zoomeye.org/user/login', data=data) if resp.status_code != 401 and "access_token" in resp.text: content = resp.json() self.token = content['access_token'] self.headers['Authorization'] = f'JWT {self.token}' return True else: logger.info(resp.text) except Exception as ex: logger.error(str(ex)) return False
def search(self, dork): search_result = set() # create a browser instance browser = pychrome.Browser(url="http://127.0.0.1:9222") # create a tab tab = browser.new_tab() # start the tab tab.start() tab.Page.enable() # call method tab.Network.enable() tab.Runtime.enable() start = 1000 for step in range(0, start + 10, 10): url = "https://www.google.com/search?q={}".format(dork) url = url + "&start={}".format(step) # stepinfo="step:"+str(step) # logger.info(stepinfo) try: # call method with timeout tab.Page.navigate(url=url, _timeout=5) tab.wait(5) exp = 'document.getElementsByClassName("r").length' length = tab.Runtime.evaluate(expression=exp) # google就看报不报错,报错了的话document.getElementsByClassName("r").length是为0的 if length['result']['value'] == 0: logger.warn("[PLUGIN] Google Dork get 0, Exit") break # 从每一页上抓取url for l in range(0, length['result']['value']): # tab.wait(1) exp1 = 'document.getElementsByClassName("r")[{}].getElementsByTagName("a")[0].href'.format( l) res1 = tab.Runtime.evaluate(expression=exp1) logger.info(res1['result']['value']) search_result.add(res1['result']['value']) except Exception as ex: logger.error(str(ex)) tab.stop() browser.close_tab(tab) return search_result
def add_poc_from_file(self, filename): ret = False if os.path.exists(filename): try: load_file_to_module(filename) ret = True except SystemExit: pass except Exception as ex: msg = "[PLUGIN] load PoC script failed: {0}".format(str(ex)) single_time_warn_message(msg) else: err_msg = "[PLUIGIN] invalid pocsuite3 PoC file {}".format( filename) logger.error(err_msg) return ret
def bind_telnet_shell(host, port, user, pwd, check=True): if not check_port(host, port): return False try: tn = telnetlib.Telnet(host, port) tn.expect([b'Login: '******'login: '******'\n') tn.expect([b'Password: '******'password: '******'\n') tn.write(b'\n') if check: flag = random_str(6).encode() if flag not in read_results(tn, b'echo %s' % flag): return False start_listener(tn) except Exception as e: logger.error(str(e))
def _set_pocs_modules(): # TODO # load poc scripts .pyc file support if conf.poc: load_poc_sucess = False # step1. load system packed poc from pocsuite3/pocs folder for found in glob.glob(os.path.join(paths.POCSUITE_POCS_PATH, "*.py*")): dirname, filename = os.path.split(found) poc_name = os.path.splitext(filename)[0] if found.endswith(('__init__.py', '__init__.pyc')): continue if conf.poc in (filename, poc_name): info_msg = "loading PoC script '{0}'".format(found) logger.info(info_msg) load_poc_sucess = load_file_to_module(found) # step2. load poc from given file path try: if not load_poc_sucess and (not conf.poc.startswith('ssvid-')) and check_file(conf.poc): info_msg = "loading PoC script '{0}'".format(conf.poc) logger.info(info_msg) load_poc_sucess = load_file_to_module(conf.poc) except PocsuiteSystemException: logger.error('PoC file "{0}" not found'.format(conf.poc)) raise SystemExit # step3. load poc from seebug website using plugin 'poc_from_seebug' if not load_poc_sucess and conf.poc.startswith('ssvid-'): info_msg = "loading Poc script 'https://www.seebug.org/vuldb/{0}'".format(conf.poc) logger.info(info_msg) conf.plugins.append('poc_from_seebug') load_poc_sucess = True if conf.vul_keyword: # step4. load poc with vul_keyword search seebug website info_msg = "loading PoC script from seebug website using search keyword '{0}' ".format(conf.vul_keyword) logger.info(info_msg) conf.plugins.append('poc_from_seebug') load_poc_sucess = True if (conf.poc or conf.vul_keyword) and not load_poc_sucess: error_msg = "" logger.error(error_msg) raise PocsuiteSyntaxException(error_msg)
def load_string_to_module(code_string, fullname=None): try: module_name = 'pocs_{0}'.format( get_md5(code_string)) if fullname is None else fullname file_path = 'pocsuite://{0}'.format(module_name) poc_loader = PocLoader(module_name, file_path) poc_loader.set_data(code_string) spec = importlib.util.spec_from_file_location(module_name, file_path, loader=poc_loader) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod except ImportError: error_msg = "load module '{0}' failed!".format(fullname) logger.error(error_msg) raise
def _set_multiple_targets(): # set multi targets to kb if conf.url: targets = parse_target(conf.url) if not targets: err_msg = "incorrect target url or ip format!" logger.error(err_msg) for target in targets: kb.targets.add(target) if conf.url_file: for line in get_file_items(conf.url_file, lowercase=True, unique=True): kb.targets.add(line) if conf.dork: # enable plugin 'target_from_zoomeye' by default if 'target_from_shodan' not in conf.plugins: conf.plugins.append('target_from_zoomeye')
def check_requires(data): requires = get_poc_requires(data) requires = [i.strip().strip('"').strip("'") for i in requires.split(',')] if requires else [''] if requires[0]: poc_name = get_poc_name(data) info_msg = 'PoC script "{0}" requires "{1}" to be installed'.format(poc_name, ','.join(requires)) logger.info(info_msg) try: for r in requires: if ":" in r: r, module = r.split(":") __import__(module) else: __import__(r) except ImportError: err_msg = 'try install with "python -m pip install {0}"'.format(r) logger.error(err_msg) raise SystemExit
def search(self, dork, pages = 1, resource = 'ipv4'): search_result = set() try: for page in range(1, pages + 1): url = "https://censys.io/api/v1/search/{}".format(resource) data = { "query": dork, # 搜索的关键字, "fields": ["ip"], "page": page } resp = requests.post(url, data = json.dumps(data), auth = (self.uid, self.secret)) if resp and resp.status_code == 200 and "results" in resp.json(): content = resp.json()["results"] for match in content: ans = match["ip"] search_result.add(ans) except Exception as ex: logger.error(str(ex)) return search_result
def check_account(self): if self.token_is_available(): return True elif self.username and self.password: if self.new_token(): self.write_conf() return True while True: username = input("Telnet404 email account: ") password = getpass.getpass( "Telnet404 password: (input will hidden)") self.username = username self.password = password if self.new_token(): self.write_conf() return True else: logger.error("The username or password is incorrect, " "Please enter the correct username and password.")
def search(self, dork, pages=1, resource='host'): search_result = set() try: for page in range(1, pages + 1): url = "https://api.shodan.io/shodan/{0}/search?key={1}&query={2}&page={3}".format(resource, self.token, urllib.parse.quote(dork), page) resp = requests.get(url) if resp and resp.status_code == 200 and "total" in resp.json(): content = resp.json() for match in content['matches']: ans = match['ip_str'] if 'port' in match: ans += ':' + str(match['port']) search_result.add(ans) except Exception as ex: logger.error(str(ex)) return search_result
def command_set(self, *args, **kwargs): key, _, value = args[0].partition(" ") if key in self.current_module.options: self.current_module.set_option(key, value) logger.info("{} => {}".format(key, value)) elif key in self.current_module.global_options: self.current_module.setg_option(key, value) logger.info("{} => {}".format(key, value)) elif key in self.current_module.payload_options: if value.isdigit() and key != "lport": index = int(value) if index >= len(self.last_ip): logger.warning("Index out of range") return value = self.last_ip[index] self.current_module.setp_option(key, value) logger.info("{} => {}".format(key, value)) else: logger.error("You can't set option '{}'.".format(key))
def load_file_to_module(file_path): if '' not in importlib.machinery.SOURCE_SUFFIXES: importlib.machinery.SOURCE_SUFFIXES.append('') try: module_name = 'pocs_{0}'.format(get_filename(file_path, with_ext=False)) spec = importlib.util.spec_from_file_location(module_name, file_path, loader=PocLoader( module_name, file_path)) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod except ImportError: error_msg = "load module failed! '{}'".format(file_path) logger.error(error_msg) raise
def start(self): """ Routersploit main entry point. Starting interpreter loop. """ while True: try: command, args = self.parse_line(input(self.prompt)) command = command.lower() if not command: continue command_handler = self.get_command_handler(command) command_handler(args) except PocsuiteBaseException as err: logger.error(err) except EOFError: logger.info("Pocsuite stopped") break except KeyboardInterrupt: logger.info("User Quit") break
def token_is_available(self): if self.token: headers = {'Authorization': 'JWT %s' % self.token} headers2 = {'Authorization': self.token} try: resp = requests.get('http://api.ceye.io/v1/identify', headers=headers) if resp and resp.status_code == 200 and "data" in resp.json(): self.headers = headers return True resp = requests.get('http://api.ceye.io/v1/identify', headers=headers2) if resp and resp.status_code == 200 and "data" in resp.json(): self.headers = headers2 return True except Exception as ex: logger.error(str(ex)) return False
def crawl(url, max_pages=50, url_ext=()): true_url = get_redirect_url(url) pages_need_visit = [true_url] pages_count = 0 urls = {'url': set(), 'js': set(), 'img': set()} while pages_count < max_pages and pages_need_visit: url = pages_need_visit.pop(0) try: parser = LinkParser() links = parser.get_links(url, url_ext=url_ext) for k, v in links.items(): urls[k] = urls[k].union(v) pages_count += len(links['url']) pages_need_visit.extend([i for i in links['url']]) except Exception as ex: logger.error(ex) return urls
def create_executable(self): self.mkdirs() ext = '' path = os.path.join(self.path, self.filename) if self.target_os == OS.LINUX: if self.target_arch == OS_ARCH.X64: exe_code = self.create_linux_x86_64_exe() else: exe_code = self.create_linux_x86_exe() elif self.target_os == OS.WINDOWS: ext = '.exe' if self.target_arch == OS_ARCH.X64: exe_code = self.create_win_x86_64_exe() else: exe_code = self.create_win_x86_exe() else: logger.error('OS %s is not supported' % self.target_os) return self.write_file(exe_code, path + ext) return path
def __init__(self, bind_ip='0.0.0.0', bind_port=666, is_ipv6=False, use_https=False, certfile=os.path.join(paths.POCSUITE_DATA_PATH, 'cacert.pem'), requestHandler=BaseRequestHandler): if not os.path.exists(certfile): gen_cert(filepath=certfile) threading.Thread.__init__(self) self.bind_ip = bind_ip self.bind_port = int(bind_port) self.is_ipv6 = is_ipv6 self.https = use_https if self.https: self.scheme = 'https' else: self.scheme = 'http' self.certfile = certfile self.server_locked = False # Avoid call start method muti-times self.server_started = False # Aviod start server mutl-times self.requestHandler = requestHandler if ':' in bind_ip: ipv6 = get_host_ipv6() if not ipv6: logger.error('Your machine may not support ipv6') raise PocsuiteSystemException self.host_ip = ipv6 self.httpserver = HTTPServerV6 self.is_ipv6 = True else: self.is_ipv6 = False self.host_ip = get_host_ip() self.httpserver = HTTPServerV4 self.__flag = threading.Event( ) # The identifier used to pause the thread self.__flag.set() # set flag True self.__running = threading.Event( ) # The identifier used to stop the thread self.__running.set() # set running True
def load_file_to_module(file_path, module_name=None): if '' not in importlib.machinery.SOURCE_SUFFIXES: importlib.machinery.SOURCE_SUFFIXES.append('') try: module_name = 'pocs_{0}'.format(get_filename( file_path, with_ext=False)) if module_name is None else module_name spec = importlib.util.spec_from_file_location(module_name, file_path, loader=PocLoader( module_name, file_path)) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) poc_model = kb.registered_pocs[module_name] except KeyError: poc_model = None except ImportError: error_msg = "load module failed! '{}'".format(file_path) logger.error(error_msg) raise return poc_model
def _set_multiple_targets(): # set multi targets to kb if conf.url: targets = set() for url in conf.url: parsed = parse_target(url) if parsed: targets.add(parsed) if not targets: err_msg = "incorrect target url or ip format!" logger.error(err_msg) for target in targets: kb.targets.add(target) if conf.url_file: for line in get_file_items(conf.url_file, lowercase=False, unique=True): kb.targets.add(line) if conf.dork: # enable plugin 'target_from_zoomeye' by default if 'target_from_shodan' not in conf.plugins and 'target_from_fofa' not in conf.plugins and 'target_from_fofac' not in conf.plugins: conf.plugins.append('target_from_zoomeye') if conf.dork_zoomeye: conf.plugins.append('target_from_zoomeye') if conf.dork_shodan: conf.plugins.append('target_from_shodan') if conf.dork_google: conf.plugins.append('target_from_google') if conf.dork_censys: conf.plugins.append('target_from_censys') if conf.dork_fofa: conf.plugins.append('target_from_fofa') if conf.dork_fofac: conf.plugins.append('target_from_fofac')
def _set_http_user_agent(): ''' set user-agent :return: ''' conf.http_headers[HTTP_HEADER.USER_AGENT] = DEFAULT_USER_AGENT if conf.random_agent: uapath = os.path.join(paths.POCSUITE_DATA_PATH, 'user-agents.txt') if os.path.exists(uapath): with open(uapath) as f: agents = f.read().split("\n") if len(agents) == 1 and "" in agents: logger.error("user-agents file is empty will use default") else: conf.agents = agents else: logger.error("user-agents file not fond will use default") if conf.agent: conf.http_headers[HTTP_HEADER.USER_AGENT] = conf.agent
def search(self, dork, pages=2): search_result = set() data = {"query": dork, "size": 10, "ignore_cache": "false", "start": 1} try: for page in range(1, pages + 1): data['start'] = page url = "https://quake.360.cn/api/v3/search/quake_service" resp = requests.post(url, json=data, headers=self.headers, timeout=80) if resp and resp.status_code == 200 and resp.json( )['code'] == 0: content = resp.json() for match in content['data']: search_result.add("%s:%s" % (match['ip'], match['port'])) else: logger.error("[PLUGIN] Quake:{}".format(resp.text)) except Exception as ex: logger.error(str(ex)) return search_result
def command_use(self, module_path, *args, **kwargs): if module_path.isdigit(): index = int(module_path) if index >= len(self.last_search): logger.warning("Index out of range") return module_path = self.last_search[index] if not module_path.endswith(".py"): module_path = module_path + ".py" if not os.path.exists(module_path): module_path = os.path.join(paths.POCSUITE_ROOT_PATH, module_path) if not os.path.exists(module_path): errMsg = "No such file: '{0}'".format(module_path) logger.error(errMsg) return try: load_file_to_module(module_path) self.current_module = kb.current_poc self.current_module.pocsuite3_module_path = ltrim(rtrim(module_path, ".py"), os.path.join(paths.POCSUITE_ROOT_PATH, "")) except Exception as err: logger.error(str(err))
def search(self, dork, pages=1, resource='web'): search_result = set() try: for page in range(1, pages + 1): url = "https://api.zoomeye.org/{}/search?query={}&page={}&facet=app,os".format( resource, urllib.parse.quote(dork), page) resp = requests.get(url, headers=self.headers) if resp and resp.status_code == 200 and "matches" in resp.json( ): content = resp.json() if resource == 'web': search_result.update( [match['site'] for match in content['matches']]) else: for match in content['matches']: ans = match['ip'] if 'portinfo' in match: ans += ':' + str(match['portinfo']['port']) search_result.add(ans) except Exception as ex: logger.error(str(ex)) return search_result
def fetch_poc(self, ssvid): if self.check_account(): try: if ssvid and ssvid.startswith('ssvid-'): ssvid = ssvid.split('ssvid-')[-1] resp = requests.get('https://www.seebug.org/api/user/poc_detail?id=%s' % ssvid, headers = self.headers) if resp and resp.status_code == 200 and "code" in resp.json(): poc = resp.json()['code'] return poc elif resp.status_code == 200 and "status" in resp.json() and resp.json()["status"] is False: if "message" in resp.json(): msg = resp.json()["message"] if msg == "没有权限访问此漏洞": msg = "No permission to access the vulnerability POC" else: msg = "Unknown" msg = "[PLUGIN] " + msg raise Exception(msg) except Exception as ex: logger.error(str(ex)) else: return None
def cookie_is_available(self): if self.cookie: try: browser = pychrome.Browser(url="http://127.0.0.1:9222") # create a tab tab = browser.new_tab() # start the tab tab.start() tab.Page.enable() # call method tab.Network.enable() tab.Runtime.enable() tab.Network.clearBrowserCookies() url = "https://fofa.so/" tab.Network.setExtraHTTPHeaders( headers={ "Connection": "keep-alive", "Cookie": "_fofapro_ars_session={c}".format( c=self.cookie) }) tab.Network.setUserAgentOverride( userAgent= "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36" ) tab.Network.setCookie(name="_fofapro_ars_session", value=self.cookie, url="https://fofa.so/") # call method with timeout tab.Page.navigate(url=url, _timeout=5) tab.wait(2) test = 'document.getElementsByClassName("user-avatar").length' tmp = tab.Runtime.evaluate(expression=test) # print(tmp['result']['value']) if tmp['result']['value'] != 0: return True except Exception as ex: logger.error(str(ex)) return False
def _set_http_user_agent(): # load random HTTP User-Agent header(s) from files uapath = 'data/user-agents.txt' if os.path.exists(uapath): with open(uapath) as f: conf.user_agents = f.read().split("\n") else: conf.http_headers[HTTP_HEADER.USER_AGENT] = DEFAULT_USER_AGENT conf.user_agents.append(DEFAULT_USER_AGENT) logger.error("user-agents file not fond will use default") if not conf.user_agents: conf.user_agents.append(DEFAULT_USER_AGENT) logger.error("user-agents no value will use default") if conf.random_agent == 1: conf.http_headers[HTTP_HEADER.USER_AGENT] = choice(conf.user_agents) else: conf.http_headers[HTTP_HEADER.USER_AGENT] = DEFAULT_USER_AGENT if conf.agent: conf.http_headers[HTTP_HEADER.USER_AGENT] = conf.agent
def exec_cmd(cmd, raw_data=True): cmd = shlex.split(cmd) out_data = b'' try: p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while p.poll() is None: line = p.stdout.read() out_data += line except Exception as ex: logger.error("Execute cmd error {}".format(str(ex))) encoding = chardet.detect(out_data).get('encoding') encoding = encoding if encoding else 'utf-8' if IS_WIN: out_data = out_data.split(b'\r\n\r\n') else: out_data = out_data.split(b'\n\n') if not raw_data: for i, data in enumerate(out_data): out_data[i] = data.decode(encoding, errors='ignore') return out_data