Create an invisible post on any Facebook page
You may know that you can create many types of posts on your Facebook feed. one of them is called "invisible" (unlisted) which unlike other types cannot be seen on your feed, but like others, it has a link and id.
These types of posts are not shown on the feed timeline but are accessible via a direct link. the main impact of these types of posts is that the page admins cannot view or delete them since they don't have any links.
An attacker can use the post sharing feature to send it to others.
At Creative Hub we can create ads and use collaboration to complete them. Facebook creates an invisible post on the selected page for previewing them to the users.
I intercepted the request and change the "page_id" to the victim's "page_id" and it saves without any error or issue.
The permission here has been checked before generating the preview so you should definitely have the advertiser role. (above image)
Also, the Share Feature (image below) has been added to Facebook's Creative Hub recently, therefore, I started digging deeper into it again.
After clicking on the share button the API will answer with a new shareable URL like this:
https://www.facebook.com/ads/previewer/__PREVIEW_KEY__
The gotcha is that the permission-check is missing before generating a preview post on the share page.
Changing page_id before saving the mockup in Graphql request and then getting back the sharable link for it, gives us the ability to create a post on any page.
All we need to do is to find the post_id that exists on any ad preview endpoints.
Finally, we created an invisible post on the victim page without their knowledge!
POC:
Facebook fixed this vulnerability after I reported it but still, I was able to bypass the fix by using another approach.
// This request will create a post page plus sending a notification to the mobile deviceAsyncRequest.post('/ads/previewer/notify_mobile/__PREVIEW_KEY__',{})
The "send to mobile" feature creates a preview again without checking permission.
Bypass POC:
Timeline:
November 6, 2020 – Report Sent
November 6, 2020 – Triaged
November 11, 2020 – Fixed
November 12, 2020 – Bypass Sent
November 12, 2020 – Triaged
November 20, 2020 – Fixed
December 16, 2020 – $30,000 Bounty awarded