Skip to content

Static Token used for authentication in the Slack iOS application

March 11, 2015

When I register for a Slack team from the Safari browser in my iPhone, the final request for registering a team looks like:

1

The response to this request is a redirect to the URL https://slack.com/checkcookie?redir=https%3A%2F%2Fn00bgiri.slack.com%2F%3Ffresh which is then redirected to https://n00bgiri.slack.com/?fresh which is then redirected to https://n00bgiri.slack.com/app. The series of these requests/responses can be seen below:

2

The final response for the request https://n00bgiri.slack.com/app looks like:

3

This screenshot is taken from the Safari browser in the iPhone.

An important thing to notice here is the option “Open Slack”. That is actually a hyperlink that looks like: <a href="slack://login/<redacted>/xoxo-<redacted>-<redacted>" class="btn btn-primary btn-large">Open Slack</a>

The value xoxo-<redacted>-<redacted> in the above URL is the keys to the kingdom. It can be essentially considered as a replacement for the username/password combination. It is a static value that does not change or get invalidated even if the account is logged out. This brings us to the first issue i.e. If an attacker gets hold of this value of a victim (by different attack vectors which is out of scope for the purposes of this discussion), he can essentially gain complete access of a victim’s account perpetually. It does not matter if the victim is logged in or not since it is a static token and does not get invalidated on logout. Please note that the above value should not be confused with another token value that looks similar but is of the form xoxs-<redacted>-<redacted>-<redacted>-<redacted>. I will describe what this other value is in a moment. The xoxo value is only created/sent in the response once when the team is first registered so that’s important to know here.

Now, the normal authentication flow in the Slack iOS app is something like below:

  • The first authentication request is sent to the URL https://slack.com/api/auth.signin with the POST parameters email, password and team.
  • In response to the above request, the server assigns and sends a token (xoxs-<redacted>-<redacted>-<redacted>-<redacted>) in the JSON response.
  • Then, a request is sent to the URL https://slack.com/api/users.login with the POST parameters agent,set_active and token. The token sent here is the xoxs token received above. This completes the authentication flow.
  • The xoxs token is then used in all subsequent requests.

Now, if you logout of the iOS application, this xoxs token gets invalidated (as it should be) but the static xoxo token discussed earlier does not. And, that’s the problem.

This brings me to the second attack aka Login CSRF:

Normally, in a Login CSRF attack, an attacker tricks a victim to submit an authentication request with the username and password as parameters in the request. If there are no CSRF tokens present in this request, it becomes possible to trick victims to authenticate to an attacker controlled account.

So, we now know that the xoxo token is a static token and can be treated as username/password. Therefore, the authentication request would look something like this:

Screen Shot 2015-03-12 at 2.08.49 AM

Notice there is nothing that can be considered as a CSRF token in the above request.

I have created a video PoC for this attack as well.

Exploiting the Login CSRF is extremely easy in this case.
What I essentially did was that as an attacker, I noted down the hyperlink that the server sent when I first registered my team: slack://login/<redacted>/xoxo-<redacted>-<redacted>

I, then sent, the victim an email with this link above as a hyperlink. When the victim clicks on that, the Slack iOS app opens up and sends the above authentication request automatically. I didn’t even have to craft a HTML that sends a POST request to the /api/users.login endpoint. It was as simple as tricking the victim to click on a GET URL. The Slack app does all the leg work for the attackers.

So, that’s if folks. To summarize, I described 2 issues above:

  1. Static tokens that don’t get invalidated
  2. Login CSRF

 

Remediation:

I am not an expert in iOS pentesting but I googled the correct way to handle iOS URL schemes and I saw these websites:

I think they are worth looking into. The premise is essentially that, you should be asking the victim user before opening up the slack:// URL automatically in the Slack application to mitigate the Login CSRF issue.

For the static token issue, I think it’s a bad idea to associate static tokens with user accounts all together. So, that should be looked into as well and tried to get rid of. If not, I don’t see any reason of sending that value in the response in clear text after registering.

 

Slack’s Response:

Thanks for your extensive report. Both of these issues are already known and being fixed.

1) The static tokens are something we are moving away from for all apps, including iOS. We hope to have this completed soon.
2) There is not much security implication of logging a user in this way. Because Slack groups are closed to the public, it would be difficult to convince the user they are in the correct group if you manage to log them in. We have an open bug to add CSRF to the login page,but this is low priority.

 

Cheers!

 

 

Advertisements

From → Security

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: