This is the story of how a failed Bootstrap implementation on a website allowed me to gain JavaScript code execution into thousands of user browsers.
How I Found It?
Before I get into the story, I'll quickly explain how I found this vulnerability in the first place. I have started developing a new opportunistic approach for acquiring persistent XSS (Cross Site Scripting) on various web-services across the Internet. This methodology consists of the following steps:
- Use custom web-crawler to spider web services across the Internet and scrape source code. It iterates through IP addresses and hits the web-root content for every IP address.
- It then identifies websites that are using externally hosted JavaScript. This is achieved for each server by…
- Reviewing the HTML source code for <script> tags with a source (src) value containing a full web-address (rather than a local path). An example would be <script type='text/javascript' src='https://domain.name/path/to/hosted/javascript.js'></script>
- I also ensure that the <script> src value is not just pointing back to the same server that is hosting the website. To do this, I acquire the server name through inspection of the host value in the HTTPS certificate, and cross-reference that against the host name in the <script> tag to ensure that the site hosting the Javascript is on a different server than the target website.
- If the Javascript is confirmed to be hosted externally, the script executes an API request to a name-registrar service to determine if the domain in the <script> tag is available for purchase.
- If the domain is available, trigger an alert to indicate that Javascript injection into the web-service is possible.
- Examine the cost of the domain name and review the web-service to determine if it is a heavily trafficked site. If there appears to be sufficient opportunity for widespread exploitation and the domain is not cost-prohibitive, purchase the domain name.
- Stand up a web-server and then create a DNS A record for the new domain which matches the subdomain of the <script> tag src value in the vulnerable site.
- You can now inject JavaScript into ALL THE BROWSERS!!!
A Case Study -- "You Forgot Your Boot"
In some cases, this methodology just returns abandoned blogs or other low-traffic sites that would have very little exploitative ROI (Return on Investment). In other cases, however, using this methodology can identify opportunities to inject JavaScript into the web-browsers of thousands of users. This is a case study of one such example that I recently found. While using my scanner, I recently got an alert for iht.edu.in. I quickly reviewed the website to determine that it is owned by IHT (The Institute of Horticulture Technology), an academic University in India.
I looked at the source-code to confirm the security flaw, and discovered that the IHT website (iht.edu.in) had a <script> tag pointing to maxcdn.strapcdn.com.
Anybody with front-end development experience (specifically with Bootstrap) will likely connect the dots and realize what happened here. The developer(s) intended to pull in JavaScript code from the Bootstrap framework (which is hosted at maxcdn.bootstrapcdn.com), but they accidently forgot the “boot” in the “bootstrapcdn” domain name. Because of this line in the source code, when anybody browsed to the iht.edu.in website, their browser would attempt to retrieve an external .js (JavaScript) file from a host (maxcdn) on the strapcdn.com domain. The problem is, the strapcdn.com domain was not registered or owned by anyone. This meant two things.
- The script tag wasn’t doing anything, because it was pointing to a non-existent source.
- More importantly, this domain could be registered by anyone and then used to serve up malicious JavaScript to all of the website users within the context of the website.
I logged in to my preferred name-registrar (NameCheap) and confirmed that the domain was available. It was...and it was only going to cost me $7.98 USD.
What I Did (...since I'm a "responsible security researcher")
To passively measure risk, I setup an Apache webserver and then created a DNS A record to associate the server with the subdomain referenced in the IHT website source-code (maxcdn.strapcdn.com).
I then passively monitored for inbound connections from the iht.edu.in domain. Sure enough, immediately after standing up the server, the connections started coming in.
Under normal circumstances, I would disclose a vulnerability of this caliber immediately. However, due to the nature of this vulnerability, my purchase of the domain made it impossible for anybody else to exploit it (at least for the next year while I own the domain). So I decided to wait and do some additional research to quantify the potential impact. I allowed this to run for a period of 2 weeks (March 12 – March 26), and within that time, I was able to receive JavaScript requests from 1,454 different unique IP addresses accessing the iht.edu.in website. That’s a hell of a lot of compromised browser sessions!!!
After evaluating for two weeks, I sent an email to the only address I could find for IHT, which is their admissions inquiry email address (enquiry@iht.edu.in) to inform them of the issue.
** UPDATE **
As of April 26 (one month from the initial disclosure), the vulnerability still has not been addressed. The script tag source attribute still points towards the domain name that I control. I have sent a follow-up email to IHT asking again for them to address the issue.
What I Could Have Done (...if I just wanted to watch the world burn)
I had no intentions of actually injecting any JavaScript into the browser of some poor unsuspecting sap that is only trying to improve themselves through horticulture education. But I did think it was a worthwhile exercise to access the website and then play around in the JavaScript console to see what might be possible.
Obviously, the first option would be to just deface the website when user’s access it (for the lulz). So I used my favorite JavaScript defacement code to make everything all cattywampus and force visitors of the site to have to rotate their computers to enroll…
I obviously do not have an account to access the website and review its behavior from a post authentication perspective. But by issuing a quick alert(document.cookie) command, it seems that they aren’t exactly in the habit of using HTTPOnly flags on their cookies.
This means there is also a high-likelihood that JavaScript could be used to harvest session tokens from users by (base64) encoding the output of document.cookie, assigning it to a variable, and then executing a background web request to a server that I control. User session tokens could be retrieved from the malicious server logs, and then used to hijack user sessions and gain access to their accounts.
Lessons Learned???
So what are the take-aways here?
- Check your source-code - You aren't sending an email to your inbred cousin in Kentucky. This is the source code to your website!!! Typos matter, and can have serious consequences. Check your source code, go get some coffee, and then CHECK IT AGAIN!!!
- Use HTTPOnly - Even if somebody manages to get code execution in your users' browsers, the protection of your cookies with HTTPOnly can go a long way in protecting their user accounts. So PROTECT YOUR COOKIES!!!
Comments
Post a Comment