Uploaded image for project: 'OASIS Open Data Protocol (OData) TC'
  1. OASIS Open Data Protocol (OData) TC
  2. ODATA-262

Specify how OData services can be protected against cross-site request forgery (CSRF or XSRF)

    Details

    • Type: New Feature
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: V4.0_WD01
    • Fix Version/s: CN01
    • Component/s: Securing OData
    • Labels:
      None
    • Environment:

      [Proposed]

    • Proposal:
      Hide

      Create a TC Note in order "Securing Open Data" to address security issues and add this to that note.

      The client adds the header

      X-CSRF-Token: Fetch

      to a GET request. The header value "Fetch" is case-insensitive.

      The server adds the same header to the response. The header value is generated by the server. It is opaque, i.e. the client has to copy it verbatim without alteration. As a consequence it is case-sensitive.

      The client adds this header with the copied, unaltered value to subsequent POST, PUT, PATCH, or DELETE requests.

      The server accepts the modifying request if and only if the provided CSRF token is still valid.

      If the token is invalid, the server responds with 403 Forbidden and includes the response header

      X-CSRF-Token: Required

      If a server requires a CSRF token for modifying requests, it MUST issue a CSRF token in responses to GET requests to the service document as this is the only well-known and small resource of a service. To guarantee freshness of the CSRF token the server MUST include cache control headers that advise intermediaries and clients to refresh their caches. The refresh period or point in time MUST be chosen to guarantee that the caches are refreshed before the CSRF token expires.

      The service SHOULD issue a CSRF token in responses to GET requests to other resources whose cache residence period is sufficiently shorter than the CSRF token validity period.

      The client MUST NOT assume to get a CSRF token in responses to GET requests to the metadata document, as this is typically not small and SHOULD be cached anyway, so there's no guarantee to get a fresh CSRF token.

      For $Batch the X-CSRF-Token MUST be provided as a header. It's not allowed to specifiy any X-CSRF-Token in the "inner" requests.

      Accepted: https://www.oasis-open.org/committees/download.php/49447/odata-meeting-40_on-20130606-minutes.html#odata-262

      Show
      Create a TC Note in order "Securing Open Data" to address security issues and add this to that note. The client adds the header X-CSRF-Token: Fetch to a GET request. The header value "Fetch" is case-insensitive. The server adds the same header to the response. The header value is generated by the server. It is opaque, i.e. the client has to copy it verbatim without alteration. As a consequence it is case-sensitive. The client adds this header with the copied, unaltered value to subsequent POST, PUT, PATCH, or DELETE requests. The server accepts the modifying request if and only if the provided CSRF token is still valid. If the token is invalid, the server responds with 403 Forbidden and includes the response header X-CSRF-Token: Required If a server requires a CSRF token for modifying requests, it MUST issue a CSRF token in responses to GET requests to the service document as this is the only well-known and small resource of a service. To guarantee freshness of the CSRF token the server MUST include cache control headers that advise intermediaries and clients to refresh their caches. The refresh period or point in time MUST be chosen to guarantee that the caches are refreshed before the CSRF token expires. The service SHOULD issue a CSRF token in responses to GET requests to other resources whose cache residence period is sufficiently shorter than the CSRF token validity period. The client MUST NOT assume to get a CSRF token in responses to GET requests to the metadata document, as this is typically not small and SHOULD be cached anyway, so there's no guarantee to get a fresh CSRF token. For $Batch the X-CSRF-Token MUST be provided as a header. It's not allowed to specifiy any X-CSRF-Token in the "inner" requests. Accepted: https://www.oasis-open.org/committees/download.php/49447/odata-meeting-40_on-20130606-minutes.html#odata-262

      Description

      A good CSRF protection pattern is that the server issues a CSRF token that is communicated to the in a special header in responses to GET requests.
      This CSRF token must be included in a special header in subsequent modifying requests.

      To guarantee interoperability between different OData implementations the choreography, header names, and header formats must be standardized.

        Attachments

          Activity

          Hide
          mikep Michael Pizzo (Inactive) added a comment -

          added that the header should be on batch, not on statement within batch.

          Show
          mikep Michael Pizzo (Inactive) added a comment - added that the header should be on batch, not on statement within batch.
          Hide
          tejones Ted Jones (Inactive) added a comment -

          The proposal outlined is in line with the Synchronizer Token pattern recommended by our security experts at Red Hat. See: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern

          Show
          tejones Ted Jones (Inactive) added a comment - The proposal outlined is in line with the Synchronizer Token pattern recommended by our security experts at Red Hat. See: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern
          Hide
          mikep Michael Pizzo (Inactive) added a comment -

          An alternative suggested by our web security folks is to first use basic auth to request a token (ex using OAuth2) that can then be used as a bearer token in requests to protected resources. This significantly reduces the exposure of the users credentials, and because bearer tokens are not subject to request forgery you can get out of the anti-CSRF business.

          Show
          mikep Michael Pizzo (Inactive) added a comment - An alternative suggested by our web security folks is to first use basic auth to request a token (ex using OAuth2) that can then be used as a bearer token in requests to protected resources. This significantly reduces the exposure of the users credentials, and because bearer tokens are not subject to request forgery you can get out of the anti-CSRF business.
          Hide
          ralfhandl Ralf Handl added a comment -

          CSRF protection needs some token that is not automatically sent by the user agent (that's why cookies are not helpful here).

          For authentication on the other hand session tokens that are automatically sent by the user agent (i.e. cookies) are extremely helpful as they allow exploring protected services/resources with standard tools (browsers). If the session token would only be sent in a header, easy exploration of OData services would become impossible.

          That's why separating authentication/session tokens in cookies from anti-CSRF tokens in headers seems a good idea.

          Using the same token in a cookie and a header may or may not introduce a security hole.

          Show
          ralfhandl Ralf Handl added a comment - CSRF protection needs some token that is not automatically sent by the user agent (that's why cookies are not helpful here). For authentication on the other hand session tokens that are automatically sent by the user agent (i.e. cookies) are extremely helpful as they allow exploring protected services/resources with standard tools (browsers). If the session token would only be sent in a header, easy exploration of OData services would become impossible. That's why separating authentication/session tokens in cookies from anti-CSRF tokens in headers seems a good idea. Using the same token in a cookie and a header may or may not introduce a security hole.
          Hide
          mikep Michael Pizzo (Inactive) added a comment -

          I'm okay adding this as a recommendation/best practice, but we shouldn't mandate this particular solution.

          Show
          mikep Michael Pizzo (Inactive) added a comment - I'm okay adding this as a recommendation/best practice, but we shouldn't mandate this particular solution.
          Hide
          mikep Michael Pizzo (Inactive) added a comment -

          From our discussion in May 30 2013 spec, folks will follow up with security experts within their companies and be prepared to discuss at Face to Face in June. Consider publishing this as a committee note that could be maintained more dynamically than specification..

          Show
          mikep Michael Pizzo (Inactive) added a comment - From our discussion in May 30 2013 spec, folks will follow up with security experts within their companies and be prepared to discuss at Face to Face in June. Consider publishing this as a committee note that could be maintained more dynamically than specification..
          Show
          ralfhandl Ralf Handl added a comment - The mechanism is e.g. described here: http://help.sap.com/saphelp_gateway20sp05/helpdata/en/e6/cae27d5e8d4996add4067280c8714e/frameset.htm
          Hide
          ralfhandl Ralf Handl added a comment - - edited
          Show
          ralfhandl Ralf Handl added a comment - - edited Cloned to https://github.com/oasis-tcs/odata-specs/issues/267

            People

            • Assignee:
              handl Ralf Handl
              Reporter:
              handl Ralf Handl
            • Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: