Executing CSRF With Phone Validation
2021-06-07 14:12:43 Author: infosecwriteups.com(查看原文) 阅读量:122 收藏

How to Programmatically Harvest the OTP

Greg Gibson

When I submit a vulnerability on a Bug Bounty program, I typically seek to build an exploit that automates as much of the Proof of Concept as possible to:

  1. Ensure it’s 100% clear the exploit can do what I’m claiming.
  2. Simplify reproduction for both the triage team and the company — if the reproduction steps require the team to simply navigate to a URL you supply, you can eliminate any confusion.
  3. Have fun! Building things is a great way to learn new tech.

I recently identified a Cross Origin Resource Sharing (CORS) vulnerability on an API that allowed a user to add a phone number to their account. In what is a fairly common flow, the user first would submit their phone number, the application would text a six digit One Time Password (OTP) to that phone number, and the user would then enter the OTP into the website to prove it was in fact their legitimate phone number.

This flow can provide both validations — by ensuring users enter a phone number they control, and security — as it makes it difficult for an attacker to take advantage of a Cross-Site Request Forgery (CSRF) vulnerability as you must make two distinct API calls with a dynamic value triggered by the first (and importantly delivered out of band) to be submitted in the second.

I spent a few hours attempting to use AWS Pinpoint and Twilio long codes (that is a normal 10 digit US phone number) to receive the OTP to no avail and my assumption at this point is there are certain checks in place that limit this B2B type messaging, instead only engaging with actual mobile numbers.

Enter Google Voice

I’ve used Google Voice for a few years and my de facto standard is to forward all incoming SMS to my personal phone number — an added convenience that allows me to text normally through the iOS messaging app versus switching into the Google Voice app.

The target application also had no issues sending the OTP to my Google Voice number so I began experimenting with using Google Voice as an intermediary between the application and Twilio. Google needed to send an OTP to my Twilio number to validate it much in the same way as the application wanted to validate my Google number. Using the Twilio API I was able to harvest the code and complete the forwarding. You can read more about setting up SMS forwarding directly from Google Support: https://support.google.com/voice/answer/9182115.

Architecture

The key to making this exploit realistic and seamless is programmatically retrieving the OTP — and doing it quickly which required building both the client-side “malicious” JavaScript to execute the API calls as well as setting up a third attacker-controlled API that could retrieve the OTP.

The basic architecture is shown above with the following flow:

  1. The victim visits a webpage running the malicious script.
  2. JavaScript sends an HTTPS POST request with JSON body including the attacker’s phone number to the target application. This triggers a preflight OPTIONS request but is ultimately allowed via the Access-Control-Allow-Origin headers echoing the request origin.
  3. The target application sends an OTP to the attacker’s Google Voice number, which then forwards that SMS to Twilio.
  4. JavaScript sends an HTTPS GET request to the attacker’s API, which triggers Lambda to harvest the code from Twilio and return it in the HTTPS response.
  5. JavaScript sends the final HTTPS POST request to the target application with the attacker’s phone number and OTP to validate.

Client-Side Code

I’m by no means a JavaScript developer — rather I can hack things together well enough to make my exploits work. That said, a few keys to making this work were forcing JavaScript to block and wait to ensure the three API calls occurred in order, and only when ready (versus the asynchronous free for all that typical JS can be).

**Note: Both the Client and Server Side code snippets contain the basic working code I used. However, I’ve removed and changed some things for simplicity and readability. If you want to duplicate this effort, use these as a baseline.**

I set up each API call as a standalone function which would call the next function only when the request had completed successfully — ie the first API call must complete before the second API call is triggered. Additionally, in the poll_twilio function, I added recursion to reattempt the call to the attacker API until the OTP code was successfully returned — this would allow for the OTP to work its way from the target application to Twilio and prevent the exploit from breaking if there were any delays along the way.

Server-Side Code

Within the Lambda, the code only needs to do a few things — poll Twilio for any messages, parse them to see if the OTP code has been received, and return an appropriate response (either 200 or 404) depending on the result. Twilio DOES provide a Python SDK but for such a simple integration I chose the REST API.

A few design decisions I made were to delete EVERY message EVERY time. You can’t assume only OTP messages will be delivered to Twilio if you have forwarding configured on an existing number. I also wanted to ensure subsequent exploit instances were not attempting to either sort through a huge message queue or finding old, formerly valid OTP codes and returning them as valid.

However, at scale, this wouldn’t work. If multiple victims were being exploited simultaneously you’d need a better way to find the right OTP code which is outside of the scope of this proof of concept.

Final Thoughts

Although not mentioned, you will need to familiarize yourself with AWS API Gateway and also set up a trial account with Twilio to build this exploit yourself. My client-side code was simply hosted in S3 as an effectively blank webpage containing only the script.

Although this entire POC may not have been necessary to demonstrate the exploit, both the Triage team and the Program commented on the quality of the work. Additionally, other vulnerabilities are currently mitigated with the use of OTP and could be reliably exploited with this automation.

I’m not very active on Social Media, but you can find me on LinkedIn, Bugcrowd, or hanging out in various security Slack or Discord servers!


文章来源: https://infosecwriteups.com/executing-csrf-with-phone-validation-103c525dd310?source=rss----7b722bfd1b8d--bug_bounty
如有侵权请联系:admin#unsafe.sh