4

We're working on an SSO implementation that would be used accross domains. I realize there are proven working models out there like CAS for this but I'm toying with a different approach and I want to get feedback from you all here to see if this is secure or not. The basic premise is that we don't want to use redirects if we don't have to and we want the product sites to be able to style their own login pages. This targets IE8+ and modern FF and webkit only. So, without further ado the implementation:

  1. Client browses to product site A.com. They don't have a session cookie for a.com so the site initiates the parent auth script.
  2. The parent script builds an iframe that loads a page from the auth server on auth.com. Auth.com validates the request based on the referer header and if the referer isnt trusted then responds with x-frame-options:DENY and/or a frame busting redirect.
  3. The script on this page (the framed script) does an ajax request to auth.com's server asking for an SSO 1 time token (1TT).
  4. The client doesn't have an auth.com cookie so this is rejected, and the iframe script tells the parent script to build an auth form using window.postMessage (and the parent script validates the origin) to communicate since it is cross domain.
  5. The user enters their credentials, and hits submit.
  6. The credentials get passed from the parent script to the framed script via postMessage again, and the framed script uses them to login to auth.com, receiving both an auth.com cookie and a 1TT.
  7. The 1TT is passed back to the parent script.
  8. The parent script passes the 1TT to A.com's server.
  9. A.com uses the 1TT to get the user info from auth.com's server via a private internal API, and auth.com invalidates the 1TT so it can't be used again.
  10. A.com returns a session cookie for A.com to the client, and now the client goes about its business on A.com.

  11. Then the client browses to B.com, but again has no session cookie for B.com. The parent script is executed again, which creates an iframe again pointing to auth.com. The iframe script requests a 1TT from auth.com, and since it has a session cookie for auth.com this time it gets one.

  12. The 1TT is passed from the iframe script to the parent script to B.com's server which uses it to get the user from auth.com and issue a session cookie for B.com.

My main concern is at step 2. Is this a solid way to prevent malicious framing? What other security vulnerabilities is this susceptible to?

Edit: All sites and scripts will be loaded HTTPS.

5
  • Actually, this is surprisingly close to stack exchanges authentication. I just need to switch to localStorage for auth.com's session info. meta.stackexchange.com/questions/64260/…
    – rbrc
    Feb 15, 2013 at 19:45
  • 1
    For starters, the referrer header can easily be forged, you can not rely on it for security.
    – Jeff
    Feb 15, 2013 at 22:17
  • 1
    The vulnerability though is that faking the referer header logs you into a site you would otherwise have access to; not sure if it's that big a deal (esp. since I assume you issue tokens per-site)
    – Bob Watson
    Feb 16, 2013 at 0:24
  • 1
    Jeff, I thought that at first too but it turns out to not be as true as you might think. I can forge my own referer header with various browser plugins but I can't forge someone else's referer header in a CSRF or even an XSS attack so it turns out to actually be secure. If you have evidence otherwise, I'd love to see implementation or a link.
    – rbrc
    Feb 16, 2013 at 1:29
  • 1
    As with all security related stuff, please don't roll your own. As someone who has spent most of his life writing SSO-related code (that may not be saying much), please don't try to do this on your own. Rely on existing protocols.
    – Steve
    Feb 16, 2013 at 4:35

2 Answers 2

1

There's not really enough information in your list (as hard as that is to believe, with 12 steps and all) to properly answer, but as you mentioned in your comment above - this is pretty close to the StackExchange model.

With that in mind; have you considered running your own OpenID Provider? The protocol spec looks pretty close to what you're after. This is also a well-tested model, so a lot of the concerns have already been well-solved. OAuth may be suitable, but it's designed around limited access tokens - don't know enough about what you're doing to say which is more appropriate.

Coming back to your model - what you've specified looks ok, though as written there's a mix of 'model' stuff and 'implementation' stuff that makes it a bit tricky to analyse. You're relying on the referrer, but it looks like in this scenario, faking the referrer will only log a client in to a different site they would have access to anyway. You are depending on referer though - maybe just load the frame with a GET request including the referrer?

