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.
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 g1.playground.quaji.com.
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 (client.g1.playground.quaji.com).
- 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.
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.