BCP 78 BCP 79
BCP 78 BCP 79
Lodderstedt
Internet-Draft yes.com
Intended status: Best Current Practice J. Bradley
Expires: January 9, 2020 Yubico
A. Labunets
Facebook
D. Fett
yes.com
July 8, 2019
Abstract
This document describes best current security practice for OAuth 2.0.
It updates and extends the OAuth 2.0 Security Threat Model to
incorporate practical experiences gathered since OAuth 2.0 was
published and covers new threats relevant due to the broader
application of OAuth 2.0.
Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Structure . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2. Conventions and Terminology . . . . . . . . . . . . . . . 4
2. The Updated OAuth 2.0 Attacker Model . . . . . . . . . . . . 4
3. Recommendations . . . . . . . . . . . . . . . . . . . . . . . 6
3.1. Protecting Redirect-Based Flows . . . . . . . . . . . . . 6
3.1.1. Authorization Code Grant . . . . . . . . . . . . . . 7
3.1.2. Implicit Grant . . . . . . . . . . . . . . . . . . . 8
3.2. Token Replay Prevention . . . . . . . . . . . . . . . . . 8
3.3. Access Token Privilege Restriction . . . . . . . . . . . 9
3.4. Resource Owner Password Credentials Grant . . . . . . . . 9
3.5. Client Authentication . . . . . . . . . . . . . . . . . . 10
3.6. Other Recommendations . . . . . . . . . . . . . . . . . . 10
4. Attacks and Mitigations . . . . . . . . . . . . . . . . . . . 10
4.1. Insufficient Redirect URI Validation . . . . . . . . . . 10
4.1.1. Redirect URI Validation Attacks on Authorization Code
Grant . . . . . . . . . . . . . . . . . . . . . . . . 11
4.1.2. Redirect URI Validation Attacks on Implicit Grant . . 12
4.1.3. Proposed Countermeasures . . . . . . . . . . . . . . 13
4.2. Credential Leakage via Referrer Headers . . . . . . . . . 14
4.2.1. Leakage from the OAuth Client . . . . . . . . . . . . 14
4.2.2. Leakage from the Authorization Server . . . . . . . . 14
4.2.3. Consequences . . . . . . . . . . . . . . . . . . . . 14
4.2.4. Proposed Countermeasures . . . . . . . . . . . . . . 14
4.3. Attacks through the Browser History . . . . . . . . . . . 15
4.3.1. Code in Browser History . . . . . . . . . . . . . . . 16
4.3.2. Access Token in Browser History . . . . . . . . . . . 16
4.4. Mix-Up . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4.1. Attack Description . . . . . . . . . . . . . . . . . 17
4.4.2. Countermeasures . . . . . . . . . . . . . . . . . . . 18
4.5. Authorization Code Injection . . . . . . . . . . . . . . 19
4.5.1. Attack Description . . . . . . . . . . . . . . . . . 19
4.5.2. Discussion . . . . . . . . . . . . . . . . . . . . . 20
4.5.3. Proposed Countermeasures . . . . . . . . . . . . . . 21
4.6. Access Token Injection . . . . . . . . . . . . . . . . . 23
4.6.1. Proposed Countermeasures . . . . . . . . . . . . . . 23
4.7. Cross Site Request Forgery . . . . . . . . . . . . . . . 23
4.7.1. Proposed Countermeasures . . . . . . . . . . . . . . 23
4.8. Access Token Leakage at the Resource Server . . . . . . . 24
4.8.1. Access Token Phishing by Counterfeit Resource Server 24
1. Introduction
1.1. Structure
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
OAuth 2.0 MUST ensure that the authorization of the resource owner
(RO) (with a user agent) at an authorization server (AS) and the
subsequent usage of the access token at the resource server (RS) is
protected at least against the following attackers:
These attackers conform to the attacker model that was used in formal
analysis efforts for OAuth [arXiv.1601.01229]. Previous attacks on
OAuth have shown that OAuth deployments SHOULD protect against an
even stronger attacker model that is described as follows:
o (A3) Attackers that can read, but not modify, the contents of the
authorization response (i.e., the authorization response can leak
to an attacker).
Examples for such attacks include open redirector attacks,
problems existing on mobile operating systems (where different
apps can register themselves on the same URI), so-called mix-up
attacks, where the client is tricked into sending credentials to a
attacker-controlled AS, and the fact that URLs are often stored/
logged by browsers (history), proxy servers, and operating
systems.
o (A4) Attackers that can read, but not modify, the contents of the
authorization request (i.e., the authorization request can leak,
in the same manner as above, to an attacker).
3. Recommendations
Clients MUST prevent CSRF. One-time use CSRF tokens carried in the
"state" parameter, which are securely bound to the user agent, SHOULD
be used for that purpose. If PKCE [RFC7636] is used by the client
and the authorization server supports PKCE, clients MAY opt to not
use "state" for CSRF protection, as such protection is provided by
PKCE. In this case, "state" MAY be used again for its original
purpose, namely transporting data about the application state of the
client (see Section 4.7.1).
Clients SHOULD use PKCE code challenge methods that do not expose the
PKCE verifier in the authorization request. (Otherwise, the attacker
A4 can trivially break the security provided by PKCE.) Currently,
"S256" is the only such method.
The implicit grant (response type "token") and other response types
causing the authorization server to issue access tokens in the
authorization response are vulnerable to access token leakage and
access token replay as described in Section 4.1, Section 4.2,
Section 4.3, and Section 4.6.
In order to avoid these issues, clients SHOULD NOT use the implicit
grant (response type "token") or any other response type issuing
access tokens in the authorization response, such as "token id_token"
and "code token id_token", unless the issued access tokens are
sender-constrained and access token injection in the authorization
response is prevented.
The resource owner password credentials grant MUST NOT be used. This
grant type insecurely exposes the credentials of the resource owner
to the client. Even if the client is benign, this results in an
increased attack surface (credentials can leak in more places than
just the AS) and users are trained to enter their credentials in
places other than the AS.
For a public client using the grant type code, an attack would look
as follows:
First, the attacker needs to trick the user into opening a tampered
URL in his browser, which launches a page under the attacker’s
control, say "https://www.evil.example". (See Attacker A1.)
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=9ad67f13
&redirect_uri=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Fevil.somesite.example%2Fcb HTTP/1.1
Host: server.somesite.example
If the user does not recognize the attack, the code is issued and
immediately sent to the attacker’s client.
Note: This attack will not work as easily for confidential clients,
since the code exchange requires authentication with the legitimate
client’s secret. The attacker will need to impersonate or utilize
the legitimate client to redeem the code (e.g., by performing a code
injection attack). This kind of injections is covered in
Section 4.5.
The attack described above works for the implicit grant as well. If
the attacker is able to send the authorization response to a URI
under his control, he will directly get access to the fragment
carrying the access token.
First, and as above, the attacker needs to trick the user into
opening a tampered URL in his browser, which launches a page under
the attacker’s control, say "https://www.evil.example".
GET /authorize?response_type=token&state=9ad67f13
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Fclient.somesite.example
%2Fcb%26redirect_to%253Dhttps%253A%252F
%252Fclient.evil.example%252Fcb HTTP/1.1
Host: server.somesite.example
Now, since the redirect URI matches the registered pattern, the
authorization server allows the request and sends the resulting
access token with a 303 redirect (some response parameters are
omitted for better readability)
https://client.evil.example/cb#access_token=2YotnFZFEjr1z...
Additional recommendations:
Leakage from the OAuth client requires that the client, as a result
of a successful authorization request, renders a page that
4.2.3. Consequences
o Additionally, one might use the form post response mode instead of
redirect for authorization response (see
[oauth-v2-form-post-response-mode]).
Proposed countermeasures:
Proposed countermeasures:
4.4. Mix-Up
1. The user selects to start the grant using H-AS (e.g., by clicking
on a button at the client’s website).
3. The client stores in the user’s session that the user selected
"A-AS" and redirects the user to A-AS’s authorization endpoint by
sending the response code "303 See Other" with a Location header
containing the URL "https://attacker.example/
authorize?response_type=code&client_id=666RVZJTA".
"https://honest.as.example/
authorize?response_type=code&client_id=7ZGZldHQ"
6. Since the client still assumes that the code was issued by A-AS,
it will try to redeem the code at A-AS’s token endpoint.
7. The attacker therefore obtains code and can either exchange the
code for an access token (for public clients) or perform a code
injection attack as described in Section 4.5.
Variants:
4.4.2. Countermeasures
Potential countermeasures:
4.5.2. Discussion
Obviously, the check in step (5.) will fail if the code was issued to
another client id, e.g., a client set up by the attacker. The check
will also fail if the authorization code was already redeemed by the
legitimate user and was one-time use only.
Note: this check could also detect attempts to inject a code which
had been obtained from another instance of the same client on another
device, if certain conditions are fulfilled:
But this approach conflicts with the idea to enforce exact redirect
URI matching at the authorization endpoint. Moreover, it has been
observed that providers very often ignore the "redirect_uri" check
requirement at this stage, maybe because it doesn’t seem to be
security-critical from reading the specification.
To conduct the attack, the adversary starts an OAuth flow with the
client and modifies the authorization response by replacing the
access token issued by the authorization server or directly makes up
an authorization server response including the leaked access token.
Since the response includes the state value generated by the client
for this particular transaction, the client does not treat the
response as a CSRF and will use the access token injected by the
attacker.
Use of CSRF tokens which are bound to the user agent and passed in
the "state" parameter to the authorization server as described in
[!@RFC6819]. Alternatively, PKCE provides CSRF protection.
o Clients MUST ensure that the AS supports PKCE before using PKCE
for CSRF protection. If an authorization server does not support
PKCE, "state" MUST be used for CSRF protection.
An attacker may setup his own resource server and trick a client into
sending access tokens to it that are valid for other resource servers
(see Attackers A1 and A5). If the client sends a valid access token
to this counterfeit resource server, the attacker in turn may use
that token to access other services on behalf of the resource owner.
This attack assumes the client is not bound to one specific resource
server (and its URL) at development time, but client instances are
provided with the resource server URL at runtime. This kind of late
binding is typical in situations where the client uses a service
implementing a standardized API (e.g., for e-Mail, calendar, health,
or banking) and where the client is configured by a user or
administrator for a service which this user or company uses.
4.8.1.1. Metadata
HTTP/1.1 200 OK
Content-Type: application/json
{
"issuer":"https://server.somesite.example",
"authorization_endpoint":
"https://server.somesite.example/authorize",
"resource_servers":[
"email.somesite.example",
"storage.somesite.example",
"video.somesite.example"
]
...
}
The AS could also return the URL(s) an access token is good for in
the token response, illustrated by the example return parameter
"access_token_resource_server":
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"access_token_resource_server":
"https://hostedresource.somesite.example/path1",
...
}
Mutual TLS and OAuth Token Binding are built on top of TLS and this
way continue the successful OAuth 2.0 philosophy to leverage TLS to
secure OAuth wherever possible. Both mechanisms allow prevention of
access token leakage in a fairly client developer friendly way.
Audience restriction seems easy to use since it does not require any
crypto on the client side. But since every access token is bound to
a certain resource server, the client also needs to obtain different
RS-specific access tokens, if it wants to access several resource
services. [I-D.ietf-oauth-token-binding] has the same property,
since different token binding ids must be associated with the access
token. [I-D.ietf-oauth-mtls] on the other hand allows a client to
use the access token at multiple resource servers.
If the attacker was able to take over full control including shell
access it will be able to circumvent all controls in place and access
resources without access control. It will also get access to access
tokens, which are sent to the compromised system and which
potentially are valid for access to other resource servers as well.
Even if the attacker "only" is able to access logfiles or databases
of the server system, it may get access to valid access tokens.
o The resource server must treat access tokens like any other
credentials. It is considered good practice to not log them and
not to store them in plain text.
In [RFC6749], the HTTP status code 302 is used for this purpose, but
"any other method available via the user-agent to accomplish this
redirection is allowed". However, when the status code 307 is used
for redirection, the user agent will send the form data (user
credentials) via HTTP POST to the client since this status code does
not require the user agent to rewrite the POST request to a GET
request (and thereby dropping the form data in the POST request
body). If the relying party is malicious, it can use the credentials
to impersonate the user at the AS.
If the reverse proxy would pass through any header sent from the
outside, an attacker could try to directly send the faked header
values through the proxy to the application server in order to
circumvent security controls that way. For example, it is standard
practice of reverse proxies to accept "forwarded_for" headers and
just add the origin of the inbound request (making it a list).
Depending on the logic performed in the application server, the
attacker could simply add a whitelisted IP address to the header and
render a IP whitelist useless. A reverse proxy must therefore
sanitize any inbound requests to ensure the authenticity and
integrity of all header values relevant for the security of the
application servers.
o password change
Refresh tokens SHOULD expire if the client has been inactive for some
time, i.e., the refresh token has not been used to obtain fresh
access tokens for some time. The expiration time is at the
discretion of the authorization server. It might be a global value
or determined based on the client policy or the grant associated with
the refresh token (and its sensitivity).
5. Acknowledgements
We would like to thank Jim Manico, Phil Hunt, Nat Sakimura, Christian
Mainka, Doug McDorman, Johan Peeters, Joseph Heenan, Brock Allen,
Vittorio Bertocci, David Waite, Nov Matake, Tomek Stojecki, Dominick
Baier, Neil Madden, William Dennis, Dick Hardt, Petteri Stenius,
Annabelle Richard Backman, Aaron Parecki, George Fletscher, Brian
Campbell, Konstantin Lapine, and Tim Wuertele for their valuable
feedback.
6. IANA Considerations
7. Security Considerations
8. References
[oauth-v2-form-post-response-mode]
Jones, M. and B. Campbell, "OAuth 2.0 Form Post Response
Mode", April 2015, <http://openid.net/specs/
oauth-v2-form-post-response-mode-1_0.html>.
[OpenID] Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and
C. Mortimore, "OpenID Connect Core 1.0 incorporating
errata set 1", Nov 2014,
<http://openid.net/specs/openid-connect-core-1_0.html>.
[RFC6819] Lodderstedt, T., Ed., McGloin, M., and P. Hunt, "OAuth 2.0
Threat Model and Security Considerations", RFC 6819,
DOI 10.17487/RFC6819, January 2013,
<https://www.rfc-editor.org/info/rfc6819>.
[RFC7636] Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key
for Code Exchange by OAuth Public Clients", RFC 7636,
DOI 10.17487/RFC7636, September 2015,
<https://www.rfc-editor.org/info/rfc7636>.
[arXiv.1508.04324v2]
Mladenov, V., Mainka, C., and J. Schwenk, "On the security
of modern Single Sign-On Protocols: Second-Order
Vulnerabilities in OpenID Connect", January 2016,
<http://arxiv.org/abs/1508.04324v2/>.
[arXiv.1601.01229]
Fett, D., Kuesters, R., and G. Schmitz, "A Comprehensive
Formal Security Analysis of OAuth 2.0", January 2016,
<http://arxiv.org/abs/1601.01229/>.
[arXiv.1704.08539]
Fett, D., Kuesters, R., and G. Schmitz, "The Web SSO
Standard OpenID Connect: In-Depth Formal Security Analysis
and Security Guidelines", April 2017,
<http://arxiv.org/abs/1704.08539/>.
[arXiv.1901.11520]
Fett, D., Hosseyni, P., and R. Kuesters, "An Extensive
Formal Security Analysis of the OpenID Financial-grade
API", January 2019, <http://arxiv.org/abs/1901.11520/>.
[bug.chromium]
"Referer header includes URL fragment when opening link
using New Tab",
<https://bugs.chromium.org/p/chromium/issues/
detail?id=168213/>.
[fb_fragments]
"Facebook Developer Blog",
<https://developers.facebook.com/blog/post/552/>.
[I-D.bradley-oauth-jwt-encoded-state]
Bradley, J., Lodderstedt, T., and H. Zandbelt, "Encoding
claims in the OAuth 2 state parameter using a JWT", draft-
bradley-oauth-jwt-encoded-state-09 (work in progress),
November 2018.
[I-D.ietf-oauth-closing-redirectors]
Bradley, J., Sanso, A., and H. Tschofenig, "OAuth 2.0
Security: Closing Open Redirectors in OAuth", draft-ietf-
oauth-closing-redirectors-00 (work in progress), February
2016.
[I-D.ietf-oauth-jwsreq]
Sakimura, N. and J. Bradley, "The OAuth 2.0 Authorization
Framework: JWT Secured Authorization Request (JAR)",
draft-ietf-oauth-jwsreq-19 (work in progress), June 2019.
[I-D.ietf-oauth-mix-up-mitigation]
Jones, M., Bradley, J., and N. Sakimura, "OAuth 2.0 Mix-Up
Mitigation", draft-ietf-oauth-mix-up-mitigation-01 (work
in progress), July 2016.
[I-D.ietf-oauth-mtls]
Campbell, B., Bradley, J., Sakimura, N., and T.
Lodderstedt, "OAuth 2.0 Mutual TLS Client Authentication
and Certificate-Bound Access Tokens", draft-ietf-oauth-
mtls-15 (work in progress), July 2019.
[I-D.ietf-oauth-pop-key-distribution]
Bradley, J., Hunt, P., Jones, M., Tschofenig, H., and M.
Meszaros, "OAuth 2.0 Proof-of-Possession: Authorization
Server to Client Key Distribution", draft-ietf-oauth-pop-
key-distribution-07 (work in progress), March 2019.
[I-D.ietf-oauth-resource-indicators]
Campbell, B., Bradley, J., and H. Tschofenig, "Resource
Indicators for OAuth 2.0", draft-ietf-oauth-resource-
indicators-02 (work in progress), January 2019.
[I-D.ietf-oauth-signed-http-request]
Richer, J., Bradley, J., and H. Tschofenig, "A Method for
Signing HTTP Requests for OAuth", draft-ietf-oauth-signed-
http-request-03 (work in progress), August 2016.
[I-D.ietf-oauth-token-binding]
Jones, M., Campbell, B., Bradley, J., and W. Denniss,
"OAuth 2.0 Token Binding", draft-ietf-oauth-token-
binding-08 (work in progress), October 2018.
[I-D.sakimura-oauth-jpop]
Sakimura, N., Li, K., and J. Bradley, "The OAuth 2.0
Authorization Framework: JWT Pop Token Usage", draft-
sakimura-oauth-jpop-04 (work in progress), March 2017.
[oauth_security_cmu]
Chen, E., Pei, Y., Chen, S., Tian, Y., Kotcher, R., and P.
Tague, "OAuth Demystified for Mobile Application
Developers", November 2014.
[oauth_security_jcs_14]
Bansal, C., Bhargavan, K., Delignat-Lavaud, A., and S.
Maffeis, "Discovering concrete attacks on website
authorization by formal analysis", April 2014.
[oauth_security_ubc]
Sun, S. and K. Beznosov, "The Devil is in the
(Implementation) Details: An Empirical Analysis of OAuth
SSO Systems", October 2012,
<http://passwordresearch.com/papers/paper267.html>.
[owasp_csrf]
"Cross-Site Request Forgery (CSRF) Prevention Cheat
Sheet", <https://www.owasp.org/index.php/
Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet>.
[RFC7591] Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and
P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol",
RFC 7591, DOI 10.17487/RFC7591, July 2015,
<https://www.rfc-editor.org/info/rfc7591>.
[RFC8473] Popov, A., Nystroem, M., Balfanz, D., Ed., Harper, N., and
J. Hodges, "Token Binding over HTTP", RFC 8473,
DOI 10.17487/RFC8473, October 2018,
<https://www.rfc-editor.org/info/rfc8473>.
[webappsec-referrer-policy]
Eisinger, J. and E. Stark, "Referrer Policy", April 2017,
<https://w3c.github.io/webappsec-referrer-policy>.
-13
-12
-11
-10
-09
-08
-07
-06
-05
-04
-03
-02
o Folded Mix up and Access Token leakage through a bad AS into new
section for dynamic OAuth threats
-01
Authors’ Addresses
Torsten Lodderstedt
yes.com
Email: [email protected]
John Bradley
Yubico
Email: [email protected]
Andrey Labunets
Facebook
Email: [email protected]
Daniel Fett
yes.com
Email: [email protected]