Internet DRAFT - draft-eaton-oauth-bodyhash
draft-eaton-oauth-bodyhash
Network Working Group B. Eaton
Internet-Draft Google
Intended status: Standards Track E. Hammer-Lahav, Ed.
Expires: October 13, 2009 Yahoo!
April 11, 2009
OAuth Request Body Hash
draft-eaton-oauth-bodyhash-00
Status of this Memo
This Internet-Draft is submitted to IETF in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that
other groups may also distribute working documents as Internet-
Drafts.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html.
This Internet-Draft will expire on October 13, 2009.
Copyright Notice
Copyright (c) 2009 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents in effect on the date of
publication of this document (http://trustee.ietf.org/license-info).
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document.
Abstract
This specification extends the OAuth signature to include integrity
checks on HTTP request bodies with content types other than
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 1]
Internet-Draft OAuth Request Body Hash April 2009
"application/x-www-form-urlencoded".
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Notation and Conventions . . . . . . . . . . . . . . . . . . . 3
3. The oauth_body_hash Parameter . . . . . . . . . . . . . . . . 4
3.1. Hash Algorithm . . . . . . . . . . . . . . . . . . . . . . 4
3.2. Hash Calculation . . . . . . . . . . . . . . . . . . . . . 4
4. Changes to OAuth Request Signing . . . . . . . . . . . . . . . 4
4.1. Sending Requests . . . . . . . . . . . . . . . . . . . . . 4
4.1.1. When to Include the Body Hash . . . . . . . . . . . . 4
4.1.2. Adding oauth_body_hash to Requests . . . . . . . . . . 5
4.2. Verifying Requests . . . . . . . . . . . . . . . . . . . . 5
4.2.1. When to Verify the Hash . . . . . . . . . . . . . . . 6
4.2.2. Verifying the Hash . . . . . . . . . . . . . . . . . . 6
5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 6
6. Security Considerations . . . . . . . . . . . . . . . . . . . 6
6.1. Only Trust What is Signed . . . . . . . . . . . . . . . . 6
6.2. Deprecation of SHA-1 . . . . . . . . . . . . . . . . . . . 7
Appendix A. Examples . . . . . . . . . . . . . . . . . . . . . . 7
Appendix A.1. Example PUT Request . . . . . . . . . . . . . . . . 7
Appendix A.2. Example GET Request . . . . . . . . . . . . . . . . 8
Appendix B. Obtaining the HTTP Entity Body . . . . . . . . . . . 9
Appendix C. Unkeyed vs Keyed Hash Algorithms . . . . . . . . . . 9
Appendix D. Preventing Removal of Request Bodies . . . . . . . . 9
Appendix E. Acknowledgements . . . . . . . . . . . . . . . . . . 10
7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 11
7.1. Normative References . . . . . . . . . . . . . . . . . . . 11
7.2. Informative References . . . . . . . . . . . . . . . . . . 11
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 11
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 2]
Internet-Draft OAuth Request Body Hash April 2009
1. Introduction
The OAuth Core specification [OAuth Core 1.0] provides body integrity
checking only for "application/x-www-form-urlencoded" request bodies.
Other types of request bodies are left unsigned. An eavesdropper or
man-in-the-middle who captures a signed request URI may be able to
forward or replay that URI with a different HTTP request body. Nonce
checking and the use of https can mitigate this risk, but may not be
available in some environments. Even when nonce checking and https
are used, signing the request body provides an additional layer of
defense.
This specification describes a method to provide an integrity check
on non-form-encoded request bodies. The normal OAuth signature base
string is enhanced by adding an additional parameter with the hash of
the request body. An unkeyed hash is used for the reasons described
in Appendix C.
This extension is forward compatible: Service Providers that have not
implemented this extension can verify requests sent by Consumers that
have implemented this extension. If the Service Provider implements
this specification the integrity of the body is guaranteed. If the
Service Provider does not check body signatures, the remainder of the
request will still validate using the OAuth Core signature algorithm.
This specification is only useful when cryptographic signatures are
used. The OAuth "PLAINTEXT" signature algorithm does not provide
integrity checks for any portion of the request and is not supported
by this specification.
The use of this specification with versions of the OAuth protocol
other than "1.0" is undefined.
2. Notation and Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC2119].
Unless otherwise noted, this specification is written as a direct
continuation of [OAuth Core 1.0], inheriting the definitions and
guidelines set by it.
To make the specification easier to read, HTTP entity-bodies
following the encoding requirements of the
"application/x-www-form-urlencoded" content-type as defined by
[W3C.REC-html40-19980424] are simply referred to as form-encoded.
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 3]
Internet-Draft OAuth Request Body Hash April 2009
3. The oauth_body_hash Parameter
3.1. Hash Algorithm
The body hash algorithm is determined by the OAuth signature method
used:
o If the OAuth signature method is "HMAC-SHA1" or "RSA-SHA1", SHA1
[RFC3174] MUST be used as the body hash algorithm.
o If the OAuth signature method is "PLAINTEXT", use of this
specification provides no security benefit and is NOT RECOMMENDED.
New OAuth signature method specifications SHOULD specify the hash
algorithm used to generate the body hash.
3.2. Hash Calculation
The value of the oauth_body_hash parameter SHALL be set as follows:
1. The body hash value is calculated by executing the selected hash
algorithm over the request body. The request body is the entity
body as defined in [RFC2616] section 7.2. If the request does
not have an entity body, the hash should be taken over the empty
string.
2. The calculated body hash value is encoded using Base64 per
[RFC2045].
4. Changes to OAuth Request Signing
4.1. Sending Requests
OAuth Consumers include the oauth_body_hash parameter according to
the rules described in this section, and continue to sign requests in
the manner described by [OAuth Core 1.0] section 9.
4.1.1. When to Include the Body Hash
Not all requests should contain the oauth_body_hash parameter.
o OAuth Consumers SHOULD NOT include an oauth_body_hash parameter
when making Request Token or Access Token OAuth requests.
o OAuth Consumers MUST NOT include an oauth_body_hash parameter on
requests with form-encoded request bodies. The presence or
absence
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 4]
Internet-Draft OAuth Request Body Hash April 2009
o OAuth Consumers SHOULD include the oauth_body_hash parameter on
all other requests.
Some OAuth Service Providers have implemented Request Token and
Access Token endpoints that reject requests that include unknown
parameters. Sending an oauth_body_hash parameter to such endpoints
will cause protocol failures. The oauth_body_hash parameter does not
provide additional security for OAuth request token and access token
requests since all of the protocol parameters are signed by the OAuth
Core signature mechanism. Omitting the parameter improves
interoperability without reducing security.
The presence or absence of the oauth_body_hash parameter is used to
indicate to Service Providers how they should check the integrity of
the request body. If no oauth_body_hash parameter is present, that
indicates that the request body is form-encoded and signed using the
OAuth Core signature algorithm. If the oauth_body_hash parameter is
present, the body is signed according to this extension. Including
an oauth_body_hash on form-encoded requests would make it impossible
for Service Providers to determine which body signing mechanism was
used for the request. This ambiguity would, in turn, allow the
attack described in Appendix D.
4.1.2. Adding oauth_body_hash to Requests
To include the oauth_body_hash parameter in OAuth-authenticated
requests, Consumers SHALL:
1. Determine whether the parameter should be included using the
rules described in Section 4.1.1.
2. Calculate the body hash value as described in Section 3
3. Set the oauth_body_hash parameter to the obtained value.
4. Sign the request as per [OAuth Core 1.0] section 9. The
oauth_body_hash parameter MUST be included in the Signature Base
String together with the other request parameters.
5. Transmit the oauth_body_hash parameter along with the other OAuth
Protocol parameters in the signed OAuth request.
4.2. Verifying Requests
Service Providers verify the integrity of request bodies by verifying
the OAuth signature as described in [OAuth Core 1.0] and also
verifying the value of the oauth_body_hash parameter.
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 5]
Internet-Draft OAuth Request Body Hash April 2009
4.2.1. When to Verify the Hash
Service Providers MUST decide whether the oauth_body_hash parameter
is necessary according to the rules described in Section 4.1.1.
If the request MUST NOT have an oauth_body_hash parameter, Service
Providers MUST verify that no oauth_body_hash parameter is present.
In particular, any requests with a form-encoded content-type and an
oauth_body_hash parameter MUST be rejected because of of the attack
described in Appendix D.
If the request should have an oauth_body_hash parameter but does not
contain one, the request was sent by a Consumer that does not support
this extension. The integrity of the request body cannot be checked
using this specification. Service Providers MAY accept such requests
for interoperability, or they MAY reject such requests in favor of
security.
4.2.2. Verifying the Hash
If the Service Provider determines body hash verification is
necessary, the Service Provider calculates the expected body hash for
the request as described in Section 3.
The Service Provider then compares the expected body hash with the
value sent by the Consumer in the oauth_body_hash parameter. If the
values match, the body is intact and the request can proceed.
If the values do not match, the request MUST be rejected.
Rather than comparing text values, Service Providers MAY Base64
decode (per [RFC2045]) the oauth_body_hash parameter and perform the
comparison on the octets of the hash. This reduces the risk of minor
differences in URI encoding or Base64 encoding causing spurious
integrity check failures.
5. IANA Considerations
This memo includes no request to IANA.
6. Security Considerations
6.1. Only Trust What is Signed
Many factors besides the bytes of the request body can influence the
interpretation of the body of the HTTP request. For example, a
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 6]
Internet-Draft OAuth Request Body Hash April 2009
content-type or content-encoding header can change the way a server
handles an HTTP request. This specification does not include an
integrity check on the HTTP request headers. OAuth deployments whose
security could be impacted by an attacker who tampers with HTTP
request headers should use other mechanisms (such as HTTPS) to
protect the confidentiality and integrity of the entire HTTP request.
6.2. Deprecation of SHA-1
In [NIST 800-107] the NIST Computer Security Division has recommended
that applications stop using SHA-1 for digital signatures. As of the
time of this writing, all of the cryptographic signature schemes
defined for OAuth are based on SHA-1. OAuth signature methods based
on stronger hash functions need to be developed, and those signature
methods will need to specify algorithms for calculating the
oauth_body_hash as well.
Appendix A. Examples
Appendix A.1. Example PUT Request
Sample HTTP request:
PUT /resource HTTP/1.1
Host: www.example.com
Content-Type: text/plain
Content-Length: 12
Hello World!
Base64 encoded SHA-1 hash of the body:
Lve95gjOVATpfV8EL5X4nxwjKHE=
Signature Base String (with some line breaks added for readability):
PUT&http%3A%2F%2Fwww.example.com%2Fresource&oauth_body_hash%3D
Lve95gjOVATpfV8EL5X4nxwjKHE%253D%26oauth_consumer_key%3Dconsum
er%26oauth_nonce%3D10369470270925%26oauth_signature_method%3DH
MAC-SHA1%26oauth_timestamp%3D1236874236%26oauth_token%3Dtoken%
26oauth_version%3D1.0
Signed request with body hash (with some line breaks added for
readability):
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 7]
Internet-Draft OAuth Request Body Hash April 2009
PUT /resource HTTP/1.1
Host: www.example.com
Authorization: OAuth realm="http%3A%2F%2Fwww.example.com",
oauth_body_hash="Lve95gjOVATpfV8EL5X4nxwjKHE%3D",
oauth_token="token",
oauth_consumer_key="consumer",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1236874155", oauth_nonce="10288510250934",
oauth_version="1.0",
oauth_signature="08bUFF%2Fjmp59mWB7cSgCYBUpJ0U%3D"
Content-Type: text/plain
Content-Length: 12
Hello World!
Appendix A.2. Example GET Request
Sample HTTP request:
GET /resource HTTP/1.1
Host: www.example.com
Base64 encoded SHA-1 hash of the (non-existent) body:
2jmj7l5rSw0yVb/vlWAYkK/YBwk=
Signature Base String (line breaks added for readability):
GET&http%3A%2F%2Fwww.example.com%2Fresource&oauth_body_hash%3D2jmj7
l5rSw0yVb%252FvlWAYkK%252FYBwk%253D%26oauth_consumer_key%3Dconsumer
%26oauth_nonce%3D8628868109991%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1238395022%26oauth_token%3Dtoken%26oauth_versi
on%3D1.0
Signed request with body hash (with some line breaks added for
readability):
GET /resource HTTP/1.1
Host: www.example.com
Authorization: OAuth realm="http%3A%2F%2Fwww.example.com",
oauth_body_hash="2jmj7l5rSw0yVb/vlWAYkK/YBwk%3D",
oauth_token="token",
oauth_consumer_key="consumer",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1236874155", oauth_nonce="10288510250934",
oauth_version="1.0",
oauth_signature="08bUFF%2Fjmp59mWB7cSgCYBUpJ0U%3D"
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 8]
Internet-Draft OAuth Request Body Hash April 2009
Appendix B. Obtaining the HTTP Entity Body
Not all programming platforms provide an easy mechanism to obtain the
raw octets of the HTTP entity body. Reading the entity body as raw
octets may have side effects, such as inhibiting automatic character
set conversion. Some platforms do not allow direct access to the
entity body at all if the content-type is application/
x-www-form-urlencoded. Transfer-encodings such as gzip also
complicate implementation. On the other hand, reading the entity
body as text may perform lossy conversions that prevent recovery of
the original octet stream in some situtations. Character set
conversions are not always one-to-one mappings, so solutions that
rely on converting text back to the original octet stream are likely
to fail in environments with multibyte characters.
All of these factors, and others, can make it difficult to drop in a
"verify-the-signature" filtering layer prior to other request
processing. The verification layer must consider the assumptions of
downstream processing code on the state of the request body.
Implementers of this specification should be aware of these
difficulties and consider the best way to address them in their
programming frameworks.
Appendix C. Unkeyed vs Keyed Hash Algorithms
This specification deliberately uses an unkeyed hash algorithm
(SHA-1) to provide an integrity check on the body instead of a keyed
hash algorithm such as HMAC-SHA1. This decision was made because
signing arbitrary octet streams is poor cryptographic hygiene. It
can lead to unexpected problems with cryptographic protocols.
For example, consider a proxy that uses OAuth to add authentication
information to requests sent by an untrusted third-party. If the
proxy signs arbitrary octet streams, the third-party can use the
proxy as an oracle to forge authentication messages.
Including the result of an unkeyed hash in the normal signature base
string allows the proxy to add an integrity check on the original
message without creating a signing oracle.
Appendix D. Preventing Removal of Request Bodies
This specification requires that Consumers not send the
oauth_body_hash parameter on requests with form-encoded bodies, and
requires that Service Providers reject requests that have form-
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 9]
Internet-Draft OAuth Request Body Hash April 2009
encoded bodies and an oauth_body_hash parameter. These restrictions
are necessary in order to prevent a MITM from removing non-form-
encoded request bodies. The attack would work as follows:
1. Consumer signs a request with a non-form-encoded request body and
includes a matching content-type header such as "application/
json" or "text/plain". The oauth_body_hash parameter is included
as well.
2. MITM intercepts request and modifies the content-type of the
request to be "application/x-www-form-urlencoded". The MITM also
removes the request body. The request is then forwarded to the
Service Provider.
3. The Service Provider receives the request and the signature
validates according to the OAuth Core signature specification.
4. The Service Provider then needs to decide whether to check the
oauth_body_hash value as well. Since the request content-type is
form-encoded, the Service Provider does not check the
oauth_body_hash.
5. The removal of the body goes undetected.
The impact of this attack is probably minimal. The attacker can
remove the request body, but cannot replace it with their own. Stil,
the goal of this specification is guaranteeing body integrity when
both Consumers and Service Providers use the oauth_body_hash
parameter. Out of an excess of caution, this specification requires
that Service Providers reject request that have both a form-encoded
request body and an oauth_body_hash parameter.
An alternate solution, requiring that Service Providers check the
oauth_body_hash parameter even on form-encoded request bodies, was
rejected due to implementation challenges. Some web development
frameworks block access to the raw entity body for form-encoded
requests.
Appendix E. Acknowledgements
Several members of the community contributed valuable feedback and
suggestions, including Allen Tom, Ben Laurie, Dirk Balfanz, George
Fletcher, John Panzer, Louis Ryan, and Marc Worrell.
7. References
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 10]
Internet-Draft OAuth Request Body Hash April 2009
7.1. Normative References
[OAuth Core 1.0]
OAuth, OCW., "OAuth Core 1.0".
[RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part One: Format of Internet Message
Bodies", RFC 2045, November 1996.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[RFC3174] Eastlake, D. and P. Jones, "US Secure Hash Algorithm 1
(SHA1)", RFC 3174, September 2001.
[W3C.REC-html40-19980424]
Hors, A., Raggett, D., and I. Jacobs, "HTML 4.0
Specification", World Wide Web Consortium
Recommendation REC-html40-19980424, April 1998,
<http://www.w3.org/TR/1998/REC-html40-19980424>.
7.2. Informative References
[NIST 800-107]
Dang, Q., "Special Publication 800-107, Recommendation for
Applications Using Approved Hash Algorithms".
Authors' Addresses
Brian Eaton
Google
Email: beaton@google.com
Eran Hammer-Lahav (editor)
Yahoo!
Email: eran@hueniverse.com
URI: http://hueniverse.com
Eaton & Hammer-Lahav Expires October 13, 2009 [Page 11]