Under the headline, "Shocking headline about OpenID security issue here", Benjamin Nowack describes what I think is the first major security vulnerability discovered for OpenID, and probably for a whole range of other technologies. In fact, it appears that many websites are vulnerable to the same kind of attack, whether they have implemented digital identity technology or not.
First, his summary of the problem:
When I tell the site [relying party] my homepage URL, it’s super easy to find my login name or user id for the most common services (e.g. LJ). Now the site knows
- my user id or account name
- the service/software I’m using (LJ, Drupal, WordPress, …)
- that I’m currently logged in (otherwise, OpenID doesn’t work)
… HTML forms which, when submitted, create blog posts, change profiles, add friends, etc. (In Drupal, for example, a single POST can be used to change your password, there is no need to verify the current one).
All the evil site has to do is to mimic a service form and submit it via a hidden iframe. The form will be submitted as if the user did it manually.
I think it’s actually worse than he describes, because not only does the identity host (e.g. LiveJournal in his example) become attackable, but also any other site that relies on the identity host to make identity assertions.
This is how I would do it if I was an attacker:
- Attacker sets up an innocent-looking evil Relying Party that accepts OpenID. For example, a wiki on some subject may be very suitable.
- Victim uses their OpenID to authenticate there.
- While victim uses evil site normally, attacker performs a web search on the used identity URL to determine other places on the web where the victim has used the exact same URL.
- Evil site creates a web page with N i-frames in it, all of which auto-submit hand-crafted (for the specific site) HTML POSTs. If you imagine that some of those might be banks, each could do a money order to Nigeria. (If the i-frames are small, it could be one iframe per page somewhere in the corner where nobody is looking.)
- Evil site also submits comment spam on any known blogging site, using, and thereby totally ruining victim’s reputation.
If you now think, "I won’t ever touch this OpenID thing" it turns out that this vulnerability fundamentally has nothing to do with OpenID. Not only seem other web single-sign-on technologies like LID, Sxip, i-names etc. affected as well, a similar form of the attack works against many websites. For example:
- Victim site (think: MySpace) allows users to create hyperlinks on the site to outside servers.
- Attacker creates link to evil site.
- Victim follows link created by attacker to evil site, which looks normal. Proceed as above. The only difference is that downstream sites may be not be affected, but the basic exlpoit that Benjamin reported can be the same.
While unlike in the OpenID case, there is no guarantee that the victim is logged into the victim site at the time of the attack, there is a high likelihood the victim is for many sites (eg. social networking sites).
So how are we going to solve this?
First, like Benjamin, I thought that this must be something that can be fixed by tightening the OpenID spec. However, when I realized that MySpace, for example, can be attacked the exact same way, without ever touching OpenID or any other technology like that, I realized that per se, it has nothing to do with the OpenID protocol and thus cannot really be fixed from within the protocol.
The best approach that we’ve come up with at NetMesh so far is the following:
- All identity providers, and relying parties need to be upgraded with the following code.
- They need to identify those request URLs (and HTTP methods) in their implementation that can potentially change data, or make identity assertions to downstream relying parties.
- After the code that validates the session, but prior to performing any actual work, for the above-identified request URLs, they need to look at the HTTP Referer header.
- If the referer header comes from a non-approved party (e.g evil.com), or if the referer header is empty, they must not execute the method, but insert a screen that requires the user to confirm the action.
- This confirmation screen preferably generates a unique confirmation token that is passed into the same request and checked, so that a repeat request is successful but that the token cannot be guessed from the outside.
The downside of this is that those users whose browsers or web proxies strip out referer headings have to click on one more button than others for single-sign-on etc.. But that’s the best tradeoff we have come up with so far …