Hacking Rendertron and Puppeteer— What to expect if you put a browser on the internet

Gabor Matuz
Nerd For Tech
Published in
6 min readJul 9, 2021

tldr: if you run headless browsers for things other than testing you should design the setup with the expectations that they will get owned. Headless browsers are exploitable like your normal browsers, their issues do not show up in CVE scanners and most likely you are running them without sandbox. Even if they are not exploitable you surely have SSRF to think about.

I don’t know about you but, these days any project I’m working on uses headless browsers in one form or another. Usually some let’s just make it work scraping, crawling or rendering solution. Headless browsers are powerful, so I can totally understand why. However, this is one of the few cases where me, your liberal security guy, is on the careful side of things.

Because, and I know this is a shocker: headless browsers are browsers. This means they are meant to run code.

With the risk of being banal: if you run a headless browser in your backend you should expect that they will get owned. This is probably not an issue if you run them for your tests, but surely if you run them in prod you would:

Make it hard to own

  • Run the most recent version of the browser that you update at least weekly and not just whatever comes with the version of the package
  • Run the browser without disabling the sandboxing unlike what the basic search results would tell you or the way common docker images would have it set up. Please take note that the default setup in the Rendertron project, puppeteer based rendering solution, is also vulnerable, running with old browser and no-sandbox. More on this at the end of the article.
  • Make sure that people can just point them to any site on the Internet. Like leaving your Rendertron open for people. Unlike these fellas.

Actually the puppeteer description is pretty good for hardening just like this one from Google.

You have take care of all the privilege escalation

  • Avoid running them on shared infrastructure, like Kubernetes, that attackers can use to pivot to your other things.
  • Run tight enough networking that it cannot access anything that was supposed to be internal only.
  • Not have access/credentials to anything other than maybe a sink where it dumps the data it gathers.

Make persistence hard

  • Discarding the containers that runs the browser after each session

If you don’t have doubts about your setup after reading the list, sorry for wasting you time you can stop reading here.

Yeah those could be improvements, but what about — the FAQ

1, I have a CVE scanner which would tell me about the vulnerabilities in the container. Surely it would let me know if the chrome has vulnerabilities!

Well, not really. Non of the CVE scanners I checked will actually check the bundled version.

2, This is docker and headless browser, the browser exploits wouldn’t really work, would they?

There is no magical reason for them not to work just because they are in docker. Only thing is that most browser exploits are written and tested for Widnows but chrome/chromium/v8 exploits work across different operating systems. The bugs themselves are usually cross platform.

3, What is SSRF? Running arbitrary Javascript in a browser, what can you even do from there?

Well a bunch of products like Cloudflare Workers literally only do this, and you would be surprised how far you can take it. So there is quite a lot of things you can do. Usually you cannot access the file system and limited to HTTP type requests in terms of protocols. You can try to still pivot in the network. Or for example getting to the kublet as the classic 2019 move.

Pentesters

Read this post from Vasilii Ermilov because it has much better description and exploitation ideas when it comes to pentesting. You get both a step-by-step and some good inspiration.

If you are pentesting and you made it so far, my recommendation if you can get into a headless browser, hit SSRF first: use some good old XSS or SSRF exploitation frameworks, to make recon easier. There are a bunch of good ideas in Vasilii’s blog on usual suspects you could try to access to escalate: instance metadata endpoint, chrome debug interface etc..

If you decide you want to go for the browser do some local testing first, try with the exact chrome version. Even if your metasploit runs out remember, most chrome exploits are in V8 so should work cross platform. There are quite some PoCs on github, with some love, debugging and coffee you can make them work for your case. You will need those though, most chrome exploits will be tested on win/osx and containers will almost all be linux (usually debian based). On the other hand, versions usually are horrendously outdated and most people run chrome in docker with --no-sandbox so in most cases you won’t need a sandbox escape. The more RCEs that worked in dockerised chromes on ubuntu without any need for modification were for example CVE-2020–16040 and pretty inconsistently CVE-2020–6507.

If you are in the last midnight shift of a pentest and you still want to get some exotic finding in, noticed Rendertron in a response header and googling “exploit rendertron” got you here: you will have a harder time but if you find an open redirect or stored XSS in the page an can get Rendertron to hit it for you you can still get that high finding in!

Disclaimer

Security issues related to the most recent version of Rendertron were shared with Google 9th April 2021. I have decided to publish this article after the usual 90 day grace period. I was not provided any timeline of fixes and, it seems to me, the recommendations they are publishing are in line with the views promoted by this article. With this in mind I believe the earlier people are informed about these precautions the better. Furthermore there are some fixes/workarounds one might be able to use and there is no clear timeline when these will be included in a release.

If you are running the most recent version of Rendertron (3.1.0) you should:

  • Make sure attackers cannot control the Javascript run by Rendertron. Do not expose it directly on the internet, restrict the domains it will render, be careful when rendering pages with user controlled content.
  • Run a more recent version of Chrome either by using the version from the not-yet-merged PR, or manually updating Chrome to the most recent version as described in Puppeteer docs. Make sure you rebuild the Docker image fairly frequently, Chrome exploits are frequent
  • Do not run Chrome with no-sandbox option

Please keep in mind if you deploy Rendertron in Google Cloud on App Engine as described in the repository it will run without a sandbox. I could not find any solutions or workarounds for this. You may decide to run it Flex version of App Engine where you can provide your own Docker image, giving you an option to do the above hardening. However, this might not fit most use-cases due to the longer startup times.

If you decide to use it with the Standard App Engine you should apply the measures outlined earlier (limiting network access, IAM rights, etc..)

Thanks!

This article is based on research work done together with Callum MacDonald and Zsolt Horvath. Thank you gents for the help!

Most of the heavy lifting is by Rajvardhan Agarwal writing adding the metasploit modules.

--

--

Gabor Matuz
Nerd For Tech

Security enthusiast into all things efficiency. Current project: https://inthewild.io/