def _host_survival_scan_handler_by_ping(self, ip_list: list, timeout: int) -> tuple: '''使用ping命令探测主机是否存活 ''' result = [] ret = '' if self.session.server_info.isWindows(): ips = ','.join(ip_list) self.session.client.options.set_temp_option('timeout', 0) ret = self.exec_command( f'cmd /c "for %i in ({ips}) do ping -n 1 -w {timeout} %i && echo %iok"' ) else: ips = ' '.join(ip_list) self.session.client.options.set_temp_option('timeout', 0) ret = self.exec_command( f'for ip in {ips};do ping -c 1 -W {timeout//1000} $ip && echo $ip"ok";done' ) if ret is None: logger.error("host_survival_scan_handler_by_ping error!") return result, len(ip_list) ret = re.findall(r'^\s*(\d+\.\d+\.\d+\.\d+)ok\s*$', ret, re.M) for ip in ret: result.append(ip) ip = colour.colorize(ip.ljust(15), 'bold', 'yellow') logger.info(f"{ip} is alive!" + ' ' * 20, True) return result, len(ip_list)
def _port_scan_handler(self, ports_list: list, ip: str, connect_timeout: int, isudp: bool) -> tuple: '''端口扫描处理函数 ''' result = [] self.session.client.options.set_temp_option('timeout', 30) self.session.client.options.set_temp_option('verbose', 1) ret = self.evalfile("payload/port_scan", ip=ip, ports=','.join([str(i.port) for i in ports_list]), isudp=isudp, timeout=connect_timeout) ret = ret.data if ret is None: logger.error( f"Scan {'UDP' if isudp else 'TCP'} port on {ip} error!" + ' ' * 20) return result, len(ports_list) ret = json.loads(ret) if ret: for p, response in ret.items(): for port in ports_list: if port.port == int(p): port.response = base64.b64decode(response.encode()) self._update_port_note_by_response(port) result.append(port) p = colour.colorize(str(p).rjust(5), 'bold', 'yellow') logger.info( f"{'UDP' if isudp else 'TCP'} port {p} is opened on {ip}!" + ' ' * 20, True) break return result, len(ports_list)
def get(self, kanban_id): """ Return all issues info for given kanban board """ kanban_finder = KanbanFinder() logger.info(f"Fetching kanban directory with id {kanban_id}") kanban_directory, kanban_check = kanban_finder.find_kanban_dir_with_id( kanban_id=kanban_id, kanbans_directory=config.kanbans_directory) logger.info(f"Kanban directory {kanban_directory}") if kanban_check: issue_finder = IssueFinder() try: logger.info( f"Fetching all issues for kanban with id {kanban_id}") all_issues_info_list = issue_finder.return_all_issues_info_for_kanban( kanbans_directory=config.kanbans_directory, kanban_id=kanban_id) response = jsonify(all_issues_info_list) response.headers.add("Access-Control-Allow-Origin", "*") return response except Exception as e: logger.error("Unable to fetch issues!") logger.exception(e) return {"response": "Unable to fetch issues"}, 500 else: logger.warning( f"Unable to fetch issues! Kanban with id {kanban_id} not found" ) return {"response": "Kanban id not found"}, 400
def _connect(self) -> int: ret = self.evalfile('payload/connect', host=self._host, port=self._port, user=self._user, password=self._password, database=self._current_database) ret = ret.data ret = json.loads(ret) if ret['code'] == -1: msg = base64.b64decode(ret['msg'].encode()).decode( self.session.client.options.encoding, 'ignore') logger.error('Connect error!') print(msg) self._last_connect_status = False return self.STOP elif ret['code'] == 1: logger.info('Connect successfully!', True) self._last_connect_status = True elif ret['code'] == 0: logger.error( "Can't find function `oci_connect`, the server may not have the OCI extension installed." ) self._last_connect_status = False return self.STOP return self.SUCCESS
def connect(self) -> bool: '''connect target and return True, or False if connect failed. ''' if not self.options.new_version: data = {'pass': self.options.password} try: with self.opener.post(self.options.target, data, timeout=10) as f: ret = f.read() if len(ret) == 16: self._create_key(ret) else: raise Exception("Error response!") except BaseException as e: logger.error(e) return False else: # 新shell h = hashlib.md5() h.update(self.options.password.encode()) self._create_key(h.hexdigest()[:16].encode()) sign = "gyhnb" p = CSharpPayload(os.path.join(os.path.dirname(__file__), 'new_version_test.cs'), sign=sign) ret = self.eval(p) if not ret.is_success() or ret.data != sign: logger.error( f"The expected response is `{sign}`, actually `{ret.data}`" ) return False return True
def put(self, kanban_id, issue_id): request.get_json(force=True) if api.payload is None or api.payload == {}: return {"response": "Unable to decode payload"}, 400 if (api.payload["stage"].replace(" ", "") == "" or api.payload["stage"] == "string"): return { "response": "Stage cannot be null or whitespaces only" }, 400 elif api.payload["stage"] not in [stage.value for stage in Stages]: return { "response": "Stage cannot be anything other than todo, done or doing" }, 400 issue_stage_hand = IssueStageHandler() logger.info(f"Changing issue with id {issue_id} current stage") try: issue_stage_hand.change_stage( kanbans_directory=config.kanbans_directory, kanban_id=kanban_id, issue_id=issue_id, stage_to_assign=api.payload["stage"], ) return {}, 204 except AttributeError: logger.error( f"Issue is not set to any stage! Check issue config xml") return {"response": "Issue is not set to any stage"}, 500 except FileNotFoundError: logger.warning("Issue couldn't be found") return {"response": "Issue id not found"}, 400 except Exception as e: logger.error("Couldn't update issue stage!") logger.exception(e) return {"response": "Unable to update issue stage"}, 500
def writer(self, conn: Connection): '''向远端写 ''' read = [conn.client, ] while conn.is_alive() and self.running: r, w, e = select.select(read, [], []) if not r: logger.error(f"Reader thread exit on `{conn}`") conn.exec_action(Connection.ACTION_CLOSE) break writebuf = b'' while True: tmp = None try: tmp = conn.client.recv(4096) except BlockingIOError: pass except OSError: conn.exec_action(Connection.ACTION_CLOSE) break if not tmp: break writebuf += tmp while writebuf: # 限制每次上传的大小 block = writebuf[:self.upload_buf_size] if self.upload_buf_size > 0 else writebuf writebuf = writebuf[self.upload_buf_size:] if self.upload_buf_size > 0 else False conn.exec_action(Connection.ACTION_WRITE, block)
def _forward(self, sessionid: str): '''执行前需要把webshell超时时间设置为无限 ''' self.exp.session.client.options.set_temp_option('timeout', 0) self.exp.session.client.options.set_temp_option('verbose', 1) ret = self.exp.evalfile('forward/forward', rhost=self.rhost, rport=self.rport, sessionid=sessionid) ret = ret.data if ret is None: logger.warning( "Forward request has exit!If forwarding is still working, please ignore this warning." ) return ret = json.loads(ret) if ret['code'] == -1: # connect failed error = base64.b64decode(ret['msg'].encode()).decode( self.exp.session.client.options.encoding, 'ignore') logger.error(error) elif ret['code'] == 1: logger.info( f"Connection has closed successfully for id `{sessionid}`!", False) self._close(sessionid)
def log_exception(e): error = '"Line":"{line}", "Exception_class": "{exception_class}", "Exception_docstring": "{exception_docstring}", "Exception_message": "{exception_message}"'.format( exception_class=e.__class__, exception_docstring=e.__doc__, exception_message=e.message, line=extract_function_name()) logger.error('{%s}' % error)
def run(self, args: Cmdline) -> int: args = self.parse.parse_args(args.options) ret = self.SUCCESS if args.create is not None: ret = self._create_from_file(args.create, args.nosave) elif args.list: ret = self._list() elif args.delete: ids = ', '.join([str(i) for i in args.delete]) if utils.input( f"Are you sure to delete these webshell connection `{ids}`? (y/n) " ).lower() == 'y': for i in args.delete: self._delete(i, True) elif args.save is not None: if len(args.save) == 0: if self.session.client is None: logger.error("No webshell client is using.") return self.STOP else: ret = self._save(self.session) else: for i in args.save: if i in self.manager.session_map: self._save(self.manager.session_map.get(i)) else: if isinstance(self.session, MainSession): ret = self._create_from_client(self.session, args.nosave, None) else: logger.error( "Current session is a webshellsession!If you want to get a copy, it is recommended to create it from a file" ) ret = self.STOP return ret
def run(self, args: Cmdline) -> int: args = self.parse.parse_args(args.options) text = self.load_config(self._name) if text is None: logger.warning("There is currently no memo!Will create a new.") text = {'note': ''} text = text['note'] raw_text = base64.b64decode(text.encode()) with tempfile.TemporaryDirectory() as tmpdir: path = os.path.join(tmpdir, 'note') with open(path, 'wb') as f: f.write(raw_text) if os.system(f"{config.editor} {path}") != 0: logger.error( f"Run editor `{config.editor}` failed!The editor must edit file in console like `vim filename` or `notepad filename`" ) logger.info( f"You can change editor in config file `{os.path.join(config.root_path, 'config.py')}`" ) return self.STOP with open(path, 'rb') as f: text = f.read() if text == raw_text: logger.warning( 'The content has not been changed, so it has not been saved!' ) else: self.save_config(self._name, {'note': base64.b64encode(text).decode()}) logger.info("Content has been updated!", True) return self.SUCCESS
def check_regions(logger, regions_name): if not regions_name: logger.error("Missing regions or region_name.") abort(400) exists = False try: session = db.session # session.execute("set enable_seqscan=false") exists = session.query( session.query(UserFile).filter_by( name=regions_name, expired=False).exists()).scalar() session.commit() session.close() except Exception as e: logger.error("Error or table does not exist", e) abort(500) if exists: result = {"text": "ok"} return json.dumps(result) else: abort(404)
def _parse_ports(self, ports: list, isudp=False) -> list: '''解析端口范围,返回端口列表 ''' ret = [] default_ports = self.default_udp_ports if isudp else self.default_tcp_ports if not ports: return default_ports for p in ports: min_port = 0 max_port = 0 try: if '-' in p: p1, p2 = p.split('-') min_port = int(p1) max_port = int(p2) else: min_port = max_port = int(p) for port in range(min_port, max_port + 1): pp = Port(port, Port.UDP if isudp else Port.TCP, '') tmp = [t for t in default_ports if t.port == pp.port] if tmp: pp = tmp[0] ret.append(pp) except: logger.error(f"Port `{p}` format error!") return ret
def read_test(): with open("spider_testphp.vulnweb.com.json") as f: datas = f.readlines() for data in datas: item = json.loads(data) url = item["url"] method = item["method"] headers = item["headers"] data = item["data"] try: if method.lower() == 'post': req = requests.post(url, data=data, headers=headers) http_model = HTTPMETHOD.POST else: req = requests.get(url, headers=headers) http_model = HTTPMETHOD.GET except Exception as e: logger.error("request method:{} url:{} faild,{}".format(method, url, e)) continue fake_req = FakeReq(req.url, {}, http_model, data) fake_resp = FakeResp(req.status_code, req.content, req.headers) task_push_from_name('loader', fake_req, fake_resp) logger.info("爬虫结束,开始漏洞扫描") start()
def delete(self, kanban_id, issue_id): """ Deletes issue for given kanban """ kanban_finder = KanbanFinder() logger.info(f"Fetching kanban directory with id {kanban_id}") kanban_directory, kanban_check = kanban_finder.find_kanban_dir_with_id( kanban_id=kanban_id, kanbans_directory=config.kanbans_directory) logger.info(f"Kanban directory {kanban_directory}") if kanban_check: try: issue_deleter = IssueDeleter() issue_deleter.delete_issue_for_kanban( kanbans_directory=config.kanbans_directory, kanban_id=kanban_id, issue_id=issue_id, ) except FileNotFoundError as fe: logger.warning( f"Unable to update issues! Issue with id {issue_id} not found" ) logger.exception(fe) return {"response": "Issue id not found"}, 400 except Exception as e: logger.error("Couldn't update issue") logger.exception(e) return {"response": "Couldn't update issue"}, 500 return 204 else: logger.warning( f"Unable to fetch issues! Kanban with id {kanban_id} not found" ) return {"response": "Kanban id not found"}, 400
def test04_login(self,keywords, password, expect_code): r = self.api.login(keywords, password) logger.info("请求数据:{} 响应数据:{}".format((keywords, password, expect_code), r.json())) print("登录结果:", r.json()) if "error" in password: logger.info("锁定60验证...") r = self.api.login(keywords, password) logger.info("请求数据:{} 响应数据:{}".format((keywords, password, expect_code), r.json())) print("登陆结果:", r.json()) r = self.api.login(keywords, password) logger.info("请求数据:{} 响应数据:{}".format((keywords, password, expect_code), r.json())) print("登陆结果:", r.json()) time.sleep(60) r = self.api.login("13600001111", "q123456") logger.info("请求数据:{} 响应数据:{}".format((keywords, password, expect_code), r.json())) print("登陆结果:", r.json()) try: # 4. 断言登录信息 common_assert(self, r, status_code=expect_code) except Exception as e: logger.error(e) raise
def detail(): try: token = flask.request.headers.get("token", None) if token not in util.session: message = { "error": "limited authority", "code": 401, "tips": util.get_tips_dict(10006) } message = json.dumps(message) logger.debug("GET /user/v1/detail - 401") return message, 401 uuid = util.session[token] user_detail = conductor.user.user_detail(uuid) except STPHTTPException as e: message = { "error": e.error_message, "code": e.httpcode, "tips": e.tip } message = json.dumps(message) logger.debug("GET /user/v1/detail - %s" % e.httpcode) logger.error("Get user detail ERROR:\n %s" % traceback.format_exc()) return message, e.httpcode user_detail = json.dumps(user_detail) return user_detail, 200
def run(self, args: Cmdline)-> int: args = self.parse.parse_args(args.options) ret = self.SUCCESS if args.add: lhost = args.lhost if args.lhost else None lport = args.lport if args.lport else None rhost = args.rhost if args.rhost else None rport = args.rport if args.rport else None lf = True if args.L else (False if args.R else None) uploadsize = args.uploadsize info = (lhost, lport, rhost, rport, lf, uploadsize) if None in info: logger.error("Some options are not set.Check you input.") return self.STOP ret = self._add(*info) elif args.flush: for ID in args.flush: rule = self._forward_list.get(ID) if rule: self._flush(ID) else: logger.warning(f"No specified rules `{ID}`!") elif args.delete: self._delete(args.delete) else: ret = self._list() return ret
def run(self, args: Cmdline) -> int: args = self.parse.parse_args(args.options) webshell = self.session.client if webshell is None: logger.error('No webshell client is using.') return self.STOP if args.webshell_help: print(colour(webshell.help)) elif args.options_help: old = webshell.options.option_list() tmp = [] tmp.append([old[0][0], old[0][4]]) for l in old[1:]: tmp.append([l[0], l[4]]) print( tablor(tmp, border=False, title="Options", max_width="30-1, 80-2")) else: old = webshell.options.option_list() tmp = [] tmp.append([old[0][0], old[0][1], old[0][2], old[0][3]]) for l in old[1:]: tmp.append([l[0], l[1], l[2], l[3]]) print( tablor(tmp, border=False, title="Options", max_width="30-1, 10-3")) return self.SUCCESS
def unlock(): try: data = json.loads(flask.request.data) uuid = data.get("uuid", None) params = {"uuid": uuid} util.check_param(**params) token = flask.request.headers.get("token", None) if (token not in util.session) or \ (not conductor.user.is_admin_user(util.session[token])): message = { "error": "limited authority", "code": 401, "tips": util.get_tips_dict(10006) } message = json.dumps(message) logger.debug("POST /user/v1/unlock - 401") logger.warn("unlock user %s WARNING: limited authority." % uuid) return message, 401 conductor.user.unlock(uuid) except DuplicateException as e: message = { "success": e.error_message, "code": e.httpcode } message = json.dumps(message) logger.info(e.error_message) logger.debug("POST /user/v1/unlock - %s" % e.httpcode) return message, e.httpcode except STPHTTPException as e: message = { "error": e.error_message, "code": e.httpcode, "tips": e.tip } message = json.dumps(message) logger.debug("POST /user/v1/unlock - %s" % e.httpcode) logger.error("unlock user ERROR:\n %s" % traceback.format_exc()) return message, e.httpcode except json.decoder.JSONDecodeError: logger.error("unlock user ERROR: JSON decode failed.\n %s" % traceback.format_exc()) logger.debug("POST /user/v1/unlock - 406") message = { "error": "invalid POST request: JSON decode failed.", "code": 406, "tips": util.get_tips_dict(10004) } message = json.dumps(message) return message, 406 logger.info("unlock user %s success." % uuid) message = { "success": "unlock user %s success." % uuid, "code": 200 } message = json.dumps(message) return message, 200
def upload_regions(logger): print("Uploading regions") logger.debug("Uploading regions.") regions_name = request.form.get('regions_name') regions = request.form.get('regions') if not regions or not regions_name: logger.error("Missing regions or region_name.") abort(400) regions_name = regions_name regions, error_regions = parse_input_regions(regions) id = generateRegionId(regions_name) try: session = db.session #session.execute("set enable_seqscan=false") create_upload_table_full(session, id, createUpload=True, regions=regions) create_upload_table(session, id, create=True) df_regions = pd.DataFrame(regions, columns=['chr', 'start', 'stop']) df_regions["len"] = df_regions["stop"] - df_regions["start"] + 1 avg_len = df_regions["len"].mean().astype("float") max_len = df_regions["len"].max().astype("float") # Add an entry to the user file uf = UserFile(name=id, preloaded=False, count=len(regions), avg_length=avg_len, max_length=max_len) session.add(uf) session.commit() session.close() except Exception as e: logger.error("Error uploading regions.", e) abort(500) result = { "id": id, "name": regions_name, "parsed_lines": len(regions), "avg_len": avg_len, "max_len": max_len, **({ "error": error_regions } if error_regions else {}) } return json.dumps(result)
def wrapper(token: str,*args, **kwargs): if not token: return False try: decoded = jwt.decode(token.strip(), cnf.SECRET, algorithm = "HS256") return func(*args, **kwargs) except jwt.exceptions.InvalidSignatureError: logger.error("Invalid signature received from : ") return False
def vulscan(target): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/74.0.3945.0 Safari/537.36", "Spider-Name": "Baidu.Inc" } if target == "": return elif "://" not in target: target = "http://" + target try: req = requests.get(target, headers=headers, timeout=60) target = req.url except: return netloc = urlparse(target).netloc logger.info("开始爬虫:{}".format(target)) cmd = [Excvpath, "-c", Chromepath, "--fuzz-path", "--robots-path", "-t", "20", "--custom-headers", json.dumps(headers), "--max-crawled-count", "10086", "-i", "-o", "json", target] rsp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = rsp.communicate() try: result = json.loads(output.decode().split("--[Mission Complete]--")[1]) except IndexError: return if result: all_req_list = result["req_list"] logger.info("获得数据:{}".format(len(all_req_list))) for item in all_req_list: with open("spider_{}.json".format(netloc), "a+") as f: f.write(json.dumps(item) + '\n') url = item["url"] method = item["method"] headers = item["headers"] data = item["data"] try: if method.lower() == 'post': req = requests.post(url, data=data, headers=headers) http_model = HTTPMETHOD.POST else: req = requests.get(url, headers=headers) http_model = HTTPMETHOD.GET except Exception as e: logger.error("request method:{} url:{} faild,{}".format(method, url, e)) continue fake_req = FakeReq(req.url, {}, http_model, data) fake_resp = FakeResp(req.status_code, req.content, req.headers) task_push_from_name('loader', fake_req, fake_resp) logger.info("加入扫描目标:{}".format(req.url)) logger.info("爬虫结束,开始漏洞扫描") start() logger.info("漏洞扫描结束") logger.info("发现漏洞:{}".format(KB.output.count()))
def _save(self, session: Session) -> int: '''保存session对应的webshell客户端信息 ''' path = os.path.join(os.path.dirname(__file__), "connections_example.xml") webshell = session.client if webshell is None: logger.error( f"No webshell client is using for session `{'manager' if isinstance(session, MainSession) else session.id}`." ) return self.STOP if os.path.exists(config.webshell_save_path): path = config.webshell_save_path try: tree = ET.parse(path) root = tree.getroot() ID = session.state.get( 'save_id') # 如果session创建时添加了-n选项,则不会有save_id字段(指定保存连接的ID) item = root.find(f"./item[@id='{ID}']") if item is None: ID = 0 for c in root: i = int(c.attrib.get('id', 0)) if ID < i: ID = i ID += 1 item = ET.Element("item", {'id': str(ID)}) root.append(item) w = item.find("./webshell") if w is None: w = ET.Element('webshell', {'value': webshell.type}) item.append(w) else: w.set('value', webshell.type) old_options = item.find("./options") if old_options: item.remove(old_options) options = ET.Element('options') for o in webshell.options.option_list()[1:]: attr = {'name': o[0], 'value': str(o[1])} if o[1] is None: # 如果参数值为None则加一个NoneType属性 attr['NoneType'] = 'true' option = ET.Element('option', attr) options.append(option) item.append(options) tree.write(config.webshell_save_path) session.state['save_id'] = ID # 保存成功后添加save_id字段 logger.info(f"Save a webshell connection `{ID}`.", True) except ET.ParseError: logger.error(f"Xml parse error on file `{path}`!") return self.STOP return self.SUCCESS
def test02_approve_info(self): self.login.login("13600001111", "q123456") r = self.approve.api_approve_info() try: common_assert(self, r, status=None) except Exception as e: logger.error(e) raise
def test01_approve(self): self.login.login("13600001111", "q123456") r = self.approve.api_approve("张三", "362322199512036344") try: common_assert(self, r, status_code=200) except Exception as e: logger.error(e) raise
def test01_loan_info(self): id = 874 r = self.loan.api_loan_info(id) logger.info("申请投资详情结果:{}".format(r.json())) try: common_assert(self, r, status=200) except Exception as e: logger.error(e) raise
def cmdloop(self): self.running = True thread_list = [] keepthread = threading.Thread(target=self._keep_shell_alive, name="keep shell alive") shellthread = threading.Thread(target=self._shell, name="shell") readerthread = threading.Thread(target=self._reader, name="reader") keepthread.setDaemon(True) shellthread.setDaemon(True) readerthread.setDaemon(True) thread_list.append(keepthread) keepthread.start() utils.sleep(1) if self.running: thread_list.append(shellthread) thread_list.append(readerthread) shellthread.start() else: return utils.sleep(1) readerthread.start() try: if self.exp.session.server_info.isUnix( ) and self._is_supported_shell(): logger.info( 'You can type `:getfshell` to upgrade to a fully interactive shell(The premise is that Pty has been obtained.)' ) logger.info( "Type `Ctrl + c` three times in a row to exit the fully interactive shell" ) while self.running: cmd = utils.input() if not cmd: continue if self.exp.session.server_info.isUnix( ) and cmd == ':getfshell' and self._is_supported_shell(): if not self.enter_fully_shell(): logger.error( "Unable to get a fully interactive shell!") continue break self._writer(cmd + '\n') except KeyboardInterrupt: pass self.close() logger.info("Wait for thread exit...") for t in thread_list: t.join(5) if t.is_alive() and not utils.kill_thread(t.ident): logger.error( f"Exit thread `{t.name}` failed, thread id is `{t.ident}`!" ) logger.info("All have been cleaned up!")
def test04_login(self): r = self.api.login(phone, password) print("登录结果:", r.json()) try: # 4. 断言登录信息 common_assert(self, r, description="登录成功") except Exception as e: logger.error(e) raise
def test22_is_not_login(self): # 2.判断是否登录 r = self.api.islogin() try: # 4. 断言登录信息 common_assert(self, r, status=250, description="您未登陆") except Exception as e: logger.error(e) raise