def authenticate_http(self, f: http.HTTPFlow) -> bool: """ Authenticate an HTTP request, returns if authentication was successful. If valid credentials are found, the matching authentication header is removed. In no or invalid credentials are found, flow.response is set to an error page. """ assert self.validator username = None password = None is_valid = False try: auth_value = f.request.headers.get(self.http_auth_header, "") scheme, username, password = parse_http_basic_auth(auth_value) is_valid = self.validator(username, password) except Exception: pass if is_valid: f.metadata["proxyauth"] = (username, password) del f.request.headers[self.http_auth_header] return True else: f.response = self.make_auth_required_response() return False
def response(flow: http.HTTPFlow) -> None: # This will add a script to the <head> of every page in www.overleaf.com if flow.request.pretty_host == 'www.overleaf.com': ctx.log.info("Installing SW on {}".format(flow.request.pretty_url)) if flow.request.path == '/install.js': flow.response = file_response(os.path.join( os.path.dirname(__file__), "install.js"), content_type=JS_MIME) return if flow.request.path == '/sw.js': flow.response = file_response(os.path.join( os.path.dirname(__file__), "sw.js"), content_type=JS_MIME) return if flow.request.path == '/sw_include.js': flow.response = file_response(os.path.join( os.path.dirname(__file__), "sw_include.js"), content_type=JS_MIME) return if flow.request.path == '/sw_config_overleaf.js': flow.response = file_response(os.path.join( os.path.dirname(__file__), "sw_config_overleaf.js"), content_type=JS_MIME) return flow.response.replace("<head>", "<head><script src=\"install.js\"></script>")
def error(self, flow: http.HTTPFlow): """Kills the flow if it has an error different to HTTPSyntaxException. Sometimes, web scanners generate malformed HTTP syntax on purpose and we do not want to kill these requests. """ if flow.error is not None and not isinstance(flow.error, HttpSyntaxException): flow.kill()
def request(flow: http.HTTPFlow) -> None: global REQUESTS global is_logging global logging_domain if flow.request.pretty_host == "startlogging": REQUESTS = {} is_logging = True logging_domain = flow.request.path[1:] flow.response = http.HTTPResponse.make(200, b"Logging started", {"Content-Type": "text/plain"}) return if flow.request.pretty_host == "stoplogging": is_logging = False save_path = os.environ[ "FPNET_SAVE_PATH"] if 'FPNET_SAVE_PATH' in os.environ else None if save_path and REQUESTS: with gzip.open( os.path.join(save_path, "{}.json.gz".format(logging_domain)), 'wt') as fh: fh.write(json.dumps(REQUESTS)) logging_domain = None REQUESTS = {} flow.response = http.HTTPResponse.make(200, b"Logging stopped", {"Content-Type": "text/plain"}) return
def request(flow: http.HTTPFlow) -> None: # pretty_host takes the "Host" header of the request into account, # which is useful in transparent mode where we usually only have the IP # otherwise. if flow.request.pretty_host == "base.micro.server.matocloud.com": ctx.log.error( ''' -------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/ ||----w | || || Time: %s Request:%s param:%s --------------------------------\n''' % (time.strftime('%Y.%m.%d %H:%M:%S', time.localtime( time.time())), flow.request, flow.request.text)) flow.request.host = "base.micro.server.matocloud.com" elif flow.request.pretty_host == "mitm.it": flow.request.host = "mitm.it" else: flow.kill()
def request(self, flow: http.HTTPFlow) -> None: endpoint = flow.request.path port = 9999 url = flow.request.url for each in ["172.17.0.1", "172.17.0.2", "172.17.0.3", "172.17.0.4", "172.17.0.5", "172.17.0.6"]: url = url.replace(each, environ['REPO_URL']) mock = True if int(time.time() - self.start_time) > 60 else False if mock and "textContent" in endpoint: rnd = randint(1, 100) text_content = self.get_text_content() if rnd < 90 else self.generate_template() flow.response = http.HTTPResponse.make( 200, text_content, {"Content-Type": "text/plain", "charset": "UTF-8"} ) elif mock and "alfresco/service/api/solr/metadata" in endpoint: body_req = flow.request.get_text() metadata_content = bytes(self.get_metadata_content(loads(body_req)), encoding="utf-8") flow.response = http.HTTPResponse.make( 200, metadata_content, {"Content-Type": "application/json", "charset": "UTF-8"} ) else: flow.request.url = url flow.request.port = port
def request(flow: http.HTTPFlow) -> None: if ".moflex" in flow.request.url: #send the moflex file to trigger the exploit flow.response = http.HTTPResponse.make( 200, bytes(content), { 'Server': 'nginx', 'Content-Type': 'application/octet-stream', 'Accept-Ranges': 'bytes', 'Last-Modified': 'Wed, 09 Sep 2015 00:29:42 GMT', 'Date': 'Sat, 30 May 2020 22:58:49 GMT', 'Content-Range': 'bytes 0-3884159/3884160', 'Content-Length': '3884160', 'Connection': 'keep-alive' }) content_len = flow.response.headers["Content-Length"] flow.response.headers[ "Content-Range"] = "bytes 0-" + content_len + "/" + content_len elif "spray" in flow.request.url and ".jpg" in flow.request.url: #"spraying" the heap flow.response = http.HTTPResponse.make( 200, pack("<I", ropBufferAddr) * (0x2B8 // 4), { 'Server': 'nginx', 'Content-Type': 'image/jpeg;charset=UTF-8', 'Content-Length': '15370', 'Accept-Ranges': 'bytes', 'Last-Modified': 'Tue, 08 Sep 2015 22:28:06 GMT', 'Cache-Control': 'max-age=59321', 'Expires': 'Mon, 01 Jun 2020 04:14:48 GMT', 'Date': 'Sun, 31 May 2020 11:46:07 GMT', 'Connection': 'keep-alive' })
def request(self, flow: HTTPFlow): if flow.request.host == 'dummy-upstream': flow.error = Error('No upstream is configured.') flow.response = make_error_response( 400, 'No upstream is configured.', )
def response(self, flow: http.HTTPFlow) -> None: # Topshop PDP if 'http://local.m.topshop.com:8080/api/products/%2Fen%' in flow.request.url: flow.response = http.HTTPResponse.make( 200, json.dumps( json.load( open('proxy_server/fixed_responses/ts_pdp.json'))), {"Content-Type": "application/json"}) # Dorothy Perkins PDP - Products out of stock if 'http://local.m.dorothyperkins.com:8080/api/products/%2Fen%' in flow.request.url: flow.response = http.HTTPResponse.make( 200, json.dumps( json.load( open('proxy_server/fixed_responses/dp_pdp.json'))), {"Content-Type": "application/json"}) # Dorothy Perkins Quick View if re.match( r'http://local.m.dorothyperkins.com:8080/api/products/[0-9]{8}', flow.request.url): # if flow.request.url == 'http://local.m.dorothyperkins.com:8080/api/products/31364808': flow.response = http.HTTPResponse.make( 200, json.dumps( json.load( open('proxy_server/fixed_responses/quickview.json'))), {"Content-Type": "application/json"})
def replay_request( self, f: http.HTTPFlow, block: bool=False ) -> http_replay.RequestReplayThread: """ Replay a HTTP request to receive a new response from the server. Args: f: The flow to replay. block: If True, this function will wait for the replay to finish. This causes a deadlock if activated in the main thread. Returns: The thread object doing the replay. Raises: exceptions.ReplayException, if the flow is in a state where it is ineligible for replay. """ if f.live: raise exceptions.ReplayException( "Can't replay live flow." ) if f.intercepted: raise exceptions.ReplayException( "Can't replay intercepted flow." ) if not f.request: raise exceptions.ReplayException( "Can't replay flow with missing request." ) if f.request.raw_content is None: raise exceptions.ReplayException( "Can't replay flow with missing content." ) f.backup() f.request.is_replay = True f.response = None f.error = None if f.request.http_version == "HTTP/2.0": # https://github.com/mitmproxy/mitmproxy/issues/2197 f.request.http_version = "HTTP/1.1" host = f.request.headers.pop(":authority") f.request.headers.insert(0, "host", host) rt = http_replay.RequestReplayThread( self.options, f, self.event_queue, self.should_exit ) rt.start() # pragma: no cover if block: rt.join() return rt
def request(self, flow: http.HTTPFlow) -> None: # redirects all requests to api.github.com to local server (flask instance) if flow.request.host == "api.github.com": if val.get_type() != 'ConnectionError': flow.request.host = "gitty.local" else: val.pop_type() flow.kill()
def response(flow: http.HTTPFlow) -> None: print("RES|", flow.response) data = dict(request=flow.request, response=flow.response) zmq_socket.send_multipart((b"RES|", pickle.dumps(data))) _, action = zmq_socket.recv_multipart() if action == b'DROP': print("BACKCHAN killing response!") flow.kill()
def authenticate(self, f: http.HTTPFlow) -> bool: valid_credentials = self.check(f) if valid_credentials: f.metadata["proxyauth"] = valid_credentials del f.request.headers[self.which_auth_header()] return True else: f.response = self.auth_required_response() return False
def request(self, flow: HTTPFlow) -> None: """Route the request and set `X-Caller` and `X-Callee` headers.""" req = flow.request self._logger.debug("incoming request %s, headers: %s", req, req.headers) try: server_addr = req.headers["X-Server-Addr"] server_port = int(req.headers["X-Server-Port"]) remote_addr = req.headers["X-Remote-Addr"] node_name = self._node_names[remote_addr] if server_port == YAGNA_REST_PORT: # It's a provider agent calling a yagna daemon # Since we assume that the provider agent runs on the same container # as the provider daemon, we route this request to that container's # host-mapped daemon port req.host = "127.0.0.1" req.port = self._ports[remote_addr][server_port] req.headers[CALLER_HEADER] = f"{node_name}:agent" req.headers[CALLEE_HEADER] = f"{node_name}:daemon" elif HOST_REST_PORT_START <= server_port <= HOST_REST_PORT_END: # It's a requestor agent calling a yagna daemon. # We use localhost as the address together with the original port, # since each daemon has its API port mapped to a port on the host # chosen from the specified range. req.host = "127.0.0.1" req.port = server_port req.headers[CALLER_HEADER] = f"{node_name}:agent" req.headers[CALLEE_HEADER] = f"{node_name}:daemon" else: flow.kill() raise ValueError(f"Invalid server port: {server_port}") self._logger.debug( "Request from %s for %s:%d/%s routed to %s at %s:%d", # request caller: req.headers[CALLER_HEADER], # original host, port and path: server_addr, server_port, req.path, # request recipient: req.headers[CALLEE_HEADER], # rewritten host and port: req.host, req.port, ) except (KeyError, ValueError) as ex: self._logger.error("Invalid request: %s, error: %s", req, ex.args[0]) flow.kill() raise
def request(self, flow: HTTPFlow): # Remove "vgs-client" header, that is sent by VGS-Collect. # This copies logic from proxy flow.request.headers.pop('vgs-client', None) if flow.request.host == 'dummy-upstream': flow.error = Error('No upstream is configured.') flow.response = make_error_response( 400, 'No upstream is configured.', )
def request(flow: http.HTTPFlow) -> None: if flow.request.url == "https://nus.c.shop.nintendowifi.net/nus/services/NetUpdateSOAP": if not ctx.options.certhax_payload or not certhax_payload_b64: ctx.log.warn("[certhax] - The certhax payload file is not set, the exploit won't be triggered...") return if not ctx.options.arm9_payload or not arm9_payload_b64: ctx.log.warn("[certhax] - The arm9 payload file is not set, the exploit won't be triggered...") return if b"nus:GetSystemTitleHash" in flow.request.content: ctx.log.info("[certhax] - Found nus:GetSystemTitleHash message") ctx.log.info("[certhax] - Sending dummy SystemTitleHash to trigger sysupdate attempt...") flow.response = http.HTTPResponse.make( 200, GetSystemTitleHashResponse, {"Content-Type": "text/xml"} ) elif b"nus:GetSystemUpdate" in flow.request.content: ctx.log.info("[certhax] - Found nus:GetSystemUpdate message") ctx.log.info("[certhax] - Sending dummy TitleId to trigger ticket installation attempt...") flow.response = http.HTTPResponse.make( 200, GetSystemUpdateResponse, {"Content-Type": "text/xml"} ) elif b"nus:GetSystemCommonETicket" in flow.request.content: ctx.log.info("[certhax] - Found nus:GetSystemCommonETicket message") ctx.log.info("[certhax] - Sending payload Certs to trigger the exploit...") flow.response = http.HTTPResponse.make( 200, GetSystemCommonETicketResponse.format(certhax_payload_b64, arm9_payload_b64), {"Content-Type": "text/xml"} ) elif flow.request.url == "https://ecs.c.shop.nintendowifi.net/ecs/services/ECommerceSOAP": if not ctx.options.certhax_payload or not certhax_payload_b64: ctx.log.warn("[certhax] - The certhax payload file is not set, the exploit won't be triggered...") return if not ctx.options.arm9_payload or not arm9_payload_b64: ctx.log.warn("[certhax] - The arm9 payload file is not set, the exploit won't be triggered...") return if b"ecs:GetAccountStatus" in flow.request.content: ctx.log.info("[certhax] - Found ecs:GetAccountStatus message") ctx.log.info("[certhax] - Sending list of services URL...") flow.response = http.HTTPResponse.make( 200, GetAccountStatusResponse, {"Content-Type": "text/xml"} ) elif flow.request.url == "http://conntest.nintendowifi.net/": ctx.log.info("[certhax] - Found conntest request") ctx.log.info("[certhax] - Sending response...") flow.response = http.HTTPResponse.make( 200, conntest, {"Content-Type": "text/html", "X-Organization": "Nintendo"} )
def request(flow: http.HTTPFlow) -> None: if flow.request.pretty_url.startswith( 'https://grammultitool.com/api/v1/user/authenticate'): flow.response = requestResponse[0] elif flow.request.pretty_url.startswith( 'https://grammultitool.com/api/v1/user/licenses/?access_token='): flow.response = requestResponse[1] elif flow.request.pretty_url.startswith( 'https://grammultitool.com/api/v1/user/licenses/1/register?'): flow.response = requestResponse[2]
def request(flow: http.HTTPFlow) -> None: global isLoggingIn if not flow.request.pretty_host.endswith("magica-us.com"): return if flow.request.path.startswith('/search'): # TODO: implement search return if flow.request.path.startswith('/magica/api'): # TODO: implement the rest apis = { '/magica/api/gacha': gacha.handleGacha, '/magica/api/userCard': userCard.handleUserCard, '/magica/api/user/': user.handleUser, '/magica/api/gameUser': gameUser.handleGameUser, '/magica/api/userChara': userChara.handleUserChara, '/magica/api/friend': friend.handleFriend, '/magica/api/userPiece/': userPiece.handleUserPiece, '/magica/api/userPieceSet/': userPieceSet.handleUserPieceSet, '/magica/api/userLive2d': userLive2d.handleUserLive2d, '/magica/api/money': money.handleMoney, '/magica/api/shop': shop.handleShop, '/magica/api/userDeck': userDeck.handleUserDeck, '/magica/api/quest': quest.handleQuest } if flow.request.path.startswith('/magica/api/test/logger/error'): flow.response = http.HTTPResponse.make( 200, '{"resultCode": "success"}', {}) return if flow.request.path.startswith('/magica/api/page'): apiResponse = page.handlePage(flow, isLoggingIn) if isLoggingIn: isLoggingIn = False flow.response = http.HTTPResponse.make(200, apiResponse, {}) for endpoint in apis.keys(): if flow.request.path.startswith(endpoint): try: apis[endpoint](flow) except: flow.response = http.HTTPResponse.make( 500, '{"errorTxt": "Had some trouble with ' + endpoint + '","resultCode": "error","title": "Error"}', {}) raise return if flow.request.path.startswith('/magica'): # index.html is the title page -- logins only happen at midnight and when the title page is requested if flow.request.path == '/magica/index.html': isLoggingIn = True serveAsset(flow) else: flow.response = http.HTTPResponse.make(404, "", {})
def request(self, flow: http.HTTPFlow) -> None: if flow.response or flow.error or not flow.live: return for spec in self.items: if spec.matches(flow): flow.metadata['blocklisted'] = True if spec.status_code == NO_RESPONSE: flow.kill() else: flow.response = http.Response.make( spec.status_code, headers={"Server": version.MITMPROXY})
def request(flow: http.HTTPFlow) -> None: config = utils.readFile(CONFIG_FILE) method = flow.request.method url = flow.request.url if config is not None: for matchMethod in config: if matchMethod == method: for patternURL in config[matchMethod]: if re.match(patternURL, url) is not None: ctx.log.warn('>>> FOUND request to kill: ' + method + ' ' + url) flow.kill()
def flow(): request = HTTPRequest(first_line_format='first_line', host=b'localhost', path=b'/test/', http_version=b'1.1', port=1234, method=b'', scheme=b'', headers=Headers([(b"Host", b"example.com")]), content=None, timestamp_start=111.1) flow = HTTPFlow(client_conn=MagicMock(), server_conn=MagicMock()) flow.request = request return flow
def request(self, flow: HTTPFlow): """MITMProxy addon event interface for outgoing request.""" try: request = MITMRequest.from_mitmproxy(flow.request) response = self.process_request(request).to_mitmproxy() flow.response = response except DoNotIntercept as e: # Let the request pass through, by not interrupting the flow, but log it logger.warning(str(e)) except Exception as e: flow.response = HTTPResponse.make( status_code=getattr(e, 'http_status_code', 500), content=str(e), headers={'Content-Type': 'text/plain'})
def response(self, flow: http.HTTPFlow) -> None: original_base_uri = f"{flow.request.scheme}://{flow.request.host}" if flow.request.port not in [80, 443]: # only add the port if it's nonstandard; this allows the replace to work as expected original_base_uri += f':{flow.request.port}' html = BeautifulSoup(flow.response.content, "html.parser") if html.body: with ThreadPoolExecutor(max_workers=self.max_workers) as executor: flow.response.text = str( inline_html(html, original_base_uri, executor)) new_base_uri = f"{flow.request.scheme}://{ctx.options.listen_host}:{ctx.options.listen_port}" flow.replace(original_base_uri, new_base_uri)
def request(self, f: http.HTTPFlow) -> None: if self.flowmap: rflow = self.next_flow(f) if rflow: assert rflow.response response = rflow.response.copy() if ctx.options.server_replay_refresh: response.refresh() f.response = response f.is_replay = "response" elif ctx.options.server_replay_kill_extra: ctx.log.warn( "server_playback: killed non-replay request {}".format( f.request.url)) f.kill()
def request(self, flow: http.HTTPFlow) -> None: if ctx.options.glean_app_id == "": raise Exception("The option glean_app_id must be set") if ctx.options.proxy_instance_id == "": raise Exception("The option proxy_instance_id must be set") self.ensure_telemetry_storage_path() if flow.request.pretty_url.startswith( f"https://incoming.telemetry.mozilla.org/submit/{ctx.options.glean_app_id}" ): # Parse request contents parsed = json.loads(flow.request.text) formatted_json_string = json.dumps(parsed, indent=4, sort_keys=True) print("formatted_json_string", formatted_json_string) # Save response filename = f'{parsed["ping_info"]["seq"]}.json' with open(os.path.join(self.telemetry_storage_path, filename), "w") as f: f.write(formatted_json_string) # Respond without sending request to external server ctx.log.info( f"Intercepted telemetry request (stored as {filename}), responding with a 200 OK without actually sending request to external server" ) flow.response = http.HTTPResponse.make(200)
def request(flow: http.HTTPFlow) -> None: if flow.request.pretty_url == "http://google.com": flow.response = http.HTTPResponse.make( 200, # (optional) status code b"Hello World", # (optional) content {"Content-Type": "text/html"} # (optional) headers )
def request(self, flow: HTTPFlow): """ { "charInstId": 9, "skinId": "char_123_fang#1" } """ if self.inServersList( flow.request.host) and flow.request.path.startswith( "/charBuild/changeCharSkin"): self.info("Receive skin change request") req = json.loads(flow.request.get_text()) resp = { "playerDataDelta": { "deleted": {}, "modified": { "troop": { "chars": { str(req["charInstId"]): { "skin": req["skinId"] } } } } } } self.info("make response") self.tBuilder.chars[str(req["charInstId"])]["skin"] = req["skinId"] flow.response = HTTPResponse.make( 200, json.dumps(resp), {"Content-Type": "application/json; charset=utf-8"}) self.info("Reply Complete")
def request(flow: http.HTTPFlow) -> None: if "json" in flow.request.pretty_url: flow.response = http.HTTPResponse.make( 200, # (optional) status code b"Hello World", # (optional) content {"Content-Type": "application/json"} # (optional) headers )
def request(flow: http.HTTPFlow) -> None: p_url = flow.request.pretty_url intercept = (p_url.startswith('https://www.google.com/search') or p_url.startswith('https://www.youtube.com/results')) if intercept: q = p_url[30:] if 'q' in flow.request.query: # 'oq' also valid key q = flow.request.query['q'].replace(' ', '') elif 'search_query' in flow.request.query: q = flow.request.query['search_query'].replace(' ', '') logging.info(q) for x in death: if x in q: logging.info('!!! DEATH KEY !!!: ' + x + ' found in ' + q) # flow.response = http.HTTPResponse.make(451) # Prod Response flow.response = http.HTTPResponse.make(200,x,{"Content-Type": "text/html"}) # for testing break
def request(self, flow: http.HTTPFlow) -> None: if "baidu" in flow.request.pretty_url: flow.response = http.HTTPResponse.make( 200, # (optional) status code b"Hello BaiDu", # (optional) content {"Content-Type": "text/html"} # (optional) headers )
def request(flow: http.HTTPFlow) -> None: # pretty_url takes the "Host" header of the request into account, which # is useful in transparent mode where we usually only have the IP otherwise. if flow.request.pretty_url == "http://example.com/path": flow.response = http.HTTPResponse.make( 200, # (optional) status code b"Hello World", # (optional) content {"Content-Type": "text/html"} # (optional) headers )
def __init__( self, opts: options.Options, f: http.HTTPFlow, channel: controller.Channel, ) -> None: self.options = opts self.f = f f.live = True self.channel = channel super().__init__( "RequestReplay (%s)" % f.request.url ) self.daemon = True
def request(self, flow: http.HTTPFlow): if self.flt: cookie_list = [] # type: List[Tuple[str,str]] if flowfilter.match(self.flt, flow): for (domain, port, path), c in self.jar.items(): match = [ domain_match(flow.request.host, domain), flow.request.port == port, flow.request.path.startswith(path) ] if all(match): cookie_list.extend(c.items()) if cookie_list: # FIXME: we need to formalise this... flow.metadata["stickycookie"] = True flow.request.headers["cookie"] = cookies.format_cookie_header(cookie_list)
def __init__( self, opts: options.Options, f: http.HTTPFlow, event_queue: typing.Optional[queue.Queue], should_exit: threading.Event ) -> None: """ event_queue can be a queue or None, if no scripthooks should be processed. """ self.options = opts self.f = f f.live = True if event_queue: self.channel = controller.Channel(event_queue, should_exit) else: self.channel = None super().__init__( "RequestReplay (%s)" % f.request.url ) self.daemon = True