You're also relying on the ability to pass info back and forth between frames; you may want to consider using an interim page on auth.com instead (i.e. forward user to auth.com, if user already logged in there, POST back to https://B.com with 1TT). Using iframes complicates things (What if you're already in a frame? You're relying on the browser here to 'break out' successfully - could this be subverted by messing with the DOM?). You may be able to make this secure, but it's a complicating factor - and the enemy of good security tends to be overly-complicated schemes.

12
  • OpenID and OAuth both rely on redirects which is what I want to avoid. I'm going to have to think about a frame within a frame (within a frame within a frame) possiblity but I think all of that can be pretty easily defeated with x-frame-options:DENY. Loading the frame would be a GET request, yes, which includes the referer unless I'm missing something?
    – rbrc
    Feb 16, 2013 at 1:34
  • I mean add it to your query string so you're not relying on the browser to send it (in the case where a user has referers turned off, or you're requesting across domains and one is https). x-frame-options:DENY relies on the browser also doing the right thing - there's no reason an attacker can't just ignore it.
    – Bob Watson
    Feb 16, 2013 at 1:41
  • In what scenario would an attacker be able to ignore x-frame-options in order to hijack someone's session? As for turning off the referer, I'm of the opinion that you have to be an advanced user to do that so telling such a user that they need to allow referer for authentication doesn't really bother me. But ideally I'll setup a local login to site A.com without SSO in addition.
    – rbrc
    Feb 16, 2013 at 1:53
  • In any scenario where they're making an HTTP request, they can choose to ignore it, they can instruct users to turn it off, etc. (don't underestimate the social engineering aspect) - but just because it's hard to articulate a precise attack doesn't mean that it's hard to exploit. (Also, checking the referer and checking the query string are about as hard as each other - why not just make it work when it's turned off? The principle here is don't trust the client, build your site with that assumption and you'll automatically make it harder to attack.)
    – Bob Watson
    Feb 16, 2013 at 2:13
  • Well, as for the query string, a malicious framer can write any query string they like, whereas forging the referer is much harder. They can only forge a referer for a domain they control. I agree that its worth while to make it be able to login to the local site directly when the referer is missing, or as the stack exchange implementation outlines, any time anything seems off.
    – rbrc
    Feb 16, 2013 at 3:55
1

This SSO Design has a number of technical limitation that make it impossible to implement. There are security concerns with this design.

The worst vulnerability that this design implements is OWASP A9-Insufficient Transport Layer Protection. SSL must be used to protect all authentication information, therefore if you spill an authentication cookie over HTTP a session could be hijacked. So if a user on a wifi network were to authenticate using this SSO Design, they could have their account hacked with a tool like firesheep.

#2 is not possible: The originating site A.com must load the authentication iframe using an HTTPS page. However, by doing this, the referer header element will be missing and there is no way to verify where the request is originating from. Mozilla's Origin Header Proposal is trying to fix this problem, but its not supported by all browsers. OAuth uses a Signed Callback URL to insure that a browser is being authenticated to a trusted domain.

For #9, instead of sharing user data with "private internal API", try using a public standard like OAuth. In fact what you have described sounds a lot like 3-legged OAuth. OAuth is probably how you authenticated to http://security.stackexchange.com to ask this question, and it has proven to be secure.

13
  • HTTPS can send referer if going to another HTTPS site. tools.ietf.org/html/rfc2616#section-15.1.3
    – Bob Watson
    Feb 16, 2013 at 0:03
  • @Bob Watson this does not hold for cross-domain requests. That would be information leakage. Some CSRF exploits use this to obscure their origin, try it.
    – rook
    Feb 16, 2013 at 0:05
  • can is the operative. Most browsers don't, but you may not want to rely on that, since they meet the spec if they do. Not that that helps the questioner.
    – Bob Watson
    Feb 16, 2013 at 0:06
  • @Bob Watson Let me know of a browser that does this. I would be happy to submit the information leakage vulnerability to their bug tracker.
    – rook
    Feb 16, 2013 at 0:08
  • 1
    I was wrong above; most browsers do send referer with https kb.mozillazine.org/Network.http.sendSecureXSiteReferrer / bugzilla.mozilla.org/… - in fact, it was removed and added back in
    – Bob Watson
    Feb 16, 2013 at 0:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .