BOOK THIS SPACE FOR AD
ARTICLE ADHi, I’m Amr Kadry, a penetration tester and bug hunter, acknowledged by over 45 companies including Mozilla, CrowdStrike, Canva, Vimeo, and others. Today, I want to share an interesting business logic vulnerability I recently discovered in one of Mozilla’s products.
I was poking around Mozilla’s products, armed with my trusty proxy and a lot of curiosity. I went deep — clicking, testing, and trying to understand how every little feature worked. After diving into all the requests and functions, I started feeling like a detective on the verge of cracking the case. But one product stood out — a monitoring product that grabbed my attention. This is where I focused my testing, and what I found was more than worth the effort. Let me explain.
First, let me give you a quick rundown of how the application works.
Mozilla’s Monitor is designed to help users stay informed about data breaches. Users can sign up with their email to receive alerts if their credentials are compromised in any known breach. It scans large databases of leaked information and cross-references user emails to notify them of any exposure.
Architecture
As evident from the architecture, the breach data is powered by haveibeenpwned.com. With this foundation in place, our focus will now shift to identifying and addressing specific logic vulnerabilities.
The main function, as I mentioned, revolves around adding email addresses for monitoring. In the free trial, each Mozilla account can add up to five emails.
For example, let’s say you add an email like moraa@gmail.com — once it’s added, a verification token is sent to that email address, which needs to be confirmed to activate the monitoring.
I first checked to see if there was any leaked verification token in the response, but that was handled well. Next, I tried manipulating the requests I sent to the server using various tricks. For example, I attempted adding multiple emails in the same request, hoping to trigger an error or retrieve any potential leaks. I also tested a race condition by sending multiple emails in one connection to see if the server would mishandle the requests or send the same verification token to different emails. But, once again, the server handled everything flawlessly.
Another issue here! The verification token is too long to be guessed or brute-forced. For example, a token like 8034a6f3-cecd-49a4-9c43-2cf5976380a1 would be nearly impossible to crack.
Without that verification token we as hackers are in trouble now :))
Detailed Explanation of the getAllEmailsAndBreaches Function
(if you don’t care about that explanation you can skip it)
By searching for the getAllEmailsAndBreaches function, I found that this function doesn’t retrieve data for verified emails only; it also returns information for unverified emails.
The getAllEmailsAndBreaches function is designed to collect and return email addresses associated with a user, along with any breaches related to those emails. Here’s how the function operates and its implications regarding verified and unverified emails:
Function Definition and Parameters:The function takes two parameters: user, which contains information about the user and their associated email addresses, and allBreaches, which is an array of breach records from the database.2. Initialization of Arrays:
Two arrays are initialized to store verified and unverified emails. The verifiedEmails array will hold emails that have been confirmed as valid, while the unverifiedEmails array will store emails that have not yet been verified.3. Error Handling:
The function contains error handling to ensure that both the user object and the list of breaches are valid.4. Retrieving User Emails:
This line calls getUserEmails, which retrieves all email addresses associated with the user from the database. It’s important to note that this may include both verified and unverified emails :))5. Processing Verified and Unverified Emails:
The primary email in accounts.firefox.com of the user is always processed first, and it is bundled into the verifiedEmails array:6. Returning Data:
At the end of the function, both verified and unverified emails are returned as part of an object. This means that the function exposes information about unverified emails, which could potentially lead to security concerns if not handled properly.The Verification Token is leaked in Response
As we can see, there’s no validation on the data returned for unverified emails. When I accessed this endpoint, I discovered that the verification token was leaked in the response for those unverified emails. Here we go!
Verification Email endpoint
I was able to grab that verification token and use it in the verification email endpoint to confirm the email. Now, I can easily monitor any email I want without any permission from the email’s owner , thanks to this misconfiguration :))
The Email has been verified and now can monitor it :))
Vulnerability Fixed by Removing Unused API Endpoint /user/breaches API GET endpoint
Submitted the report: September 11, 2024
Pending Program Review: September 12, 2024
Triaged as Medium: September 12, 2024
Rewarded the bounty: September 23, 2024
Resolved: November 19, 2024
Conclusion
In conclusion, this vulnerability in Mozilla’s Monitor product highlights the critical importance of thoroughly testing business logic and access controls. Through source code review, I identified a flaw in a single function that allowed me to bypass email verification, demonstrating how even small oversights can lead to significant security risks. Mozilla’s swift response to address the issue reflects their strong commitment to user safety. I hope this write-up underscores the value of meticulous code analysis and robust security testing in identifying and mitigating such vulnerabilities.
I hope you found this write-up beneficial and insightful. I’m always striving to improve my future write-ups and make them even more informative. Feel free to connect with me on LinkedIn or reach out on my X account if you have any questions or feedback. Looking forward to engaging with you!
LinkedIn: Amr Kadry
X: 0d_3mrr