How I found a bug that revealed your PayPal password

In the hunt for security issues, the pursuit of unexplored assets and hidden endpoints often ends up distracting you from the obvious but still essential functionality.

If you approach a goal as if you were the first person to assess safety, then I believe you will definitely find something new. Especially if the code you are testing is still in development. This is the story of a serious security bug affecting perhaps the most visited PayPal page: the login page.

First discovery

While researching the authentication flow in PayPal, I noticed a javascript file that contained what looked like a session id and CSRF token.

This immediately caught my attention because providing session data inside a valid JS file usually means allowing attackers to attack.

In an attack known as XSSI, a malicious web page can use the

However, the importance of a secret is measured by the damage you can cause if you know it. Therefore, I immediately decided to find out what exactly the _csrf and _sessionID variables mean and how they can be used in a real attack.

After countless attempts to replace the CSRF token of authenticated requests on the pay pal platform with _csrf, I came to the conclusion that classic request forgery with these tokens is impossible. Likewise, the session ID from the script was not enough to impersonate the victim.

Then I went back to the vulnerable script to understand what it was being used for. This took me into the depths of PayPal's underlying security mechanism that was used to prevent brute force, a known security issue. Although this functionality is used in many places, I will focus on the login form.

The idea was quite simple: after several failed attempts to login, before trying again, you would have to solve recaptcha. The implementation, however, may surprise you quite a bit.

When the system detects a probable brute force, the response to the next authentication attempt is a page that contains nothing but the Google captcha, and if the user resolves it, a POST request is initiated to / auth / validatecaptcha.

The body of the request contains the variables _csrf and sessionID, which are already familiar to us, as well as other values, which I will return to a little later.

The captcha validation request response is intended to re-enter the user with the authentication flow. For this purpose, the response contains an automatically submitted form with all data from the last login request, including an unencrypted email address and password.

I realized that with the right timing and some interaction with the victim, knowing all the tokens used in this request is enough to get a login and password.

In a real attack, the only thing that is required of the user is one visit to the page, which is controlled by the attackers. So I took a step back and tried to figure out what parameters were missing. It turned out to be easier than I expected.

  • The jse value was not validated at all.

  • recapcha was a token provided by Google when solving a captcha, it is not tied to a specific session, so any valid token, for example, generated by an automated service, may work.


Putting it all together, I created a proof of concept that demonstrates the entire process, excluding the integration of the CAPTCHA solution service.

The XSSI vulnerability is exploited first; this is done in order to get a set of tokens that would be valid in the victim's session. Then, in the victim's browser, several requests are launched with a random login and password, which simulate a brute-force attempt and launch a thread to solve the security problem.

As soon as the victim logs into PayPal from the same browser, the cached random credits are replaced with the user's email address and password. The last step is to get the recaptcha token, after which the credits are sent in raw form to the server, to the / auth / validatecaptcha endpoint to be displayed on the page.

Later, I discovered that the same vulnerable process was exploited by the order pages and allows an attacker to obtain credit card information in plain text using the same technique.

Information disclosure

The proof of concept, along with related information, was submitted to PayPal's Bug Bounty program on November 18, 2019, and verified on HackerOne 18 days later. This was followed by a quick confirmation from the PayPal team and a few additional questions. My reward was $ 15,300 and I received it on December 10th. Yes, the bug scored 8 points (high priority) on the CVSS scale - the same rating I gave when I submitted my report.

The patch was applied after another 24 hours. This means that the bug was fixed 5 days after the warning, which is quite an impressive time frame.

Correction and recommendation for prevention

The / auth / validatecaptch endpoint now requires an additional CSRF token that cannot be compromised by cross-site scripting enablement.

This approach does correct the vulnerability, but I believe that it could have been avoided if the oldest and most important advice in information security was followed in system design: never store passwords in plain text...

Even large companies make mistakes and vulnerabilities. On our course "Ethical hacker" we teach students to look for these vulnerabilities and make money from it. If you are tired of fixing bugs in the code and constantly building on something new - come to us, we will learn to "break", finding gaps in the software even from cool corporations.

find outhow to upgrade in other specialties or master them from scratch:

Other professions and courses

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *