This report was fully disclosed on 19 August 2020

Summary

Due to a lack of access control in the Slack API, it was possible for a user with access to a slack instance and a limited number of channels to export an entire list of users, even if that user had never shared channels with the others. In this case it allowed any contractor at Cobalt to export a complete list of clients including names, company email addresses, and when provided job titles and phone numbers.

Proof of Concept

GlitchWitch was able to successfully obtain a complete list of all users ever invited to the Cobaltcore slack instance, including names, company email addresses, and when provided job titles and phone numbers.

This poses a significant risk to the confidentiality of the platform as it seems anyone with access to the slack can also get a complete list of all clients who have ever engaged with Cobalt.

As you can see from the above screenshot, a small selection of guests that are not in any channels I am in are available to me.

As you can see from the above screenshot, a small selection of guests that are not in any channels the user is in are available to them.


The second and more efficient way of accessing this information is by using the slack token given to the slack desktop client in combination with the “user.list” api end-point.

First we can run the following in our terminal.

export http_proxy='http://127.0.0.1:8080';export https_proxy='http://127.0.0.1:8080'
slack

Then we can use burp to look for a request to the following URL https://wss-primary.slack.com/?token=xoxc-REDACTED&bots_as_apps=1&[TRUNCATED]` As we can see, a token is sent as a parameter in this request.

Using this token we can access a json list at https://slack.com/api/users.list?token=xoxc-REDACTED&pretty=1 with all users on the slack, and from there use offline sorting to extract all the guest details.

The above list, once downloaded as a json file, totals 162424 lines.

Using the following regex in an IDE it was determined that 2011 unique guests with non cobalt/cobaltcore emails are in the list.

""guest_invited_by": "(.*)\n                "email": "(.*)"
""guest_invited_by": "(.*)\n                "email": "(.*)cobalt"

Slack User List.

Remediation Status

At the time of publishing this it appears the issue was addressed by Slack. Attempting to perform the steps presented in the second half of the PoC now results in the following error.

ok	false
error	"invalid_auth"

Response From [email protected]

On Monday, March 3, 2020 00:08, Ray [email protected] wrote:

Hello,

Thank you. I’ll look into this and see what privacy options we have with Slack to prevent this type of activity.

As always, I appreciate the partnership!

Ray

—-oO0Oo—-

Ray Espinoza

Head of Security

Cobalt Labs

www.cobalt.io

Response From [email protected]

On Monday, March 10, 2020 21:43, Ray [email protected] wrote:

Thank you for checking in. I hope you’re staying safe with all this crazy coronavirus stuff going around. We’ve reached out to Slack to see if there’s any way to limit access either by disabling API access or limiting the APIs that can be called. Initial conversations indicate that they don’t have a way to limit access. Our customers have single channel access. Cobalt employees and pentesters get full licenses. We background check all pentesters and employees so it’s at least we know who’s on our instance. We’re still seeing if there’s something Slack can do to help us. I’ll keep you posted.

Thanks Ray

Response From [email protected]

On Monday, August 18, 2020 18:36, Ray [email protected] wrote:

It’s great to hear from you. Unfortunately, Slack doesn’t have a way to address this issue and with our ability to manage who gets access to our slack instance (customers, pentesters, employees) we’re managing this risk the best that we can as every part involved has signed non disclosure agreements.

Thank you again for sharing what you find. It’s hugely valuable to Cobalt and my team!

Ray

—-oO0Oo—-

Ray Espinoza

Head of Security

Cobalt Labs

www.cobalt.io

Timeline

  • 3 March 2020: Affected Party Notified
  • 3 March 2020: Affected Party Responded (+0 days)
  • 19 August 2020: Affected Party Released Patch (+169 days)
  • 10 March 2020: Affected Party Responded (+7 days)
  • 18 August 2020: Affected Party Responded (+168 days)
  • 19 August 2020: Report Published (+169 days)