How I compromised integrity of Twitter Fleets (iOS and Android)

How I compromised integrity of Twitter Fleets (iOS and Android)

·

3 min read

Beginning

At the beginning of May I was learning how to reverse engineer mobile apps. My focus was on iOS at the moment and I was learning a lot about proxies and runtime manipulation. One morning I've got an idea to research how Twitter built Fleet functionality. I went in with idea to simple stop request trough MITM and modify it on the fly. It actually worked!

Note: This isn't security threat per-say, this is issue with compromised show of content!

Writeup

Thinking process

I've never before researched or reported any bounty so I was brainstorming with my developer brain. What happens when I publish Fleet and how that can be modified?! I researched how Twitter handles publishing of Fleets and figured whole process can be modify to actually compromise integrity of Fleet it self.

Writing up POC (proof of concept)

Twitter Fleets integrity can be compromised by sharing tweet using "Share in a Fleet" option. Malicious user has ability to change shared tweet id and trick user in thinking that tweet they are clicking on is legitimate but in reality user can be baited to view a totally different malicious tweet. This issue in Fleets can also result in unableness to "skip" fleet.

Twitter app has a feature to share tweet as Fleet by using built in "Share in a Fleet" option. Creating fleet sends a request to a server that creates an object. That object can be modified to change shared tweet completely, which compromises the integrity of the shared resource. Even more, attacker can "force" user in opening modified tweet by extending media_bounding_boxes width and height values , resulting in "full screen layer" that is completely clickable and can't be skipped.

From:

{...
    "media_bounding_boxes": [
        {
            "anchor_point_x": 0.5,
            "anchor_point_y": 0.5,
            "entity": {
                "type": "tweet",
                "value": "1392985728271884288"
            },
            "height": 0.423306,
            "rotation": 0,
            "width": 0.936
        }
    ],
...
}

To:

{...
    "media_bounding_boxes": [
        {
            "anchor_point_x": 0.5,
            "anchor_point_y": 0.5,
            "entity": {
                "type": "tweet",
                "value": "1392124243710779394" //pointing to totally different Tweet
            },
            "height": 1000.423306,   //tweet can't be skipped because runtime drawn layer will be activated on click event
            "rotation": 0,
            "width": 1000.936  //tweet can't be skipped because runtime drawn layer will be activated on click event
        }
    ],
...
}

Impact

Every shared tweet is suppose to have an integrity . As user of the Twitter app I would expect that shown tweet, is one that gets open if I choose to interact with it. More for, as user of app I would like to have an option to "scroll" through fleets and not be forced to open one. This vulnerability compromises those already made "promises". Malicious attacker can stage scam campaign based on this issue.

Example: Attacker claims to be an account that provides memes of cute dogs, and it create fleets that share a dog related content, but in background attacker is using this vulnerability to pass in different tweets to full fill its malicious agenda . Once users starts interacting with those fleets: User can't skip Fleet User is forced to open tweet, because runtime draw of views with modified width and height User gets redirected to a tweet that is political ad, crypto scam, nsfw content etc.

Video showcase

iOS Fleet showcase

Android crash showcase

Bug bounty process

  • This "bug" was reported in May 15th, it went trough trough bug triage steps by May 20th.
  • Escalated to the point where change in values crashes Android app on opening "malicious fleet"
  • No response from Twitter for 2 months
  • Me publicly asking whats going on with ticket now that fleet feature will be discontinued
  • Twitter marking it as "informative" because they couldn't reproduce issue as valid threat!