Securing Apache, part 4-Cross-site Tracking & Cross-site Manipulation
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.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.
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).
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.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
-
The first and the foremost security measure is to disable the TRACE request method (unless needed) on your web servers.
-
Moreover, Web-server vendors should have TRACE disabled in the web-server’s default “out-of-the-box” configuration.
-
Proxy servers should also be shipped with TRACE disabled in their default configurations.
-
Disable TRACE in your browser’s XmlHttpRequest object too. For this, check the support page of your browser’s vendor.
-
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:
-
Activate mod_rewrite in httpd.conf by adding this line to it:LoadModule rewrite_module modules/mod_rewrite.so
-
Add the following lines in httpd.conf to disable TRACE:RewriteEngine OnRewriteCond %{REQUEST_METHOD} ^TRACERewriteRule .* - [F]
-
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:
-
If the same URL is opened multiple times, only one entry will be made into the history list.
-
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.
-
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.
-
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:
-
Attacker creates an iframe whose src is Page B.
-
The code saves the current value of history.length in a variable.
-
The code then changes the src of the iframe to Page A.
-
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:
-
Attacker creates an iframe with src='Transaction_done.php' with history.length element in it.
-
This alerts the attacker with the current value of victim’s history.length.
-
Now, changes the src of iframe to Money_transfer.php.
-
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:
-
The attacker creates an iframe with its src as the victim’s site, with a history.length element in it.
-
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.
-
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:
-
The attacker builds an array of URLs to check (let’s call it URL[]).
-
The attacker then runs history.go(URL[x]) for each URL in the list.
-
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.
-
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>
-
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
Linuxforu
Comments
Post a Comment