According to a research conducted by PreciseSecurity, in 2019, nearly 40% of All Cyber Attacks were performed by using cross-site scripting (XSS).
In this post, you will learn more about this vulnerability. How it can be used to impact real systems and have some guidelines on how to deal with user data. Covering all possible attack vectors that stem from XSS is not in the scope of this article, but I’ll leave you with some links for you to learn more about this topic.
An XSS attack takes advantage of 2 main points of how the internet and browsers work:
Knowing this, the goal of someone that’s trying to exploit these flaws is to insert malicious javascript code in web pages for the victims to execute.
This kind of flaw has 2 main categories, Stored and Reflected.
Where the vulnerability is permanently stored on the target servers. For example, if we can insert a script in a comment section, everyone seeing the comments will be attacked.
Where the vulnerability comes from an input, for example, a GET parameter. If we can get our victim to click on a malicious link with a GET parameter, that is being printed back on the webpage, we have a successful attack.
Ok, security is fun to theorize about, but what’s the risk? As always, it depends on the type of web application, the existence of other existing vulnerabilities, the application visibility and lots of other things. So it can range from the attacker being able to redirect users to other pages, or to being able to steal authentication tokens from highly privileged users, rendering the login form useless.
Now you may be thinking: “Yea yea, that’s cool and all, but… give me real examples”.
The funniest case I’ve seen so far was exploited by Sammy Kambar. He was MySpace’s user and noticed that the platform was vulnerable to this flaw and that he could execute javascript in his profile.
He thought that it would be a good idea to execute javascript on everyone that visited his profile, where, without their knowledge, they would send him a friend request and change their profile description to “but most of all, Samy is my hero” and the same code would be replicated in the visitor’s profile.
The result wasn’t what he anticipated, as this turned into a worm, as it grew exponentially. This was the first documented case of an XSS worm and it infected over 1 million profiles in 24 hours.
Ok, but that’s an old platform, it should be solved by now, right?
Nope, see:
Learn more here.
We now know how this works, the risks and some companies that were affected by it, how do we exploit it?
Calm your horses, trying XSS attacks is part of a PenTest work that’s subjected to a prior agreement with the owners of that software. If you’re interested in trying to exploit an application that doesn’t belong to you make sure you have a PenTest request signed first[2]. There are companies that have an active bug bounty program and if followed, you are allowed to test their systems.
Here are some lists of companies that you can try this on:
So let's assume you are developing a web app and want to see if you’re vulnerable. The easiest way to do it is to run something link OWASP ZAP to crawl and test it for you.
But if you want to test it manually you can go to any section that accepts user input and prints it back, like a comment section and you can try inserting a script tag with some javascript, just like in the next image.
If you're successful, you’ll see something like this:
If not, maybe your application is already escaping some characters and if so we need to test evasion methods depending on where your input is being inserted, see a comprehensive list of evasion methods here: https://owasp.org/www-community/xss-filter-evasion-cheatsheet
To exploit a reflected vulnerability we can search for places on our application where we print a message that is sent through a get parameter and test it using something like this:
[URL]/?error=\%3Cscript\%3Ealert\%281\%29\%3B\%3C\%2Fscript\%3E
This, if successful, will return the same result as the last attack.
Remember that it’s possible to escalate this vulnerability, depending on your application, but that will require you to use your imagination.
A good place to start is to read these guidelines: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
But I know that’s tedious for most developers, so the number one rule is to NEVER TRUST USER INPUT.
If you have user input and want to print it back on the webpage, always sanitize it (encode it and validate it) and whitelist some terms if needed only for example <br> or <p> tags.
Every web language already has some implementation of functions to help you in this, like htmlspecialchars and filter_input in PHP, and some frameworks like Django already escape what they can when printing variables, see https://docs.djangoproject.com/en/3.0/topics/security/#cross-site-scripting-xss-protection
[2] http://www.vulnerabilityassessment.co.uk/Presite%20Inspection.html
©️ Cover Picture from https://www.geeksforgeeks.org/what-is-cross-site-scripting-xss/
This is an article written by Pedro Caseiro, Software Engineer @md3 Pedro started out as a self-taught PHP and Javascript web developer. With about 6 years of professional experience, he's a fan of SPA. Recently he started to transition to back-end Python developments.
Cookie | Duration | Description |
---|---|---|
_GRECAPTCHA | 6 months | Set by google api recaptcha. Used to validate form submission. It does not store any personal data. |
cookielawinfo-checkbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
CookieLawInfoConsent | 6 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store the consented cookie categories options. It does not store any personal data. |
pll_language | 6 months | The cookie is set by Polylang plugin and is used to store the selected language. It does not store any personal data. |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Cookie | Duration | Description |
---|---|---|
_ga | 2 years | This cookie is set by Google Analytics. The cookie is used to calculate visitor, session, campaign data and track site usage for the site's analytics report. Cookies store information anonymously and assign a randomly generated number to identify unique visitors. |
_ga_122676620_1 | 2 years | Set by Google to distinguish users. Connections on the same site only. |
_gac_gb_UA-122676620-1 | 90 days | This cookie is set by Google Analytics. Connections on the same site only. |
_gid | 24 hours | This cookie is set by Google Analytics. The cookie is used to store information about how visitors use a website and helps create an analytics report on how the website is doing. The data collected, including the number of visitors, the source from which they came and the pages visited in an anonymous form. |