Information security has fascinated me as a hobby. Finding web vulnerabilities is a game of (ab)using a system in a permitted but unintended way. Here’s some of the more fun things I have discovered. All were all responsibly disclosed to the vendor and fixed, and outside of established bug bounty programs, I don’t recommend poking around into other people’s systems.
XSS on thousands of domains, courtesy of unsubscribe links
One obvious place to look for vulnerabilities are in URLs. You see a
?id=123? Might as well try
?id=123'" to see what happens. But you can go a lot deeper.
I received some unsolicited marketing email with an unsubscribe link. A normal person would ignore the email or unsubscribe and be done. Instead, I wanted to see how they were tracking me. What I saw in the URL was similar to this:
= is enough of a hint at base64 encoding. Decoded, that’s:
Well, first thing’s first: can I unsubscribe other email addresses, or is that ID connected to my email? Yep, turns out any email address works.
Importantly, I noticed that the decrypted email string was in the source, inside a script block. On a hunch, I changed my email address above to something entirely else:
And presto, the page broke. Cross site scripting injection — there was absolutely no sanitization.
This is interesting because this email came from a very well known, publicly traded email marketing company that commonly white-labeled their product on customers' domains. So, there were tens of thousands of domains with the form
email.customerdomain.com that had an XSS, including several Fortune 500 companies. Within about an hour, I found six very large consumer companies with an exposed subdomain using their software, meaning the blast radius of this was quite wide. Four of these companies allowed their login cookies to be read from the vulnerable domain.
I promptly tried to find a security contact for this email marketing company. In all, it took 2 weeks to get a human, and an additional three months for them to fix it. There was never any followup or disclosure to customers about the vulnerability.
XSS via Emoji skin colors
Emojis are made of unicode character points. They cleverly use modifiers to turn 👍 into 👍🏾 using the 🏽 skin tone.
The skin tone modifiers are just unicode character points, but those are annoying to work with, so—sample size two, of enterprise chat apps with >10m daily active users—people end up being a bit lazy and just treating them as strings. And not validating those strings in any way.
In Slack, this allowed me to make a persistent self-XSS by setting the preferred skin tone to be
2<script>alert(1)</script>. Including remote scripts worked as well, so the entire application could be compromised.
In another (not named because I didn’t report it through a public bug bounty program), I could “react” to any post, and everyone else’s browser would run my XSS-ed skin tone.
Open uploads, fake MIMEs, null bytes
This one is fairly specific, but shows how several small vulnerabilities can combine to create a big one. A fairly popular stock charting application allowed screenshots to be uploaded from their application. Using packet capture, I found that it was using a PHP script. Based on some trial and error, I figured out that the script validated the extension and MIME type of the uploaded file, but didn’t validate if it was a real image. Additionally, they let you rename images once uploaded, but the newly named file needed to end in
So, I uploaded a simple PHP script as
image.png, with a fake MIME type. I then discovered that I was able to rename the upload to
image.php\u0000.png (with an included null byte), which made the file on disk as
image.php, but passed their re-naming validation.
From there, I needed to find the location of the uploaded script, if indeed it was web-accessible. Their image viewer proxied the image file through a script, which I presume was used to track usage analytics or something similar. Fortunately, the site had a
robots.txt that disallowed indexing of many
/uploads/<year>-<month>/ locations. From there, I was able to guess the path of my script, which executed flawlessly.
At this point, their site was fully exploited — they used this server to host their binary application, and all their finance data came from a database that was also used by this website. Overall, I would have been able to download all customer information, infect their binary application, etc.
Of course, I didn’t do any of this once I realized the extent of the vulnerability. I let them know the issue, and they had it fixed within a couple hours. We both confirmed that the vulnerability had never been exploited by someone else, and they gave me lifetime access to their application out of gratitude.