Securing Apache, Part 4: Cross-site Tracing (XST) & Cross-site History Manipulation (XSHM)

3
16586
Locked up!

Locked up!

This series of articles addresses the Web security concerns of information security experts, systems administrators and all those who want to jump-start their careers in this domain. This time we will delve deeper into Web application security, peel off the layers of cross-site tracing (XST) and cross-site history manipulation (XSHM) attacks, and recommend some solutions.

In part 3 of this series, we discussed about XSS attacks; in solutions to these, we talked about using HttpOnly cookie mechanisms. HttpOnly is a session protection mechanism which specifies that the session identifier should not be accessed from the application DOM. In that case, the attacker cannot hijack the session using malicious scripts, because document.cookie does not return anything useful. HttpOnly works with almost all modern browsers. It is implemented simply as:

Set-Cookie: PHPSESSIONID=[token]; HttpOnly

It was by far one of the best ways to stop XSS attacks from fetching a victim’s cookies — until it was found that the web server HTTP TRACE method (more about it below) can be used to bypass HttpOnly security mechanisms.

If an attacker forces the victim’s browser, using XSS, to issue a TRACE request to the web server, and this browser has a cookie for that domain, the cookie will be automatically included in the request headers, and will therefore be echoed back in the resulting response. At that point, the cookie string will be accessible by JavaScript, and it will be finally possible to send it to a third party even when the cookie is tagged as HttpOnly. Hence, XST is nothing else but doing an XSS attack using TRACE.

HTTP TRACE and XST

The HTTP TRACE request is a method designed for debugging problems such as network connection errors between servers. It is defined with other well-known methods like GET, PUT, DELETE, etc.

When a client sends a TRACE request to a compliant server, the server responds by echoing back the header sent by the client. An attacker can exploit this to circumvent HttpOnly cookies by injecting code that sends an asynchronous XMLHttpRequest with the TRACE method, and receiving the HttpOnly cookie in the message echoed back by the server.

Let’s have a look at a simple attack scenario to understand it clearly:

Attack scenario

Let’s continue with the example that we used (for reflected XSS) in part 2 of this series. When an attacker finds an XSS vulnerability in a web application, where the application’s script displays the criteria used in a website query as part of the URL for the results of the query. For example, the URL in the browser for a page showing the results for a search for “products” might be http://www.example.com/search.php?query=products. Now, take the following cases:

When HttpOnly cookies are not deployed, and TRACE is enabled

Here, as already discussed in part 2, the attacker might post a modified link, such as this: http://www.example.com/search.php?query=<script>alert(document.cookie)</script>.

This harmless example will cause the victim’s browser to pop up an alert box, showing their current set of cookies.

When HttpOnly cookies are deployed but TRACE is still enabled

Here, it is clear that the  above method will not work for the attacker, because HttpOnly will not return these cookies to the JavaScript document.cookie. So here, the attacker, knowing that TRACE is enabled on the web server (they can verify it by methods given in the security section below), might use something like the following code (call it mal.js):

<script type="text/javascript">
var x = new ActiveXObject("Microsoft.XMLHTTP");
// var x = new XMLHttpRequest();
x.open("TRACE", "http://example.com",false);
x.send();
//x.send("");
cookie=x.responseText;
alert(cookie);
</script>

(The code above is used for Internet Explorer browsers; modifications required for Mozilla are commented out).

This will alert the victim with their cookies even after HttpOnly is used. Remember, here the attacker can shorten such a big malicious code via tiny URL techniques (refer to part 2 of this series). The attacker can also steal here the cookies, and other login credentials. A visualisation of this is shown in Figure 1.

Attack possible with TRACE enabled
Figure 1: Attack possible with TRACE enabled

The particular example above is taken just for educational purposes. I once again stress that neither I nor LFY aim to teach readers how to attack servers. Rather, the attack techniques are meant to give you knowledge that you need to protect your own infrastructure.

What’s going behind the scenes?

The above code, using the ActiveX control XMLHTTP, will send a TRACE request to the target web server. If TRACE is enabled on the web server, it will then echo the information sent within the HTTP request. Now, if the victim’s browser happens to have a cookie from the target Web server, or is logged in to the server using implicit authentication mechanisms, they will then be able to see their cookies.

What if you disable TRACE?

Many security experts suggest that you disable the Web server’s TRACE method to begin with, though it  provides an effective security measure (see Figure 2).

Attack not possible with TRACE disabled
Figure 2: Attack not possible with TRACE disabled

However, if there is a proxy server between the client and the web server, it has been found possible to force the proxy server to respond to the TRACE request, rather than the origin server itself. To do this, the attacker would simply include Max-Forward: 0 in the HTTP request header. Seeing this, the first proxy server in the chain will respond to the TRACE request, instead of forwarding it to the web server. Hence, the XSS script could be updated to:

