Skip to content

GoCamo: Content-Type validation bypass

High
dropwhile published GHSA-jg2r-qf99-4wvr Nov 12, 2019 · 1 comment

Package

go-camo

Affected versions

< 2.1.1

Patched versions

2.1.1

Description

Overview

Go-Camo's build-in check to only proxy resources of type image/* (and optionally video/* and audio/*) can be bypassed. Go-Camo can be tricked to proxy resources of arbitrary Content-Type.

This could allow XSS.

Details

Go-Camo, is supposed to only fetch media files. If a resource is fetched that is not a configured accepted content type, the proxy should refuse to pass the resource along to the client.

What happens behind the scenes is that when Go-Camo fetches an image source, and notices that the content type of this resource is not in the accept list, it will returns an error message Unsupported content-type returned. This behavior is an important security precaution as it stops attackers from proxying arbitrary content through camo, which could lead to XSS or phishing pages being served by Camo.

Howeve, as part of this advisory, it was discovered that the content type filter can be bypassed by providing multiple values for the header Content-Type. The problem is that Go-Camo only checks that the first value is of the expected type; the following values are not validated. For example, Content-Type: image/png, text/html; charset=UTF-8 will bypass Go-Camo's content type validation, because image/png matches image/*.

The code that does the content type validation relies on globbing and, hence, the whitelist image/* matches the content type from the previous example.

This bug in the content-type validation would not matter much if browsers would be conservative when processing an ambiguous Content-Type header. But since this is the web, browsers strive for a maximum of compatibility. When provided with multiple content types, browsers seem to automatically choose the type that fits the resource. The following HTTP response will be rendered by Chrome as well as Firefox as text/html:

HTTP/1.1 200 OK
Content-Length: 292
Content-Security-Policy: media-src 'self'; script-src 'none'; object-src 'none'
Content-Type: image/svg+xml, text/html; charset=UTF-8
Date: Fri, 08 Nov 2019 17:15:43 GMT
Server: go-camo
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Via: 1.1 google
Alt-Svc: clear
Connection: close

<html>
  <head>
    <title>test</title></head>
    <body>
      <!-- Insert arbitrary HTML here -->
    </body>
</html>

Impact

Arbitrary redirect is possible with:

<meta http-equiv="refresh" content="2;url=https://evil.com" />

It may also be possible to host a phishing page, if the CSP policy does not exclude it.

Patches

A fix has been added as part of the 2.1.1 release.

Workarounds

To limit the impact, the following steps may be taken:

  • Upgrade to go-camo >= 2.1.1 release

Alternative mitigations

If you find yourself unable to upgrade, the following steps may be taken to mitigate the issue:

  • A CSP can be configured to prevent javascript execution for all resources proxied by Go-Camo. This prevents XSS.
  • Proxied resources can be served from a sub-domain separate from your site domain. This makes phishing less likely to succeed because the phishing page is not hosted under the main domain.

References

Special thanks to @dappelt and GitLab for the findings and very clear reporting of the issues.

For more information

If you have any questions or comments about this advisory:

Severity

High

CVE ID

CVE-2019-18923

Weaknesses

No CWEs

Credits