Showing posts with label SSO. Show all posts
Showing posts with label SSO. Show all posts

Saturday, June 02, 2007

Building Secure Single Sign On Systems and Google

After seeing several posts which spelled doom and gloom if there was ever found an XSS hole in any of Google's because they used a Single Sign On (SSO) System I started trying to think of a method in which secure sign on could be securely implemented, where all the SSO server side code is trusted, e.g. when you own all the websites, and here's what I came up with.

Idea 1: Remote Javascript



The first thing that came into my head was using Remote Javascript files, to give any SSO site (site specific of course), which the server side back-end could then use to query a database, to check that the specific token was valid for their site, and if it was, they would be issued another site specific login token, which would be placed in a user's cookie, and session management would resume as usual.

The problem with this is, of course, making sure that no other sites can retrieve this login token by including the same remote javascript in their page.

Of course, there are several things you could do to prevent this:

You could do referer checks. While we have seen methods to spoof or strip referers, there have been no methods to my knowledge to date which can do this when you're requesting script elements. You could technically spoof the header normally, and try to poison the cache, but as long as the appropriate cache headers are sent, then this should not be possible.

But this leaves any users who have referer stripping firewalls in danger, and this is unacceptable.

You could use CSRF style protections. But this faces the problem of what you can actually tie the token to. You could tie the token to the IP, but as long as Anti-DNS Pinning works, this can be attacked and broken, so this is not a valid solution. And Furthermore doing such checks would be rather expensive in terms of operations needing to be performed, since this is being done between separate servers/sites.

Which essentially means that while we can make this system secure for most people, there are some we would not secure, and it is therefore not viable.

Idea 2: Remote iframes


I kept thinking about other ways you could send data to a specific site only and (from my attempts to break SessionSafe) I remembered that we could use iframes.

If an iframe sets the window.top.location.href property, the page which loaded the iframe cannot read that value, and even if they could it would be considered a browser bug and fixed. So to transfer data to our domain and our domain only we would do the following:

Write an iframe to the page which looked like this:
<iframe width="300" height="150" src="http://ssodomain.com/login.php?site=Service"></iframe>

And on http://ssodomain.com/login.php the following would be done:

If the user is not logged in display a login form.

If the user is logged in then write the following javasript tot he page:

window.top.location = 'http://companyownedwebsite.com/verify.php?auth=123456';

Where companyownedwebsite.com was determined by a switch statement on the site variable, so that only a valid site could be redirected to, and so the SSO service knew which particular value to parse in auth variable.

The other mechanisms are the same as in Idea 1. Furthermore this protects you from Programmatic password theft, since the password is entered on a domain which has nothing other than a login form.

Google's Approach


After thinking of Idea 2, I realised that this is what google does; on most of their services anyway. The one service (at which I initially looked to find out how Google implemented SSO, *doh*) which doesn't use the exact same method as above is Gmail. What it turns out Gmail does (which I somehow missed) is, instead of using an iframes, they redirect gmail.com to the equivalent of http://ssodomain.com/login.php?site=Gmail where the whole login page is displayed, and the form is submitted to that same domain.

So what does this mean?



