Heine

  • Home
  • Drupal
  • About
Home

The OpenID 2.0 Compliance Crusade - Part I

Heine —Mon, 2010/01/11 - 22:50

We released Drupal 6.14 because of a number of vulnerabilities in the OpenID core module. One of those vulnerabilities was caused by not obeying the OpenID 2.0 Authentication specification.

A number of other spec violations was discovered while working on the security issue. This might not be that be surprising, after all, our OpenID implementation was written against a draft, not the final 2.0 specification.

In addition, the issue queue on the OpenID core module hints that the OpenID module is going the way of BlogAPI (another Drupal dodo).

Rather than trying to fix each violation, I decided to correct the immediate issue and then start a belated OpenID 2.0 Compliance Crusade in public, to get our OpenID implementation fully compliant.

Wanna join in? Great! The rest of this post is meant to provide a slightly easier introdcution into the first part of OpenID than the official specs. To prevent disappointment: It's basically a partial retelling of the spec. With this introduction, you should be able to investigate spec violations, and file and review patches for OpenID.

A typical OpenID transaction has three parties involved: the user, the OpenID provider (OP) and the webapp that request authentication, called the relying party (RP).

Here, the RP is Drupal, and the OP, or OpenID Provider is Gmail, Yahoo, Live or MyOpenID.

Step 1. Initiation

The user kicks off the process by providing an identifier to Drupal. This user-supplied identifier can either be his own identifier (heine.myopenid.com) or identify the OpenID provider that should be used (yahoo.com). A user-supplied identifier that identifies the OpenID provider is called an "OP Identifier" in the spec. We can distinguish between the different identifiers after having performed the Discovery step.

Step 2. Discovery

Contacting the OpenID Provider

After normalizing the identifier (#575804, #578464), Drupal contacts the OpenID provider to inquire about its services. Drupal should follow each and all redirects (still part of the normalization) until it discovers the required information. Drupal should note the final URL as being the Claimed Identifier and use this URL during the authentication step. [huh? How does that jive with 7.3.1: "If the end user entered an OP Identifier, there is no Claimed Identifier."?]

Rules for discovery:

  1. If the identifier is an XRI, Drupal should do XRI resolution that will deliver an XRDS document.
  2. If the identifier is a URL, Drupal uses the YADIS protocol to fetch an XRDS document.
  3. Should Yadis fail, result in an invalid XRDS document, or result in an XRDS document without a SERVICE ELEMENT, Drupal should do HTML-based discovery

Interpreting the response

It's a bit hard to describe each and every discovery method, so I'll just go into detail on XRDS based discovery via XRI or Yadis (section 7.3.2), as this is the method used by Google (vulnerability was discovered using Google OpenIDs).

So, we have an XRDS document, basically an XML document with entries for services related to the Identifier. It looks something like:

<service xmlns="xri://$xrd*($v*2.0)">        
  <Type>http://specs.openid.net/auth/2.0/signon</Type>
  <URI>https://www.exampleprovider.com/endpoint/</URI>
  <LocalID>https://exampleuser.exampleprovider.com/</LocalID>
</service>

Drupal knows whether the user-supplied identifier is describing the user or the OpenID provider by following a series of steps.

First, Drupal should search throught the XRDS document, trying to find whether it contains an OP Identifier element which is a Service element, containing a Type tag with the text content "http://specs.openid.net/auth/2.0/server" and a URI tag (the text content is the OP endpoint URL Drupal must use to do authentication requests).

If Drupal cannot find this OP Identifier element, it should try to find a Claimed Identifier Element which is a Service element, containing a Type tag with the text content "http://specs.openid.net/auth/2.0/signon", a URI tag (containing the OP endpoint URL as above) and an optional LocalID tag (an identifier used by the OpenID provider to identify the user).

As you can see, the example code above doesn't contain an OP Identifier Element, but a Claimed Identifier Element. The response by Google, below contains an OP Identifier element; the Identifier describes the OpenID provider, not the user. The OpenID provider will allow the user to choose an identity when authenticating (ie which gmail account to login with).

<service priority="0">        
  <Type>http://specs.openid.net/auth/2.0/server</Type>
  <Type>http://openid.net/srv/ax/1.0</Type>
  <Type>http://specs.openid.net/extensions/ui/1.0/mode/popup</Type>
  <Type>http://specs.openid.net/extensions/ui/1.0/icon</Type>
  <Type>http://specs.openid.net/extensions/pape/1.0</Type>
  <URI>https://www.google.com/accounts/o8/ud</URI>
</service>
 

As I wrote above Drupal should search for an OP Identifier Element, and only then for a Claimed Identifer Element. Right now, Drupal just looks at the first services entry. This issue has been filed under #579448.

When the discovery is completed, Drupal has the following information:

  • The OP Endpoint URL to use during authentication requests
  • The protocol version in use

If the user did NOT enter an OP Identifier (ie, not yahoo.com, but heine.myopenid.com), additional information is present:

  • Claimed Identifier (openid.claimed_id)
  • OP-Local Identifier (openid.identity)

These Identifiers should be used when doing authentication requests (Step 4 in the image), EXCEPT in the case of an OP Identifier. Then Drupal should use the the special URL "http://specs.openid.net/auth/2.0/identifier_select" as BOTH the Claimed Identifier (openid.claimed_id) and the OP-Local Identifier (openid.identity).

The vulnerability stems from the fact that Drupal doesn't use this URL for the Claimed Identifier during authentication, causing undefined behaviour in the OP.

To be continued…

That's all for now; steps 4-7 will have to wait for Part II.

  • Drupal
  • Planet Drupal
  • OpenID

Comments

Thank you for your research

Submitted by alex_b (not verified) on Tue, 2010/01/12 - 20:23

Heine - thank you for this detailed writeup. I'll see you in the issue queue. Looking forward to subsequent posts.

Recent posts

  • Teampassword manager's password generator is biased
  • Other vectors for SA-CORE-2014-005?
  • Lazy loading: hook_hook_info is for hook owners only.
  • "Always offline" problem in EA's Origin due to antivirus
  • From bug to exploit - Bakery SSO
more

Security reviews

I provide security reviews of custom code, contributed modules, themes and entire sites via LimoenGroen.

Contact us for a quote.

Follow @ustima

Copyright © 2021 by Heine Deelstra. All rights reserved.

  • Home
  • Drupal
  • About