Monday, February 7, 2011

Tricky exploit - a penetration test puzzle - Solution

This entry provides the details of an interesting exploit I had found recently. If you haven't done so, please read the introductory entry before reading on, as some of the information is not repeated.

Site Map

Before going on to describe the actual exploit, I'll analyze the various elements of the website stressing their relevant properties.

The mock-website's domain is
It contains 2 subdomains:
1. www. - the public site.
  • This section contains all the publicly available pages.
  • In the mock-site there is a search page in search.php.

2. client. - the client site.
  • This is the section requiring login. (login.php).
  • Access here is session based. The session cookie is set to the client sub-domain (
  • Upon successful log-in, a menu is shown (menu.php) with a link to the Printing system. 
  • As described in the previous entry, a click on this link causes a two step process: browser goes to printAutoLogin.php which contains the user's previously entered credentials in a form which is auto-submitted to printSystem.php which attempts to validate them.

Relevant Findings

First off search.php contains an obvious XSS vulnerability. By injecting malicious values in the query parameter we can have the page do whatever we want.

But what can we do with it?
It does not contain the session cookie because its on a different domain (www. vs client.) and an XMLHTTP request to printAutoLogin.php would also fail for the same reason: violation of the same origin policy.

    So we have to look onward.

    1.  It seems that printAutoLogin.php works on authentication-failed sessions too!

    When entering invalid credentials in the login page (login.php), a fail message is rightfully displayed. But printAutoLogin.php still returns the invalid parameters on their way to printSystem.php. Apparently the server code saves them too early.

    But there's no harm in that right? the printing system authentication would just find them equally invalid and deny access. So no harm there. Right?

    2. It seems that printAutoLogin.php does not escape the outputted credentials!

    This is basically another XSS. Malicious content can be entered at login.php, and printAutoLogin.php would echo them. This is an odd type of XSS because its not reflected, nor is it exactly stored: Its only available in the current session! Other users can't see it.

    We could in theory, use CSRF to write malicious parameters to the login page in the user's session. Then printAutoLogin.php would do whatever we want, but in doing so we run over the very details we were after. The user's credentials!

    So the hacker can basically only XSS himself. No big deal. Right? :)

    3. Did you know it's possible to have multiple cookies with the same name?!

    It's even legitamate, and supported by all modern browsers. A cookie is identified by its name, path, and domain parts. So if a second cookie is set having the same name but a different path or domain then another cookie, both will be sent along with subsequent requests.

    The order of appearance of cookies is explained in the RFC:
    If multiple cookies satisfy the criteria, they are ordered in
       the Cookie header such that those with more specific Path attributes
       precede those with less specific.

    When presented with multiple Session cookies, the server takes the first one and discards the rest. I am not sure this is ubiquitous with all server software but its what happens with the audited server, and with the mock-website server.

    The original session cookie has path /.
    In order to create a second cookie that would precede the first one, its path should be more specific. For example: /printAutoLogin.php (yes, path could be an actual file).

    Putting it all together

    With all this we can construct the full attack.

     Click image to enlarge

    Figure 1. The double XSS, back-flip exploit show down.

    0. The user has an authenticated session opened with the server. Session ID = 1111

    1. The attacker manually creates a session (ID=1337) on his own computer with malicious credentials that comprise an XSS payload (XSS Payload 2). He must then make sure the session does not invalidate by using keep-alives.

    2. The attacker attempts to initiate an XSS attack using search.php (Payload One) on the user. For example, in the form of a link in an email messagew.

    3. By clicking the link, the user's browser engages in Payload 1 that preforms:
       3.1 Set a second Session ID cookie (value 1337) to path /printAutoLogin.php. This cookie does not erase the previous one, but rather precedes it in precedence (as explained above).
       3.2 Redirect browser to printAutoLogin.php.

    4. When fetching printAutoLogin.php both cookies are sent but because the second cookie comes first, the server returns that session's credentials which are in fact XSS Payload 2 which preforms:
       4.1 Remove newly set session Cookie. Original cookie is intact.
       4.2 Using XMLHTTP request printAutoLogin.php and save the response. The document appears to be fetching itself! However, because the second cookie has been deleted, the response is the user session's and contains his credentials! (Step 5)
      4.3 Send the credentials to Attacker. (Step 6)

    See it in action

    Log-in into the system, and then ... "check this out."  :)

    I hope you enjoyed reading this as much as I writing it!
    Your comments are most welcome.


    Tricky exploit - a penetration test puzzle

    In a recent application security audit for a web-site I came across a big, blaring breach.
    while it's always fun to find a good vulnerability, it turned out to be quite tricky to actually exploit it. The trickiness was not due to good security practices but to pure (un)luck (depending on whose point of view). It seemed every angle I tried was off by just a tiny bit.

    Eventually I managed to find an interesting multiphase exploit vector, and I think it makes for some interesting tinkering/reading.  I've created a mock-up replica of the vulnerable web-site to allow for testing and analysis. After reading the introductory section about the vulnerability, you may wish to try your wit against the mock-site and find it yourself, before reading on to the detailed exploit write-up.

    The Target Site
    This was your ordinary small company site.
    It had 3 sub-systems:
    1. a public site, available to any user.
    2. a client site, requiring a login.
    3. a printing system, requiring its own login.

    After login to the client site, the user was shown a menu that contained a link to the printing system. In order to facilitate the user, the link to the printing system from the menu would try to use the previously given credentials from the client login and pass them on to the printing system for authentication. A poor man's SSO so to speak.

    The Breach
    It turned out that this "facilitating" method would pull the user credentials and post them to the printing system unencrypted via a client-side redirect!

    Initially the user supplies the login credentials to the client site (login.php).
    If successful, a menu is presented (menu.php).
    A click on the "Go to Printing" link directs the browser to an intermediate page (printAutoLogin.php) that contained the user credentials in a pre-filled form that is immediately  auto-submitted to the printing system login page (printSystem.php) which checks them for validity.

     Click image to enlarge

    Figure 1. Client side SSO. First redirect fetches user credentials and passes them to Print System.

    The breach is crucial and apparent: the URL printAutoLogin.php returns the current user's name and password in clear text! This information is of course very valuable to the attacker. The only question remaining is, how can he get it??

    Exploitation Problems
    Finding a breach is one thing. Showing a functional proof-of-concept attack exploiting it is sometimes quite another. While the breach is what the client actually pays for, it is the exploit that gets his respect and admiration. Usually getting a working exploit takes some dull, dirty work of fitting loose ends in place, but in this case it turned out to be an interesting puzzle.

    What I wanted to do was leverage an XSS vulnerability I had found in the site to get the user credentials. One way to do this would be to obtain the session cookie and use it to access the tell-tale URL impersonating the legitimate user and obtaining his credentials (assuming no IP checks are done). The cookie was set http-only which made this vector harder.

    Another option was to get the credentials on the client side (using an xmlhttprequest) and have them sent directly. This would overcome the http-only problem, and would also be much cooler...

    In practice XSS flaws were abundant. I found several around the site, but they were all just a bit off. Two were in different sub-domains, so they didn't have the session cookie set, and were prohibited from making cross-(sub)-domain xmlhttp calls. Another XSS was actually in the same sub-domain but used HTTP whereas the rest of the site was in HTTPS, so again no cookie (it was secure) and no cross-protocol calls.

    Close but no cigar. Yet.

    Playground version
    Before I continue describing the exploitation method I found, I offer you the chance to play around and find it yourself: I've recreated the relevant parts into a simplified mock-website that you can play around with.

    The website home page is:
    Valid user credentials are : Name:user123 Password:pass123

    You are welcome to stop reading and try your wit against it.
    Note that this is not an armchair pen-test riddle. You'll have to get your proxies dirty to find some relevant details that I didn't describe yet to figure it out.

    Your goal is to find and craft an XSS payload that will cause the user credentials to be sent to the attacker (an alert box with the info would do).

    Feel free to leave your comments.
    Please post only non-spoiler comments here, and the rest on the solution entry.

    The detailed exploitation is provided in a separate blog entry.