I came to the same idea independently of Google (which to me says that there must be some merit to it, sine I didn't just see the idea and say; hey, this looks good), and it should in theory and practice be perfectly sound as long as a website cannot tell determine the URL to which the iframe/a page loaded in an iframe is being redirected to, and there are no XSS holes in the SSO domain.

So Google's SSO should be secure in the face of an XSS hole?



Well, no; Google messed up; they made their SSO domain www.google.com; the same domain as their main site, which means it used used for more central purposes (central in terms of design, rather than importance). This is bad, because there should be nothing on the SSO domain other than SSO forms, because otherwise one may find XSS holes in the SSO domain, and that breaks the whole system (bar things like IP locks tying the sessions together, but with Anti-DNS Pinning, this can again be broken)

So what are you trying to say



What I'm trying to say is that all XSS holes which are not in www.google.com (and yes, the www is important) will not break SSO, but any XSS hole which is in that domain, has the potential to.

Oh, and Google isn't completely hopeless when it comes to security - they just have many more developers working for them, and many more web facing projects than most organisations.

Monday, January 22, 2007

ShareMy.Name Design Issues

I've just posted a little article about some things that I think are currently wrong with OpenID implementations, so I thought it would be only fair to give the same treatment to ShareMy.Name - which admitedly isn't a SSO (Single Sign On) service, but it does provide a facility for easily giving out your data to everyone.

First of all though, I'll give you some history of what I've personally seen. ShareMy.Name seems to have gone through several different phases from where they simply acted as a username/password and personal details depository so that other sites didn't and so you would have to provide the same username and password to all sites, and a malicious (or hacked) site could get all your details, to where you needed to enter a regenerating accesskey (sort of like those two-factor ID things) to the current state where you get an accesskey assigned to you when you sign up, and send that key (supposedly) to ShareMy.Namen where if the accesskey matches an account, it asks you if you want to send the data the site has asked for back.

You can see a demo here: http://sharemy.name/test_sendback/

They also give you a Javascript Bookmarklet which looks something like this:
javascript:document.cookie='accesskey=aNwluiUMqk;path=/';
function r(){
document.forms['sharemyname'].accesskey.value='aNwluiUMqk';
document.forms['sharemyname'].action='http://sharemy.name/sendback/';
document.forms['sharemyname'].submit();
}
if(document.forms['sharemyname']) r(); else alert('We tried everything, your going to have to enter aNwluiUMqk manually; or, they do not support ShareMy.Name.');


Which tries to send the request to Share.MyName so that you can verify whether or not you want to send certain details to the site.

For the moment lets ignore the fact that you could just ask the user to input their accesskey in a form, and they would readily do it, or the fact that every site gets sent the accesskey, and assume that the bookmarklet is the only way to get the data, and the accesskey is not sent back.

They give us the accesskey (when they set the cookie) no matter if the user agrees to give it to us on the sharemy.name page.

But ignoring the fact that we are given the accesskey initially (this is an easy fix with no real ramifications - what is harder to fix is people overloading and subverting the page in such a way that the bookmarklet fails in its job), and the fact that users are encouraged to enter their accesskeys into unknown forms ('We tried everything, your going to have to enter aNwluiUMqk manually; or, they do not support ShareMy.Name.'), there is still the problem that the site is sent the accesskey by default.

This is a problem, because when the user say gives the their First Name, Interests, and Accesskey, they are essentially giving the site all of their information, because there is no additional identification required to get information about the person other than the accesskey.

And even more than that, since the key is permanent (from what I've seen) they have access to your data indefinately.

Now I realise that this could all be fixed simply by requiring the user to be logged into their account when agreeing to share details, but I think without an expose on the ramifications of their current design, nothing will change. And its fun to write about the havoc one can wreak.

Sunday, January 21, 2007

Insecure OpenID 'Features'

Note: I wrote this a while ago, and I haven't gone over it completely, but I thought it would be worth posting about.

I read about OpenID a while ago, when my friend asked me what I thought of it from a security perspective, and from what I could tell from the documentation, except for DNS issues it wasn't a bad decentralized authentication protocol. And I didn't do any further research into it until I came a blog entry describing how it worked in practice http://www.readwriteweb.com/archives/openid_vs_bigco.php).

In that article/flash 'demo' I saw that as with any protocol, developers can come up with great 'features' which damage the security of the protocol. And this isn't one OpenID provider deciding to add an insecure feature, either, it is one that is common throughout the 3 OpenID providers mentioned in the article, which I assume are the most popular ones being used (why else would a blogger mention them?).

Now, what is this feature I feel should not exist? It is the feature to set a site to be able to accept your credentials without you having to enter your OpenID password, and since your OpenID provider does not provide these details to the host, they do

Of course, you still need to be logged into your OpenID provider, but since you're meant to be using this login for several sites, its not too much of a stretch to believe that you're going to be logged in all the time you're online - which is quite a large time frame. And if we consider that most sites will these days tell other users when a person is online, or allow you to reveal that fact yourself via posting comments, photos, etc, its not too difficult.

But enough about the feature itself; what does it mean to us? This means that an attacker can log you into any site you decided to trust via CSRF attacks because the site cannot tell if you've entered a password. Now this might not seem important, but it is very important for both large and targeted attacks because the user no longer needs to be logged into the service you want to attack, but merely logged into the central service.

Even worse, this fact is completely misrepresented to users. The questions that are posed essentially revolve around whether you trust the site that wants to verify your identity, and whether or not your OpenID provider should always verify your identity to this source, so even if a user is generally cautious about these kind of things, if something like an email provider started using this a user would be more likely to trust the site, and cause security issues. Essentially the more critical the information you are accessing the more likely to trust the site you are trying to access, and so the more critical sites are the ones which will have issues with this; lets just hope they don't use OpenID though, because leaving DNS security, essentially up to your users, is as about the worst idea anyone could come up with, but that's another rant altogether.

For reference, the 3 OpenID providers I tested were:

http://www.myopenid.com/ where users are asked if they want to allow the site they want to log into to be able to verify their identity, and the insecure answer is "Allow Forever"

http://www.claimid.com/ where users are asked if they want to log into a site, and the insecure answer is "Login and Trust"

http://www.videntity.org/ where users are asked if they trust the remote site with their identity, and the insecure answer is "Yes, and don't ask me Again"

Another insecure 'feature' is the lack of need to enter a password to register for a site. Out of those 3 OpenID vendors, only http://www.claimid.com/ asked users for a password when registering for a site, the other two had only CSRF protections. This is admittedly not particularly serious because you still need an XSS (or similar) flaw in the OpenID provider's site before you can take advantage of the design idea, but it is rather worrying that people designing secure systems don't seem to want to implement defence in depth.