Auth Bypass in ads.google.com

Reported by: Richie Lee

Google VRP

  • triaged

  • accepted

  • triaged

  • accepted

  • fixed

reward decided

$5,000

Google Ads - Disclosing script information in Bulk Actions through PREVIEW function

Hi!

I found multiple vulnerabilities in Bulk Actions from Google Ads. After some trial and errors, I believe the vulnerability happens to trigger in the PREVIEW function of Bulk Actions.

I decided to report this in Markdown format so it will be easier to understand the report. There are a few endpoints that are vulnerable to IDOR however can only be impactful if chained together to cause more damage.

In Google Ads Bulk Actions, there are 4 columns in the left which are All bulk actions, Rules, Scripts and Uploads

The vulnerability that I identified existed in Scripts section. I did not find anything juicy in All bulk actions and Rules (maybe I missed something but let's hope otherwise).

Understanding the vulnerability

There are two endpoints in PREVIEW function of Scripts that matters to us. Before that, we need to understand 3 identifiers which is sent in the JSON payload with it.

Ps. I don't work in Google so I might be wrong

  1. dashboard id Fictional, it is made up of 10 numeric characters which represents individual dashboard of a user. It is the first numeric string you will encounter when you decode the value of __ar. This might be public but I'm unsure which endpoint leaks it. Eg. 385089529

  2. script id Fictional, it is made up of 8 numeric characters which represents the individual script in a dashboard. It is the second numeric string you will encounter in /aw_bulk/_/rpc/ScriptService/Preview when you decode the value of __ar. This value will be bruteforced by the attacker to gain the value of execution_id. Eg. 3931988

  3. execution_id Non-fictional, this parameter name is reflected in /aw_bulk/_/rpc/ExecutionProgressService/GetIncrementalProgress. It is made up of 20 numeric characters which indicates it's not a good idea to bruteforce it. Once this value is combined with dashboard id, it will return information of a script through /aw_bulk/_/rpc/ExecutionProgressService/GetIncrementalProgress. Eg. 1725875959726807315

Scripts Endpoints
/aw_bulk/_/rpc/ScriptService/Preview

The above endpoint will need a valid dashboard id and script id to return a valid execution_id. In the first request it will return an OAuth URL. By navigating to it, it will prompt user to grant access to the script which discloses the script name. After granting access, resend the request and it will return the value of execution_id which can be used in the next endpoint.

/aw_bulk/_/rpc/ExecutionProgressService/GetIncrementalProgress

This endpoint will need a valid combination of dashboard id and execution_id to return the output details of the script.

Uploads Endpoints

This endpoint is identical to /aw_bulk/_/rpc/ExecutionProgressService/GetIncrementalProgress above however it doesn't return useful information nor it can be chained with others.

/aw_bulk/_/rpc/BulkExecutionStatusService/GetStatus

I'm leaving it here if the security team wants to investigate further or patch it along.

Steps to reproduce

  1. Create a profile in Google Ads and navigate to Bulk Actions

  2. Observe exists 3 columns which are Rules, Scripts and Uploads

  3. Click Scripts and create a new script with the following code and name it

    function main() {
    Logger.log("Hello Google VRP!")
    }
  4. Prepare to intercept a POST request to /aw_bulk/_/rpc/ScriptService/Preview

  5. Click Preview in the bottom right corner

  6. Obtain the value of dashboard id and script id

  7. Login into another account and perform the same thing.

  8. Retrieve the execution_id and use it in /aw_bulk/_/rpc/ExecutionProgressService/GetIncrementalProgress to get the script output information

Optional: Use an account to intercept a POST request to /aw_bulk/_/rpc/ScriptService/Preview and substitude both values to 385089529 and 3931988. Both of them are valid values of dashboard id and script id from my test account.

Unlisted YouTube POC video

https://youtu.be/6KNwYPgs8DQ

Attack scenario

A regular user finds a way to obtain a valid dashboard id (maybe through account sharing) and bruteforce a valid script id to retrieve a valid execution_id which will reveal their previous script output details.