CSRF vuln on oauth grant approval #49

Merged
merged 2 commits into from Jul 26, 2013

Projects

None yet

3 participants

@tmaher
tmaher commented Jul 26, 2013

PoC: http://www.breaksec.com/herokuoauthnir.html - this will grant the oauth client "PWN" access to all applications. While the Rack::CSRF module is present...

https://github.com/heroku/identity/blob/master/lib/identity/auth.rb#L101-L104

we're treating GETs the same as POSTs, so it won't get enforced.

@brandur brandur merged commit 29e975f into master Jul 26, 2013
@brandur brandur deleted the brandur-close-csrf branch Jul 26, 2013
@tmaher tmaher commented on the diff Jul 26, 2013
test/auth_test.rb
@@ -81,6 +81,18 @@ def app
"?code=454118bc-902d-4a2c-9d5b-e2a2abb91f6e",
last_response.headers["Location"]
end
+
+ it "does not create an authorization if a user confirms via GET" do
+ post "/login", email: "kerry@heroku.com", password: "abcdefgh"
+
+ # post once to get parameters stored to session
+ post "/oauth/authorize", client_id: "untrusted"
+
+ # then try again, but with the wrong request method (should be POST)
+ get "/oauth/authorize", authorize: "Allow Access"
@tmaher
tmaher Jul 26, 2013

No client_id param?

@brandur
brandur Jul 26, 2013

It gets stored in session on the first request (this is how it works IRL too).

@tbroyer
tbroyer commented Nov 14, 2013

I'm coming here from https://blog.heroku.com/archives/2013/11/14/oauth-sso where you say OAuth is not clear and this led to this CSRF issue.
This may not be the best place to post this, but your blog doesn't accept comments; and this PR adds a similar comment to the code, so…

OAuth is actually really clear about the endpoint is: it's the URL the Client redirects to. OAuth doesn't care what you do to authorize: yes you'd probably POST something on the click to an Approve button, but OAuth doesn't care whether you do that with a form-post or through XHR (for example), and to which URL you're posting (Google posts to a distinct URL for example). The only thing that matters to OAuth is the interop between Clients and the Authorization Server, Clients need to redirect users to the Authorization Server (AS) at the Authorization Endpoint, then the AS has to redirect users back to the Clients at their Redirection Endpoint, and at some point (not necessarily at the Redirection Endpoint, there could be other redirections involved) Clients will make requests to the Token Endpoint of the AS. The Endpoints are defined as URLs that respond to specific HTTP methods and take specific parameters, everything else is up to the implementations are they don't change anything to the protocol between the Clients and the AS.

In the OAuth spec, the endpoints are all defined as HTTP resources that are used by the other party (notably, in this case, the Authorization Endpoint is “used by the client to obtain authorization from the resource owner via user-agent redirection.“) Because the approval is made by the user, not the Client, it's not made to the Authorization Endpoint. It could be the same URL but then you'd have to either not support “POST at the Authorization Endpoint” (which is allowed per spec), or be able to tell which kind of request this is (what you didn't do, and this PR fixed).

@brandur
brandur commented Nov 14, 2013

@tbroyer Great points here, and thanks a lot for the detailed write-up! It's obvious that your understanding of the spec is much deeper than my own. I'm going to let @tmaher field this one. Maybe an edit to the original post is in order?

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