I decided to do a write up about what I think is a unique account takeover bug that I recently found. I was really surprised on the ending and I must say I got extremely lucky as you’ll see later on. This is on a private program so I apologize for everything that is redacted and the few screenshots.
From blind XSS …
While doing recon on a domain, I stumbled on an application that had an old-looking home page with a login form on which HTTPS wasn’t used. I figured that if they didn’t even have a certificate on a login page, what else did they miss? I started looking around and playing with it a bit and decided to try to see if I can signup for an account. Unfortunately, I needed an @company.com email address or else my account had to go through an approval process by an employee. With that in mind, I figured I would test to see if the application was vulnerable to blind XSS. I submitted my payload in the first name and last name fields and to my surprise, as soon as I hit the submit button I got the following error message. I didn’t take a screenshot of the error message with my blind XSS payload but it’s practically the same thing.
… to blind SQLi
I figured I’d try and get an SQL injection and get back to the blind XSS later on. Usually, when I find these kind of error messages I simply use sqlmap to see if it can do the dirty work for me. Unfortunately, I didn’t get any success with it probably mainly because I couldn’t signup with the same email address twice. There is probably an option in sqlmap where I could’ve configured it to increment a digit or something in the email address so that it sends a unique one on each requests but I figured it might be faster if I do it manually. I was struggling a bit with it as I was constantly getting invalid syntax. I decided to get in touch with Gerben Javado who I know has had quite a bit of success in SQL injections. With his help, I was able to submit a valid SQL query. However, in the response, I simply got a message showing that the user was created and that I had to wait until my account was activated.
So this confirmed that it was a blind SQLi since I couldn’t see the result directly in the page, I ended up using this payload for my PoC.
"-IF(MID(@@version,1,1) = 5, sleep(10), "")-"
The application took 10 seconds to respond which confirmed that the MySQL version was 5. And if I changed 5 to something else like 4, it responded right away.
On a side note, I also was able to get a reflected XSS here as well since special characters were being reflected in the page. But this is not what my write up is about, so back to the account takeover. :)
Back to basics
Now that I knew what characters to use without getting an invalid SQL query, I was able to submit a working blind XSS payload. I was constantly refreshing XSSHunter to see if I had any new fires. On that note, I strongly suggest using XSSHunter for testing for blind XSS and if you have any success with it, why not donate a part of your bounty to the developer :) It was a bit late and I couldn’t concentrate anymore so I went to bed. The next day, I was looking at my notes and realized 3 things I had missed or features I didn’t really look at.
- In the first screenshot about the MySQL error, we can see at the bottom it says “Please contact XXXXXX and let him know you’re having trouble. meaning I now had a valid email address to work with.
- In the second screenshot, it says an email notification is sent once an account is approved meaning I know the application can send emails.
- And last but not least, I hadn’t taken a single look at the password reset functionality yet.
Combining all of these together, I decided to test the password reset functionality on the email address I had. That said, I had the ok with the company to do this as in my report about the SQLi, they said they were most likely going to be removing this app as it’s not used anymore so they told me I could do pretty much what I’d like with it and they’d take care of the consequences, which was pretty cool and definitely a first for me!
Let’s get an account takeover!
On the password reset feature, the only requirement was to have a valid email address and it would send an email to the user. What was in the email I had no clue. I started off by testing if it was vulnerable to HPP and then SQLi but I still did not have any luck. Then I thought that if it’s sending an email to the address I’m specifying, maybe I can try to add a second email address by adding myself in CC or BCC of the email by using SMTP header injection. This is a technique I had used in the past, maybe in the OSCP labs or a school project, I don’t remember where exactly, but I know it had worked for me before.
SMTP header injection vulnerabilities arise when user input is placed into email headers without adequate sanitization, allowing an attacker to inject additional headers with arbitrary values. This behavior can be exploited to send copies of emails to third parties, attach viruses, deliver phishing attacks, and often alter the content of emails. It is typically exploited by spammers looking to leverage the vulnerable company’s reputation to add legitimacy to their emails. This issue is particularly serious if the email contains sensitive information not intended for the attacker, such as a password reset token.
After a few minutes, I was able to come up with this working PoC.
Which is URL decoded to:
Are you kidding me?
I took a look at my emails right away to see if there was some sort of password reset token or anything I could use to reset the user’s password and hoping there wasn’t any kind of 2FA implemented. To my pleasant surprise, this is what I got in the email:
This is not even a joke! The application literally sent me the user’s password in clear text which I was able to confirm was still working by logging in. I submitted my report to the program and tested some more. I ended up finding a quite a few more bugs including my blind XSS payload that I was working on earlier :) and some more SQL injections on which I discovered that absolutely everything in the database was in clear text! Yes, as you might’ve guessed, everybody’s passwords as well.
I reported my findings to the program right away and suggested to put the site down immediately as it was game over for them.
Thank you for reading :D