Maybe using Inspect Element will help you!

Small hint: If you’re struggling with reproducing it on remote, you can use socat to proxy the remote instance to localhost:1337 like this: socat TCP-LISTEN:1337,fork OPENSSL:xxx--xxx-1234.ctf.kitctf.de:443 and it should behave exactly like a locally running docker container.

Category: web

Solver: aes, Liekedaeler, lukasrad02

Flag: GPNCTF{D4NG3R0U5_D3BUGG3R}

Writeup

In this challenge, all we get is a Dockerfile. Given what the other web challenges looked like, this is quite strange. However, after taking a look at the Dockerfile, it’s quite clear why this is the case. It has one very interesting line, which is this one: google-chrome --remote-debugging-port=13370 --disable-gpu --headless=new --no-sandbox google.com This starts google chrome with a remote debugging port. We’ve seen chrome used in other challenges, but the remote debugging port thing is new. So the challenge has to somehow revolve around it.

Setup

First up, we need to get our setup right. If we simply navigate to the URL provided to us we get an error message: “Host header is specified and is not an IP address or localhost”. Initially the challenge only shipped with the description Maybe using Inspect Element will help you!, but later on they added the socat command you can see above. We didn’t have that initially, but came up with exactly the same thing. With that up and running, we can work on the actual challenge.

Abusing the Remote Debugger Port

The remote debugger port basically allows us to use the chrome debugging tools you know from the browser, but remotely. If you think about it, this allows remote code execution. This includes giving us access to file:// which allows us to read files and therefore the flag. Armed with that knowledge, we can build our exploit. First up, we’ll use the socat command socat TCP-LISTEN:8080,fork OPENSSL:xxx--xxx-1234.ctf.kitctf.de:443 as discussed above. This forwards the instance we got to our localhost on port 8080. Now we’re able to access the remote debugging port via localhost:8080. Next step is actually fetching the flag. For that we wrote a little python script which uses playwright to interact with the debugger. For our purposes, we simply go to file:///flag to get our flag. This is what our final solve script looks like:

#!/usr/bin/env python3

from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.connect_over_cdp("http://localhost:8080")
    context = browser.contexts[0]
    page = context.new_page()
    page.goto("file:///flag")
    print(page.inner_text("body"))