<script type="text/javascript">
var x = new ActiveXObject("Microsoft.XMLHTTP");
// var x = new XMLHttpRequest();
x.open("TRACE", "http://example.com",false);
x.setRequestHeader("Max-Forwards", "0");
x.send();
//x.send("");
c=x.responseText;
alert(c);
</script>

(Again, the base code is for Internet Explorer, modifications for Mozilla are commented out).

Microsoft, trying to secure Internet Explorer, removed the support for any method starting with TRACE in the XmlHttp object. However, this security measure was also broken when it was found that instead of using “TRACE”, the attacker can simply use “rnTRACE”. Hence, the line in the above script, x.open("TRACE", "http://example.com",false) would become x.open("rnTRACE","http://example.com",false).

Cross-site tracing (XST) is one of the most silently prevalent threats on the Internet today. However, following the security tips below can help you curb it.

Time for Security

  1. The first and the foremost security measure is to disable the TRACE request method (unless needed) on your web servers.
  2. Moreover, Web-server vendors should have TRACE disabled in the web-server’s default “out-of-the-box” configuration.
  3. Proxy servers should also be shipped with TRACE disabled in their default configurations.
  4. Disable TRACE in your browser’s XmlHttpRequest object too. For this, check the support page of your browser’s vendor.
  5. For all Internet Explorer users: if you must continue using Internet Explorer, switch to version 7 or 8, because they seem to have patches for this attack. However, the far better path, which I recommend, is for you to use the latest versions of Mozilla Firefox (>3.2) instead.

How to disable TRACE in Apache?

Disabling TRACE in Apache is quite easy. The only thing one requires is the Apache mod_rewrite module installed, and then, follow these steps:

  1. Activate mod_rewrite in httpd.conf by adding this line to it:
    LoadModule rewrite_module modules/mod_rewrite.so
  2. Add the following lines in httpd.confto disable TRACE:
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} ^TRACE
    RewriteRule .* - [F]
  3. Now, restart the Apache Web server.

After TRACE has been disabled according to the instructions above, any incoming TRACE requests will be responded to with an HTTP status code of either 403 or 405. You can also verify it by telnetting to your server, as shown below:

server@attacker~$ telnet www.victim.com 80
OPTIONS / HTTP/1.1
Host: www.victim.com
HTTP/1.1 200 OK
Server: Apache-httpd/2.2.1
Date: Tue, 31 Oct 2006 08:00:29 GMT
Connection: close
Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS
Content-Length: 0

As we can see in the example, the Allow line provides a list of the HTTP methods that are supported by the Web server. In this case, we see that every method is enabled except for the TRACE method.

Let’s now move on to another web application attack: cross-site history manipulation (XSHM).

Cross-site history manipulation (XSHM)

This recently evolved attack works by taking advantage of an individual’s browsing history, seen in Mozilla Firefox, Google Chrome and Internet Explorer. By manipulating the browser history, it is possible to compromise a web browser’s same-origin policy (SOP), and so violate user privacy.

Recall that in part 3 of this series we discussed a bit about SOP, and also that web pages from different origins cannot communicate with each other (“communicate” here means that a page from one origin can only send an HTTP request to a page from different origin; however, it cannot read an HTTP response of a page from different origin).

Hence, while doing CSRF, an attacker can only submit malicious HTTP requests to a bank website, but he/she cannot read the HTTP response from that site. However, recently it was found that even these limitations for the attacker can be bypassed by compromising SOP, via manipulation of the browser’s history objects.

First, let’s look at the design of the browser history object.

Browser history object

Browser history is a global list of pages visited by the user, which the user can cycle through by pressing the Back and Forward buttons of the browser. Some of its features are:

  1. If the same URL is opened multiple times, only one entry will be made into the history list.
  2. If a user opens page B, which is then automatically redirected to page A (by the web server), then only the URL of page A will be entered into the history list.
  3. It is possible to open a URL without adding it to the history list. By using location.replace, we can open different URLs, one after the other, replacing the current history position.
  4. SOP only prevents JavaScript from accessing URLs in the history; it does not prevent access to history.length (the number of elements in the global history list). Also, it is possible to load a specific URL from the history list, using history.go(URL).

The following are XSHM attack vectors which use manipulation of the browser’s history object:

  • Cross-site condition leakage
  • Cross-site user tracking
  • Cross-site URL/parameters enumeration

We will focus on these one by one.

Cross-site condition leakage

Suppose a site contains the following logic:

Page A: If(Condition)
        Redirect(Page B)

