apps-script-oauth2
apps-script-oauth2 copied to clipboard
State token is not linked to the User's session. Possible CSRF attack
Hey team, I found a problem that apps-script-oauth2 library doesn't validate the link between state value and User sessions. As a result, CSRF protection (which used a state as a protection mechanism) doesn't work properly.
For example:
- The Attacker generate an oAuth link with state parameter for attacker's UserA account
- The Attacker send a link to malicious website to the Victim.
- As soon as it opens, malicious attacker's code log in the Victim to UserA account (somehow, it does not play a role in this case).
- And next, this code sends a request with link from step №1
- Finally, Apps Script will validate the state parameter successfully
So, the Victim will not know that he performed an action under UserA account. And for example, the malicious oAuth request could link the Victim's 3rd-party UserX account to UserA account. After that, the Attacker will be able to work with UserX account via oAuth.
If we check oAuth RFC, that said that:
This is typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent's authenticated state (e.g., a hash of the session cookie used to authenticate the user-agent).
But in this plugin, we bind token to user (not user-agent, session, etc).
What do you think about this problem?
Were you able to reproduce this this or concerned by not seeing it in the code? IIRC the state token validation and session binding is handled by the Apps Script runtime, not the library (the session isn't directly exposed to the script library, so not really possible to fix there.) If you are able to recreate this, let us know so we can file an appropriate issue against the script runtime.
Were you able to reproduce
Yep, steps to repro:
- Login to the same UserA account in 2 different browsers: BrowserA and BrowserB (e.g. Chrome and Firefox or Chrome and Chrome Incognito)
- Generate an oAuth URL for UserA in BrowserA
- Copy this URL from BrowserA
- Paste this URL to BrowserB and click "Enter"
- You'll be able to pass a state validation check
It means, the state, which was created for UserA in BrowserA (i.e. SessionA), is valid for UserA in BrowserB (i.e. SessionB)
Hey @sqrrrl, did you have a chance to check it?
Yes, the apps script team is looking into it. No updates yet, but will share what I can.
Like I said, user scripts/libraries don't have direct access to the session so we rely on the Apps Script runtime to both generate and validate the state token on our behalf.
Awesome, thank you so much!
I'll wait for updates :)
Hi @sqrrrl, are there any news from the Apps Scripts team regarding the issue? Thanks!
This has been reported fixed by the apps script team -- there's now stronger binding between the session/device and the state token. Closing here.