Skip to content

[codeql-go]: Add query to find use of constant state parameter in Oauth2 flow #295

@gagliardetto

Description

@gagliardetto

The Query

This query was merged into the codeql-go repository through this PR: github/codeql-go#259

CVE ID(s)

No CVEs, yet.

Report

Short summary

This query finds oauth2 clients that use a constant value for the state parameter when creating an authentication URL in the Oauth2 authorization flow, which makes them vulnerable to CSRF.

Longer summary

Let's imagine there's a new web app (open-source) that allows you to save your Z**m recordings automatically to Google Drive; the app is called z2gd.example, reachable at https://z2gd.example (not really).

Users of z2gd.example can add a Z**m account and one or more Google Drive accounts.

Each time you have a Z**m meeting, it gets automagically uploaded to all Google Drive accounts you added to your z2gd.example account!

Now let's see the process of linking a Google Drive account:

(The API URLs are oversimplified for the sake of the example.)

  1. You go to https://z2gd.example/add/gdrive
  2. You get redirected to https://drive.google.com/oauth/authorize?client_id=cl-ymV47&redirect_uri=https://z2gd.example/oauth/callback/gdrive&state=DemoUserState (more or less), where you'll be asked to authorize z2gd.example's write access to your Google Drive account. You accept and click OK.
  3. Google then sends an authorization token (code) back to z2gd.example by redirecting you to the specified callback (see above URL) and adding the auth code to the callback URL parameters: https://z2gd.example/oauth/callback/gdrive?code=OA-6lWMywf6&state=DemoUserState
  4. Now, you're already logged in to z2gd.example, so it knows that the Google Drive auth code it is receiving is to be added to your account...
  5. ...and that's what happens; z2gd adds that new Google Drive account to the list of places it will send your Z**m metting recordings to.

Did you notice the mistake that someone at z2gd.example made? They forgot to set a proper state parameter of the Oauth2 flow!

Why that matters? Let's make up an attack scenario:

  • evilmaster0x00 wants to hear in your Z**m meetings to steal all your precious IP and trade secrets.
  • evilmaster0x00 signs up to z2gd.example and initializes the linking of his account to Google Drive; he authorizes z2gd.example to upload videos to his Google Drive account, but right before Google redirects to https://z2gd.example/oauth/callback/gdrive, he intercepts the request so it never happens, and the Google Drive never gets added to his z2gd.example account. But he now has the callback address to add his google drive account to ANY z2gd.example account: https://z2gd.example/oauth/callback/gdrive?code=OA-0BIVx12W&state=DemoUserState
  • You receive a link (a short link) to a cute picture of cat, but it just redirects you somewhere, and you end up on a z2gd.example page you thought you closed before (or, even better, z2gd.example has an open redirect and you actually get to see the cute cat picture). Oh well. Never mind. Back to work.
  • What really happened is that you ended up on https://z2gd.example/oauth/callback/gdrive?code=OA-0BIVx12W&state=DemoUserState, and that means that now evilmaster0x00 added his Google Drive account to your z2gd.example account. Now he's part of your team :)

Had z2gd.example developers set a proper, unique, per-user, per-transaction state value, the attacker could have never guessed it and his malicious callback URL would have not worked, keeping your Z**m recordings safe.

  • Are you planning to discuss this vulnerability submission publicly? (Blog Post, social networks, etc). We would love to have you spread the word about the good work you are doing

No, I'm not planning on discussing this vulnerability submission publicly.

References

https://tools.ietf.org/html/rfc6819#section-4.4.1.8

https://tools.ietf.org/html/rfc6819#section-3.6

Result(s)

Provide at least one useful result found by your query, on some revision of a real project.

Metadata

Metadata

Assignees

No one assigned

    Labels

    All For OneSubmissions to the All for One, One for All bounty

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions