Custom Web SSO

Suppose you have two web applications (AppA and AppB) and you want to have an SSO solution between these two. Namely, the user logs in to AppA and when he clicks on a link, he can start using AppB without providing any credentials. SSO as I said. Suppose AppA and AppB are deployed to different servers and are available on different domains.
I guess all of you know or at least heard about different authentication protocols or SSO implementations offering such a functionality. Easy as a pie.

I’ve seen a different implementation though. There were mulitple steps (request/response messages) in the background, so let me highlight only the interesting one:

GET /AppB/init.do?userid=[userid]&authToken=[token]&authServer=[host:port]

In the response (if the “authentication” was successful), there was a login form pre-filled with a username and a password. Then this form was instantly submitted by a tiny Javascript code. So basically there was a hidden login. Let’s see what was the magic here.

The first thing you may spot here is that sending back a form pre-filled with credentials puts some questions on the table. For one, it’s definitely not the best practice. For second, how do they know the password?? The passwords – I mean ALL of them – are stored as hash values, right? Not in this case. They stored the password in clear-text (or used a reversible encryption) – not good. Also, if you saw the passwords of 2 users, you could easily figure out the passwords of the others. But let’s put this whole “form sending thing” aside.

Take another look at the GET query instead. There are three parameters:

  • userid – OK, this is a userID
  • authToken – This is like a One Time Password. It is random, generated by AppA and you can use it only once
  • authServer – This is the interesting part. The value is a hostname and a port. Guess what happens if you change that hostname to your IP… from that point, you are the authentication server \o/
    Hey, don’t forget… great power comes with great responsibility… 😉

As you set up yourself as the authentication server, you receive a HTTP GET request from AppB – most probably from its application server. The request includes the userid and the token. That’s cool. The question is – how shall I reply to the request? What’s the correct response according to the “authentication protocol”? The problem is that you don’t know the protocol, you are a fake authentication server. Let me guide you through the protocol reverse exercise I’ve done here. Brace yourself, hardcore stuff is coming… Ready?

So you receive a GET request with the userid and the token, right? It’s like a question:
“Hey, dude here is a token and a userid. Could you please check if I can let him in? Appreciate that.”

What could be the answer? Most probably “Yes” or “No”. Considering that these are machines, I would go with “Y” or “N”.

So here is my advanced 1337 authentication server:

echo -n "Y" | nc -v -l 80

Guess what.. I could log in to AppB with any user without providing a valid token.

So the takeaways:

  • @Developers – Please never invent a new SSO architecture, use something from the shelf. But if you invent a new one, never ever let the users the replace one component of your SSO architecture.
  • @Pentesters – Always try the most simple option first (“Y”), if it doesn’t work, you can start doing complicated stuff, but always KISS first!

Happy Hacking!

Advertisements