def test_normal(scan_plugin_fixture): plugin_ins = scan_plugin_fixture rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "vuln", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "get", "querystring": "test=<?xml", "path": "/011-ssrf-curl.php", "parameter": { "test": [ "<?xml" ] }, "header": { "host": "localburp.com:8005", "connection": "keep-alive", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "dnt": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "accept-encoding": "gzip, deflate", "accept-language": "zh-CN,zh;q=0.9" }, "url": "http://localburp.com:8005/011-ssrf-curl.php?test=xml", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) plugin_ins.has_report = False asyncio.run(plugin_ins._scan(rasp_result_ins)) assert plugin_ins.has_report == True
async def post(self): """ 处理POST请求 """ try: data = self.request.body headers = self.request.headers content_type = self.request.headers.get("Content-Type", "None") if not content_type.startswith("application/json"): raise exceptions.ContentTypeInvalid Logger().info("Received request data: " + data.decode('utf-8')) rasp_result_ins = rasp_result.RaspResult(data) if rasp_result_ins.is_scan_result(): self.send_data(rasp_result_ins) else: await self.dedup_data(rasp_result_ins) self.write('{"status": 0, "msg":"ok"}\n') except exceptions.OriExpectedException as e: self.write('{"status": 1, "msg":"data invalid"}\n') Communicator().increase_value("invalid_data") Logger().warning( "Invalid data: {} posted to http server, rejected!".format( data)) except Exception as e: Logger().error( "Unexpected error occured when process data:{}".format(data), exc_info=e) self.send_error(500) return
def get_normal_response(): response = {"status": "200", "headers": {"host": "localhost"}, "body": b""} rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "php2", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "get", "querystring": "test_param=../../../../etc", "path": "/test-file.php", "parameter": { "test_param": [ "../../../../etc" ] }, "header": { "host": "localburp.com:8005", "connection": "keep-alive", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "dnt": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "accept-encoding": "gzip, deflate", "accept-language": "zh-CN,zh;q=0.9" }, "url": "http://localburp.com:8005/test-file.php?test_param=../../../../etc", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) result = { "scan_req_id": "0-a71e0906-88f6-412a-8bbe-efa94737e5c9", "response": response, "rasp_result": rasp_result_ins } return result
async def get_new_scan(self, count=1): """ 获取多条未扫描的请求数据 Parameters: count - 最大获取条数,默认为1 Returns: 获取的数据组成的list,每个item为一个dict, [{id:数据id, data:请求数据的json字符串} ... ] Raises: exceptions.DatabaseError - 数据库错误引发此异常 """ result = [] try: # 获取未扫描的最小id query = self.ResultList.select(peewee.fn.MIN( self.ResultList.id)).where((self.ResultList.id > self.start_id) & (self.ResultList.scan_status == 0)) fetch_star_id = await peewee_async.scalar(query) if fetch_star_id is None: return [] # 将要获取的记录标记为扫描中 query = self.ResultList.update({ self.ResultList.scan_status: 2 }).where((self.ResultList.scan_status == 0) & (self.ResultList.id > self.start_id)).order_by( self.ResultList.id).limit(count) row_count = await peewee_async.execute(query) if (row_count == 0): return result # 获取标记的记录 query = self.ResultList.select().where( (self.ResultList.id >= fetch_star_id) & (self.ResultList.scan_status == 2)).order_by( self.ResultList.id).limit(row_count) data = await peewee_async.execute(query) for line in data: result.append({ "id": line.id, "data": rasp_result.RaspResult(line.data) }) return result except asyncio.CancelledError as e: raise e except Exception as e: Logger().critical("Database error in get_new_scan method!", exc_info=e) raise exceptions.DatabaseError
async def get_urls(self, page=1, status=0): """ 获取指定状态的的url列表 Parameters: page - int, 获取的页数,每页10条 status - int, url的状态 未扫描:0, 已扫描:1, 正在扫描:2, 扫描中出现错误: 3 Returns: total, urls - total为数据总数, int类型,urls为已扫描的url, list类型, item形式为tuple (url对应id, url字符串) Raises: exceptions.DatabaseError - 数据库错误引发此异常 """ if page <= 0: page = 1 try: query = self.ResultList.select(peewee.fn.COUNT( self.ResultList.id)).where( self.ResultList.scan_status == status) result = await peewee_async.scalar(query) if result is None: total = 0 else: total = result query = self.ResultList.select().where( self.ResultList.scan_status == status).order_by( self.ResultList.id).offset((page - 1) * 10).limit(10) data = await peewee_async.execute(query) urls = [] for line in data: url_id = line.id rasp_result_ins = rasp_result.RaspResult(line.data) url = rasp_result_ins.get_url() urls.append((url_id, url)) return total, urls except asyncio.CancelledError as e: raise e except Exception as e: Logger().critical("Database error in mark_result method!", exc_info=e) raise exceptions.DatabaseError
def get_vuln_response(): response = { "status": "200", "headers": {"host": "localhost"}, "body": b"" } rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "vuln", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "get", "querystring": "test_param=123456", "path": "/test-file.php", "parameter": { "test_param": [ "1'openrasp" ] }, "header": { "host": "localburp.com:8005", "connection": "keep-alive", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "dnt": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "accept-encoding": "gzip, deflate", "accept-language": "zh-CN,zh;q=0.9" }, "url": "http://localburp.com:8005/test-file.php?test_param=123456", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ { "query": "SELECT id, name FROM vuln WHERE id = 1'openrasp", "server": "mysql", "tokens": [ { "start": 0, "stop": 6, "text": "SELECT" }, { "start": 7, "stop": 9, "text": "id" }, { "start": 9, "stop": 10, "text": "," }, { "start": 11, "stop": 15, "text": "name" }, { "start": 16, "stop": 20, "text": "FROM" }, { "start": 21, "stop": 25, "text": "vuln" }, { "start": 26, "stop": 31, "text": "WHERE" }, { "start": 32, "stop": 34, "text": "id" }, { "start": 35, "stop": 36, "text": "=" }, { "start": 37, "stop": 38, "text": "1" }, { "start": 38, "stop": 39, "text": "'" }, { "start": 39, "stop": 47, "text": "openrasp" } ], "hook_type": "sql" } ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) result = { "response": response, "rasp_result": rasp_result_ins } return result
def test_normal(scan_plugin_fixture): plugin_ins = scan_plugin_fixture rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "php1", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "post", "querystring": "", "path": "/upload/upload.php", "parameter": { "submit": [ "Submit" ] }, "header": { "host": "127.0.0.1:8005", "connection": "keep-alive", "content-length": "5566", "cache-control": "max-age=0", "origin": "http://127.0.0.1:8005", "upgrade-insecure-requests": "1", "dnt": "1", "content-type": "multipart/form-data; boundary=----WebKitFormBoundary484mhkVOXGBTS5jZ", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "referer": "http://127.0.0.1:8005/upload/upload.html", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-CN,zh;q=0.9" }, "url": "http://127.0.0.1:8005/upload/upload.php", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ { "name": "file", "filename": "test.txt", "content": "12345", "dest_path": "/var/www/html/upload/openrasp.php", "dest_realpath": "/var/www/html/upload/openrasp.php", "hook_type": "fileUpload" }, { "path": "/write/file", "realpath": "/write/file", "stack": [ "/var/www/html/writeFile.php@system" ], "hook_type": "writeFile" } ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) plugin_ins.has_report = False asyncio.run(plugin_ins._scan(0, rasp_result_ins)) assert plugin_ins.has_report is True
def get_vuln_response(): response = {"status": "200", "headers": {"host": "localhost"}, "body": b""} rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "vuln", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "get", "querystring": "test_param='\\"openrasp' cmd", "path": "/test-file.php", "parameter": { "test_param": [ "'\\"openrasp' cmd" ] }, "header": { "host": "localburp.com:8005", "connection": "keep-alive", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "dnt": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "accept-encoding": "gzip, deflate", "accept-language": "zh-CN,zh;q=0.9" }, "url": "http://localburp.com:8005/test-file.php?test_param='\\"openrasp' cmd", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ { "command": "/bin/sh -c ''\\"openrasp' cmd'", "stack": [ "/var/www/html/004-command-2.php@system" ], "tokens": [ { "start": 0, "stop": 7, "text": "/bin/sh" }, { "start": 8, "stop": 10, "text": "-c" }, { "start": 11, "stop": 13, "text": "''" }, { "start": 13, "stop": 14, "text": "\\"" }, { "start": 14, "stop": 28, "text": "openrasp' cmd'" } ], "hook_type": "command" } ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) result = {"response": response, "rasp_result": rasp_result_ins} return result
def _send_report_data(self, data_list): headers = { "X-OpenRASP-AppSecret": self.app_secret, "X-OpenRASP-AppID": self.app_id } send_data = [] try: for plugin_name, description, data, message, scan_time in data_list: # 尚未支持请求序列类型上报 data = json.loads(data) rasp_result_ins = rasp_result.RaspResult(data[0]) server_info = rasp_result_ins.get_server_info() vuln_hook = rasp_result_ins.get_vuln_hook() url = rasp_result_ins.get_url() if vuln_hook is not None: hook_info = vuln_hook["hook_info"] attack_type = vuln_hook["hook_info"]["hook_type"] stack = vuln_hook.get("stack", []) stack_trace = "\n".join(stack) server_type = server_info.get( "name", server_info.get("server", "None")) req_and_resp = "HTTP Request:\n{}\n\n\nHTTP Response:\n{}".format( rasp_result_ins.get_request(), rasp_result_ins.get_response()) if len(req_and_resp) > 2 * 1024 * 1024: req_and_resp = req_and_resp[:2 * 1024 * 1024] + "\n... {} more chars ...".format( len(req_and_resp) - 2 * 1024 * 1024) else: Logger().warning( "Report data with no vuln hook detect, skip upload!") continue cloud_format_data = { "rasp_id": "IAST", "app_id": self.app_id, "event_type": "attack", "event_time": time.strftime("%Y-%m-%dT%H:%M:%S%z", time.localtime(scan_time)), "request_id": rasp_result_ins.get_request_id(), "request_method": rasp_result_ins.get_method(), "intercept_state": "log", "target": rasp_result_ins.get_attack_target(), "server_hostname": rasp_result_ins.get_server_hostname(), "server_ip": rasp_result_ins.get_attack_source(), "server_type": server_type, "server_version": server_info["version"], "server_nic": rasp_result_ins.get_server_nic(), "path": rasp_result_ins.get_path(), "url": url, "attack_type": attack_type, "attack_params": hook_info, "attack_source": rasp_result_ins.get_attack_source(), "client_ip": rasp_result_ins.get_client_ip(), "plugin_name": plugin_name, "plugin_confidence": 90, "plugin_message": message, "plugin_algorithm": description, "header": rasp_result_ins.get_headers(), "stack_trace": stack_trace, # "body": base64.b64encode(rasp_result_ins.get_body()).decode("ascii"), "body": req_and_resp } send_data.append(cloud_format_data) send_data = json.dumps(send_data) r = requests.post(url=self.server_url, headers=headers, data=send_data) response = json.loads(r.text) if response["status"] != 0: Logger().warning( "Upload report to cloud failed with response: {}".format( r.text)) return False else: Logger().debug("Upload report {}!".format(send_data)) Logger().info("Upload report to cloud success!") return True except Exception as e: Logger().warning("Upload report to cloud failed!", exc_info=e) return False
def get_vuln_response(): response = { "status": "200", "headers": {"host": "localhost"}, "body": b"" } rasp_result_json = """ { "web_server": { "host": "127.0.0.1", "port": 8005 }, "context": { "requestId": "vuln", "json": { }, "server": { "language": "php", "name": "PHP", "version": "7.2.19", "os": "Linux" }, "body": "", "appBasePath": "/var/www/html", "remoteAddr": "172.17.0.1", "protocol": "http", "method": "get", "querystring": "test=xml", "path": "/011-ssrf-curl.php", "parameter": { "test": [ "test" ] }, "header": { "host": "localburp.com:8005", "connection": "keep-alive", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", "dnt": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "accept-encoding": "gzip, deflate", "accept-language": "zh-CN,zh;q=0.9", "content-length":"", "content-type": "application/x-www-form-urlencoded" }, "url": "http://localburp.com:8005/011-ssrf-curl.php?test=xml", "nic": [ { "name": "eth0", "ip": "172.17.0.2" } ], "hostname": "server_host_name" }, "hook_info": [ { "entity": "file:///etc/passwd", "hook_type": "xxe" } ] } """ rasp_result_ins = rasp_result.RaspResult(rasp_result_json) result = { "response": response, "rasp_result": rasp_result_ins } return result