
All versions of nosurf before 1.2.0 failed to apply same-origin checks for incoming requests.
This happened due to relying on the .URL.Scheme field on Go standard library's net/http.Request type
to first ensure that the request is served over HTTPS, and only then apply same-origin checks.
The aforementioned Scheme field is not filled out by the Go HTTP server on incoming requests:
// For server requests, the URL is parsed from the URI // supplied on the Request-Line as stored in RequestURI. For // most requests, fields other than Path and RawQuery will be // empty.
as in the general case Go can not tell whether the request is happening over TLS (due to a possible presence of a TLS-terminating reverse proxy, etc.).
This may allow attackers to issue non-safe cross-origin requests to your website.
In addition to implementing same-origin checks, nosurf additionally protects from CSRF using a double-submit cookie patern.
This means that, to successfully make a mutating cross-origin request,
the attacker also needs control over the contents of a page on your website,
or on a subdomain of your website.
This can be achieved via XSS, or if you intentionally give control of the HTML content for users on your website
(e.g. you are a hosting provider example.com that allows users to host their websites at alice.example.com).
The PoC in this repository demonstrates such attack in the latter case, where attacker has control of the content on a subdomain of the website's main domain.
Requires Go and Caddy. Run the servers manually:
$ go run attacker.go & go run target.go & caddy run
or via Process Compose:
$ process-compose
Visit https://attacker.target.localhost.
Click the button to submit the form to https://target.localhost and observe that the request completes successfully.
A fix for this issue was released in nosurf 1.2.0.
Thanks to Patrick O'Doherty for reporting the issue.