The Meta Conversions API Gateway is a server-side mechanism for businesses to send web events to bypass browser-based tracking methods like the Facebook Pixel. Even if a user has cookies disabled, ad blockers on, or other browser restrictions, this method still works.
The API gw.conversionsapigateway.com is Meta's own deployment of the application. The fbq JavaScript module includes the collection/processing module in a JavaScript file named capig-events.js. Any vulnerability in this script could inherit the privileges of the site it's on, such as business.facebook.com.
capig-events.js only triggers when the page has an opener window. This event includes various pieces of data, such as the message type. If the type is IWL_BOOTSTRAP then the script will check if the pixel_id exists in the list. The event origin is never explicitly verified, meaning that this can be called from any origin.
After some processing, the event.origin is used in order to dynamically load JavaScript via <origin>/sdk/<pixel_id>/iwl.js. Since an attacker can control the origin of arbitrary loaded JavaScript, this creates the opportunity for some nasty XSS. This is a classic case of not validating the origin data from a post message call and using the data anyway.
This isn't immediately exploitable because a CSP and Cross-Origin-Open-Policy (COOP) are enabled. CSP is setup to not allow arbitrary external scripts and most pages include a COOP of same-origin-allow-popups. On the surface, this appears to prevent the issue. However, the security is not evaluated on a single page or a single policy; it is evaluated across all contexts where the code runs.
For a CSP bypass, some major pages allow third-party analytics providers to be on the page. This expands the attack surface where XSS or a subdomain takeover would do the job. For the COOP bypass, an attacker can regain access to an opener by reusing a
window.name. They found a vulnerability in a third-party application that allowed them to hijack the iframe to interact with the page with a CSP allowed site. Here's the full exploit chain:
- Load URL inside of Facebook application.
- Perform the opener bypass to a less strict CSP location.
- Hijack the iFrame of the third-party site. This sends a postMessage to the parent window to trigger the exploit.
- Host an attacker-controlled JavaScript file on the third-party host with the malicious JavaScript. Script is executed in the context of www.meta.com.
- They took this to a full account on facebook by abusing CORS permissions.
After reporting the previous vulnerability, they decided to review how the conversions API actually worked. When loaded on Meta, it displayed a graphical tool to the user. After experimenting with some of the rules for events and parameters, they noticed a POSt request for adding a rule. Upon reviewing the source, they noticed that the rule information was dynamically generating JSON within the capig-events.js script.
The JSON keys are supplied in the request and are used to construct a JavaScript string without any escaping or validation. So, "]} could be used to add attacker-controlled JavaScript in the generated output. In practice, this creates stored XSS within the capig-events.js file. Notably, the payload is served to every user, including Meta-owned domains. This isn't just stored XSS; this is a supply chain attack.
The author of the post got paid $62K for the first bug and $250K for the second bug. Absolutely insane! I really appreciate the author's intricate knowledge of Meta applications. On the first bug, the CSP and COOP issues would have been easy to move on from, since they couldn't be exploited immediately. Instead, they already had either A) the gadgets ready to go for this or B) known where to find them. This knowledge has served this security researcher very well!