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, . 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]