Revealing a Clever Website Vulnerability Discovered Years Ago
Website security issues caused by multiple vulnerabilities combined
Photo by Tarik Haiga
Introduction
A few years ago, while still supporting web development, I was assigned the task of organizing a CTF competition for the company’s internal engineering team. Initially, the idea was to have teams attack and defend each other’s products, but as the organizer, I wanted to first understand the level of expertise. So, I conducted penetration tests on various company products to see how many vulnerabilities I could find, ensuring the event would run smoothly.
However, due to limited competition time and significant differences between engineering teams, the final questions were based on common engineering knowledge and interesting topics. Those interested can refer to my previous article, “ How to Create an Interesting Engineering CTF Competition “, which contains many mind-blowing questions!
Discovered Vulnerabilities
I found a total of four vulnerabilities across three products. Besides the issue discussed in this article, I also discovered the following common website vulnerabilities:
- Never Trust The Client! This is a basic issue where the frontend directly sends the ID to the backend, and the backend accepts it. This should be changed to token recognition.
- Password Reset Design Flaw I don’t remember the exact details, but there was a design flaw that allowed bypassing email verification during the password reset process.
- XSS Issue
- The vulnerability discussed in this article
All vulnerabilities were found through black-box testing. Only the product with the XSS issue was one I had participated in developing; I had no prior knowledge of the others or their code.
Current Status of the Vulnerability
As a white-hat hacker, I reported all discovered issues to the engineering team immediately, and they were fixed. It’s been two years now, and I think it’s time to disclose this. However, to respect my former company’s position, I won’t mention which product had this vulnerability. Just focus on the discovery process and reasons behind it!
Consequences of the Vulnerability
This vulnerability allows an attacker to arbitrarily change the target user’s password, log in to the target user’s account with the new password, steal personal information, and perform illegal operations.
Main Cause of the Vulnerability
As the title suggests, this vulnerability was triggered by a combination of multiple factors, including:
- Account login not supporting two-factor authentication or device binding
- Password reset verification using a serial number
- Decryption vulnerability in the website’s data encryption function
- Misuse of encryption and decryption functions
- Design flaws in the verification token
- Backend not re-validating field correctness
- User email being public information on the platform
Reproducing the Vulnerability
Since user emails are public information on the platform, we first browse the platform to find the target account’s email. After knowing the email, go to the password reset page.
- First, enter your own email to initiate the password reset process.
- Then, enter the email of the account you want to hack and initiate the password reset process again.
Both actions will send out password reset verification emails.
Go to your email to receive your password reset verification email.
The change password link has the following URL format:
1
https://zhgchg.li/resetPassword.php?auth=PvrrbQWBGDQ3LeSBByd
PvrrbQWBGDQ3LeSBByd
is the verification token for this password reset operation.
However, while observing the verification code image on the website, I noticed that the link format for the verification code image is also similar:
1
https://zhgchg.li/captchaImage.php?auth=6EqfSZLqDc
6EqfSZLqDc
shows 5136
.
What happens if we put our password reset token in? Who cares! Let’s try it!
Bingo!
But the captcha image is too small to get complete information.
Let’s keep looking for exploitable points…
The website, to prevent web scraping, displays users’ public profile email addresses as images. Keyword: images! images! images!
Let’s open it up and take a look:
Profile Page
Part of the Webpage Source Code
We also got a similar URL format result:
1
https://zhgchg.li/mailImage.php?mail=V3sDblZgDGdUOOBlBjpRblMTDGwMbwFmUT10bFN6DDlVbAVt
V3sDblZgDGdUOOBlBjpRblMTDGwMbwFmUT10bFN6DDlVbAVt
shows zhgchgli@gmail.com
Same thing, let’s stuff it in!
Bingo!🥳🥳🥳
PvrrbQWBGDQ3LeSBByd
=2395656
After reversing the password reset token and finding out it’s a number
I thought, could it be a serial number…
So I entered the email again to request a password reset, decoded the new token from the received email, and got 2395657
… what the fxck… it really is.
Knowing it’s a serial number makes things easier, so the initial operation was to request a password reset email for my account first, then request it for the target to be hacked; because we can already predict the next password request ID.
Next, we just need to find a way to convert
2395657
back to a token!
Coincidentally, we found another issue
The website only validates the email format on the frontend when editing data, without re-validating the format on the backend…
Bypassing the frontend validation, we change the email to the next target.
Fire in the hole!
We got:
1
https://zhgchg.li/mailImage.php?mail=UTVRZwZuDjMNPLZhBGI
Now, take this password reset token back to the password reset page:
Success! Bypassed verification to reset someone else’s password!
Finally, because there is no two-factor authentication or device binding feature; once the password is overwritten, you can log in directly and impersonate the user.
Reason for the Incident
Let’s review the whole process.
- Initially, we wanted to reset the password but found that the reset token was actually a serial number, not a truly unique identifier.
- The website abused encryption and decryption functions without distinguishing their usage; almost the entire site used the same set.
- The website had an online arbitrary encryption and decryption entry (equivalent to the key being compromised).
- The backend did not re-validate user input.
- There was no two-factor authentication or device binding feature.
Fixes
- Fundamentally, the password reset token should be a randomly generated unique identifier.
- The website’s encryption and decryption parts should use different keys for different functions.
- Avoid allowing external arbitrary data encryption and decryption.
- The backend should validate user input.
- To be safe, add two-factor authentication and device binding features.
Summary
The whole vulnerability discovery process surprised me because many issues were basic design problems; although the functionality seemed to work individually, and small holes seemed safe, combining multiple holes can create a big one. It’s really important to be cautious in development.
Further Reading
- How to Create an Interesting Engineering CTF Competition
- The App Uses HTTPS, But Data Was Still Stolen
- Security Issues with SMS Verification Code for Password Recovery
If you have any questions or comments, feel free to contact me.
===
===
This article was first published in Traditional Chinese on Medium ➡️ View Here