Here, an attacker can execute a CSRF attack to get an indication about the value of Condition (whether it’s TRUE or FALSE) as feedback. Such an attack is executed from the attacker’s site, using the following attack process:

  1. Attacker creates an iframe whose src is Page B.
  2. The code saves the current value of history.length in a variable.
  3. The code then changes the src of the iframe to Page A.
  4. Upon comparing the saved value with the present value of history.length, if it is the same, then Condition is TRUE.

The above algorithm is based on the browser’s history object displaying the behaviour listed as the second property/feature above.

Consequently, history.length will remain the same after opening Page A, and this indicates that Condition is TRUE. If Condition was FALSE, then Page A being added to the browser’s history would increase its length by one. Since an attacker can open both URLs from his page inside an iframe, and history.length is accessible from a page on the attacker’s site, this is a case of cross-site condition leakage — and hence, a violation of SOP.

After getting an indication of the value of Condition, the attacker can now plan a two-way CSRF attack (a two-way CSRF attach means that the attacker will be getting a response for the CSRF attack). Let’s have a look at a simple attack scenario.

Attack scenario

Suppose a bank application allows transfer of money from one account to another. Now, the site might use the following code for this:

If (Money_Transfer())
        Redirect("Transaction_done.php");

The above code executes the money-transfer transaction, and if the transaction succeeds, then the user’s browser is redirected to the Transaction_done page. In this case, an attacker can not only execute a CSRF attack and transfer money, but can also get feedback on whether this operation was successfully completed, using the following attack process:

  1. Attacker creates an iframe with src='Transaction_done.php' with history.length element in it.
  2. This alerts the attacker with the current value of victim’s history.length.
  3. Now, changes the src of iframe to Money_transfer.php.
  4. If the value of history.length remains the same, then the operation was successfully completed.

However, this was a simple attack scenario; besides this, the attacker can also detect the user’s authentication state, and can also access valuable intranet resources, which otherwise cannot be accessed publicly.

Cross-site user tracking

While using an iframe, an attacker has limitations: she cannot know what the victim is doing in the iframe, and also, by design, an iframe cannot communicate with its parent page. But, using XSHM, an attacker can bypass these limitations too — and in some cases, track user activities inside an iframe.

To track the victim’s activities in a page inside an iframe, an attacker builds a list of URLs that a parent page contains, or can submit. Now, whenever the victim clicks a link in the iframe, his history.length will remain the same. The URL of this link must always remain on top of the history list; here, the attacker can use location.replace to probe different URLs from the list, without inserting them to the top of the history list.

A typical attack process is as follows:

  1. The attacker creates an iframe with its src as the victim’s site, with a history.length element in it.
  2. On each load event of the iframe, the attacker remembers the current value of the victim’s history.length, and then changes the src of the iframe to a URL which the parent page can access.
  3. Performing the last two actions on all URLs the parent page can access, until the value of history.length ceases to increase lets an attacker know what link a user clicked, and when it was clicked.

An example of this is a phishing attack in which the attacker opens a legitimate site from an iframe. As the victim clicks a link to log in, the attacker is intimated about this, and opens a fake login page instead.

Cross-site URL/parameters manipulation

This is another attack vector of XSHM, through which the attacker can also enumerate previously browsed URLs. The attack process for this is quite simple:

  1. The attacker builds an array of URLs to check (let’s call it URL[]).
  2. The attacker then runs history.go(URL[x]) for each URL in the list.
  3. If a document.unload occurs, the event assures the attacker that URL[x] was visited in the current session.

The only limitation with the above process is that the attacker must set the URL[] array, containing all the URLs for which the victim’s visit is to be assured, prior to the attack.

Cross-site history manipulation (XSHM) is a new attack vector, by which the Same Origin Policy (SOP) can be compromised, and the user’s privacy can be violated. XSHM enhances CSRF by making it a two-way attack. However, the following security tips can help curb it.

Time for security

If your application uses conditional redirects, it might be vulnerable to XSHM. However, for the following code, there is no potential risk:

if (url != "")
        Response.Redirect(url);

This is because the condition if(url != "") is specific, and cannot produce TRUE or FALSE.

  1. For successful prevention of cross-site history manipulation, both the URL of the origin page from which redirection is executed, and a redirected target page, should contain a random token, as shown below:
    if ( !isAuthenticated)
            Redirect('Login.aspx?r=' + Random())</li>
  2. To prevent URL/parameters enumeration, all site URLs should contain random tokens placed inside the URL.

For gaining further information on these attacks, don’t forget to visit the resources below. We will deal with other dangerous attacks on web applications and Apache in the next article.

Always remember: Know hacking, but no hacking.

Further reading

3 COMMENTS

  1. Thanks ! LFY can start another magazine -LFY-Learn the Fbasics ! will be useful for beginners who are interested in learning FOSS

LEAVE A REPLY

Please enter your comment!
Please enter your name here