How we abused Slack's TURN servers to gain access to internal services
Last updated: Jan 11, 2021
Executive summary (TL;DR)
Slack's TURN server allowed relaying of TCP connections and UDP packets to internal Slack network and meta-data services on AWS. And we were awarded $3,500 for our bug-bounty report on HackerOne.
A very brief introduction to the TURN protocol
The Wikipedia page for this protocol is somewhat handy because it explains that:
Traversal Using Relays around NAT (TURN) is a protocol that assists in traversal of network address translators (NAT) or firewalls for multimedia applications. It may be used with the Transmission Control Protocol (TCP) and User Datagram Protocol (UDP). It is most useful for clients on networks masqueraded by symmetric NAT devices. TURN does not aid in running servers on well known ports in the private network through a NAT; it supports the connection of a user behind a NAT to only a single peer, as in telephony, for example.
It might be also useful to note that TURN is actually an extension to the STUN (Session Traversal Utilities for NAT) protocol rather than a network protocol that stands on its own.
TURN servers can get peers behind NAT connected by acting as a relay, as it is called in the RFCs, or a proxy from the perspective of a pentester. In the case of TCP relaying, TURN servers make use of a connect message method 0x000A in RFC 6062 while with UDP, a send indication message method 0x006 in RFC 5766 is used. For UDP, the channel method can also be used and has a similar function.
With that out of the way, one might ask, how is this related to WebRTC?
Introduction to TURN in the WebRTC infrastructure context
With WebRTC, as well as VoIP in general, one of the more painful complications has been getting the media stream (i.e. RTP packets carrying audio and video) of two or more parties to reach each other. This tends to be a problem because of NAT, which is widely known to have inflicted a great deal of pain on human nature (at least that subculture which develops real-time communications software). The problem has to do with finding the IP and port tuple of each media stream which, when either or both hosts are behind NAT, tends to be less obvious. In many cases, this has been solved with STUN and when that fails, the TURN extension which tends to be the last resort before failing to get the media stream working. Here we should mention that the ICE protocol (Interactive Connectivity Establishment) is what ties in STUN and TURN. In fact, TURN has been designed to work with ICE.
Therefore, for many WebRTC systems, one key element is to have a TURN server to relay messages between peers when direct media traffic between peers is not allowed by a firewall or NAT device.
How Slack uses TURN
When we tested Slack, we noticed that TURN was always used for establishing the media which is passed over SRTP. This has been described extensively by the webrtcHacks blog in an article called Is Slack’s WebRTC Really Slacking? (Yoshimasa Iwase) way back in 2016, and so we will not repeat the same explanation over here. But one thing that we should highlight is that the way that Slack uses its TURN server puts it in a critical position within its infrastructure, rather than it being a measure of last resort.
What we found when testing Slack's TURN servers
Our tests showed that Slack's TURN servers can be abused to relay TCP and UDP traffic to the TURN server itself and also internal addresses on Slack's AWS infrastructure. For the webapp-sort of penetration testers out there, this sounds familiar because that is how SSRF (server-side request forgery) vulnerabilities are usually abused. However, there is an important difference in that abuse of this vulnerability is not limited to just HTTP-based protocols (or targets that somehow respond to HTTP requests). Instead, we see it as closer to abusing an open proxy (e.g. a socks proxy or a web proxy with the
What could one do by abusing Slack's TURN servers?
- Connect to the AWS meta-data services at
http://169.254.169.254and obtain IAM temporary credentials
- Connect to open ports on localhost that are usually not exposed to the Internet (e.g. node exporter): 22, 25, 53, 443, 515, 5666, 8500, 8888, 9090 and 9100
- Port-scan the Slack AWS infrastructure on
10.41.0.0/16and find server management applications; possibly abuse such “trusted” services
Our methodology for testing for open TURN relay abuse
At this point, one might get the wrong impression that TURN servers do not have any authentication or authorization but the truth is that they do make use of authentication. In fact, each time there is a WebRTC session, new temporary TURN credentials are generated and returned by the system. An attacker must therefore retrieve these credentials. We used the following steps to do so:
- configure our web browser to use Burp proxy
- in the Proxy > HTTP history tab, filter for the keyword screenhero
- start a call by pressing the call button
- observe the TURN details returned in the call to
/api/screenhero.rooms.createwhich include the temporary username and password, TURN hostname and ports
- these details are then passed to our tool stunner that was written to abuse this vulnerability
Stunner is an internal tool that we developed to test STUN, and by extension, TURN for various protocol vulnerabilities. The first subcommand of interest here is
turn peer scanner, which runs a port scan through a TURN relay targeting a particular peer address. In the video demonstration we show the
turn peer httpproxy subcommand that implemented an HTTP proxy so that web browsers could be configured to pass through stunner, which then proxies HTTP requests and responses to the TURN server speaking its protocol. Finally, the TURN server relays this HTTP traffic back and forth to stunner.
And the rest, as they say, is a historic video:
The video shows:
- How to obtain the TURN credentials
- Testing relaying to the Internet through the TURN server by checking our IP address
- Connecting to internal network and meta-data services on Slacks AWS infrastructure
How to fix an open TURN relay to address this vulnerability
To address this issue, we recommend placing access control rules on the TURN server itself to block non-public addresses from being specified as the
XOR-PEER-ADDRESS in the TURN messages. In practical terms, most systems, including Slack's, make use of Coturn. Our recommendation is to make use of the following options:
no-multicast-peers denied-peer-ip=0.0.0.0-0.255.255.255 denied-peer-ip=10.0.0.0-10.255.255.255 denied-peer-ip=100.64.0.0-100.127.255.255 denied-peer-ip=127.0.0.0-127.255.255.255 denied-peer-ip=169.254.0.0-169.254.255.255 denied-peer-ip=172.16.0.0-172.31.255.255 denied-peer-ip=192.0.0.0-184.108.40.206 denied-peer-ip=192.0.2.0-192.0.2.255 denied-peer-ip=220.127.116.11-18.104.22.168 denied-peer-ip=192.168.0.0-192.168.255.255 denied-peer-ip=198.18.0.0-198.19.255.255 denied-peer-ip=198.51.100.0-198.51.100.255 denied-peer-ip=203.0.113.0-203.0.113.255 denied-peer-ip=240.0.0.0-255.255.255.255
Our recommendation here is to make use of the latest coturn which by default, no longer allows peering with
::1. In some older versions, you might also want to use the
- November 2017: added TURN abuse to our stunner toolset
- December 2017: discovered and reported TURN vulnerability in private customer of Enable Security
- February 2018: briefly tested Slack and discovered the vulnerability
- April 2018: submitted our report to Slack, helped them reproduce and address the issue through various rounds of testing
- May 2018: Slack pushed patch to live servers which was retested by Enable Security
- January 2020: asked to publish report
- February 2020: disclosure delayed by HackerOne/Slack
- March 2020: report published
We would like to extend our gratitude to the Slack security team who handled our report and provided us with test systems to check their security fixes. And many thanks to Alfred Farrugia for his work on stunner and reproducing this vulnerability reliably.
Who first discovered the TURN open relay abuse vulnerability?
From public records, it looks like that would be Cisco, who released an advisory for Cisco Meeting Server back in 2017 September 13.
We properly identified this issue separately, apparently in late 2016, by reading the TURN RFC and eventually proving the actual vulnerability by adding features within our internal toolset, stunner, to abuse this vulnerability. Since then, we have discovered various instances of the same vulnerability during our WebRTC Penetration Test engagements.
Is stunner available?
We use this during our penetration test services but unfortunately at this stage we cannot make it available outside of Enable Security.