Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-Side Request Forgery <iframe src='file:///etc/passwd'> (in version 6.3.0) #261

Closed
etsms opened this issue Nov 24, 2020 · 8 comments · Fixed by #319
Closed

Server-Side Request Forgery <iframe src='file:///etc/passwd'> (in version 6.3.0) #261

etsms opened this issue Nov 24, 2020 · 8 comments · Fixed by #319

Comments

@etsms
Copy link

etsms commented Nov 24, 2020

Expected Behavior

  • When attempting to convert html into a PDF using the /html endpoint, gotenberg should throw an exception (respond with a bad request) whenever there is an attempt to convert html with a source (src) reference to an internal system file.
  • [HTTP POST] /convert/html
  • [BODY] file: index.html >> test blank html <iframe src='file:///etc/passwd'>
  • [RESPONSE] 400 Bad Request (request was improperly formed - or something similar)

Current Behavior

  • [HTTP POST] /convert/html
  • [BODY] file: index.html >> test blank html <iframe src='file:///etc/passwd'>
  • [RESPONSE] (contents of the etc/password directory

image
image

Possible Solution

  • Respond with a bad request. Or something that indicates the requested operation is not allowed or prohibited.
  • Check the contents of the HTML file being uploaded to determine if similar file:// protocols are referenced

The use of server-side requests must be limited to specific scenarios required by the application and servers must be hardened to only allow those requests. SSRF can be remediated using a variety of standard web application protections, such as:

  1. Limit service types via input validation on user input: Analyze if the application must use URI/ URL in requests and if not, disallow them. When a use case requires URIs and URLs in requests, perform input validation on URI/URLs using whitelists or robust blacklists. For example, only allow URL schemes such as HTTP/HTTPS which are often required for accessing applications. Disable all other URL schemas such as file://, dict://, gopher://, ftp://. Alternatively, create a token based forwarding for SSRs which may eliminate the use of URIs altogether.
  2. Limit service interactions: Carefully analyze if the server requires interactions with external servers. Based on the use case, prevent unintended behavior in one of the following ways: External service interactions required: If the server is to perform interactions with external services, the server must be hardened to safely eliminate calls to services available on the local loopback adapter and prevent any calls from the server to other internal systems.
  3. External service interactions not required: If the server is to only interact with local services, configure outbound firewall rules to check any calls being made from the application. The rules must limit the web server's interaction with other hosts by routing traffic only to specified resources on the local network; i.e., web servers must disallow connections to any host not included in the whitelist.

Steps to Reproduce (for bugs)

  1. Configure Postman to use a proxy tool such as Burp Suite.
  2. Create an HTML file using the below data: test blank html <iframe src='file:///etc/passwd'>
  3. Toggle Burp Intercept on.
  4. Upload this HTML file and make a request to the "Converter" endpoint.
  5. Forward the intercepted request to Repeater and hit send.
  6. In Repeater > response section, right click and select "show response in browser".
  7. Open the response in a browser.
  8. Note that the PDF file contains contents of /etc/passwd file.

image
image

Context

  • We'd like to hide information about the server and not allow attackers to steal sensitive data

Your Environment

  • Azure
  • Linux Container
  • OS version: Unix 4.15.0.112
  • 64 bit system: True
  • 64 bit process: True
  • Processor count: 1
@gulien
Copy link
Collaborator

gulien commented Nov 25, 2020

Hello @etsms,

Thanks for this well-written issue!

It's already on my TODO list 👍 AFAIK, it would be possible to check each requests done by Google Chrome and prevent loading "unsafe" ones.

@etsms
Copy link
Author

etsms commented Nov 25, 2020

@gulien - great to hear! Thanks for the update. Looking forward to testing again.

@etsms
Copy link
Author

etsms commented Dec 1, 2020

@gulien - Question for ya... Our security team is wondering about a timeline for this patch. Do you or the gotenburg team have a timeline for this?

@gulien
Copy link
Collaborator

gulien commented Dec 2, 2020

No because I’m mostly working on Gotenberg on my free time so..

Anyway, Gotenberg should always be called from a trusted source 🤔

@serge-melis
Copy link

Is this not mitigated by the fact that, that the process runs inside of the docker container? Which has no access to anything outside of the container?

@Zettersten
Copy link

@serge-melis yes exactly. I had to prove to our security teams that it lives in a container and is short-lived. I was able to reduce the criticality of the finding by communicating that much. However, it'll stay a vulnerability until the software is patched (or updated) with a feature to disable local file navigation in the chrome driver (eg. no access to the etc/passwords path). So that's good news. As @gulien said earlier, its not (should not) publicly accessible and the client/requesters should be known and authorized.

So the risk is pretty low at this point.

BUT - a savvy hacker may find away around those other controls and ultimately pull/read sensitive information from the container. Hypothetical.... but this is the way security folks think. I'm certainly not a hacker pro.

@abergmann
Copy link

CVE-2021-23345 was assigned to this issue.

@yumauri
Copy link

yumauri commented Mar 11, 2021

Wow, that's an interesting one :)
If Chrome doesn't support such filtering out of the box, I think it could be done using some sort of proxy for Chrome. Like Privoxy, for example. But I don't know, does Chrome use proxy settings for file protocol?

@gulien gulien mentioned this issue Aug 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants