Coindrawer is a “simple cryptocoin wallet and trading platform” that allows users to store and trade Bitcoin, Litecoin, and other cryptocurrencies.
I am disclosing a non-persistent XSS vulnerability. The issue became unexploitable when Coindrawer removed the buy/sell
Order History function from their site on 26 April 2014.
Coindrawer has not yet committed to honouring this submission under its bug bounty program.
Update 27 July 2014 - Coindrawer have shut down their service and have honoured this submission under their program. See more at Coindrawer Bug Bounty finale.
Impact: Medium (XSS can perform unwanted actions in the context of the logged-in user, such as steal funds)
Difficulty: Requires a medium to high amount of user interaction (clicking malicious link, viewing iframe, etc.) and can be detected by in-browser non-persistent XSS protections such as those in Internet Explorer, Chrome, and Firefox (via Noscript). Attack is frameable due to lack of X-Frame-Options.
Order Detail function retrieves order data using AJAX. The AJAX response has a
text/html and the parameter
cancel_order is returned to the requester unsanitized. This leads to non-persistent XSS in the
There are some interesting conditions that make this attack possible:
session_token, which is usually used by Coindrawer's platform as a CSRF token, is not checked when requesting the data. Of note, if the
cancel_orderparameter is set to
true(or some similar value, I didn't keep logs and the function has since been disabled) and the
bsorder_idis set to a user's pending
Sell BTCorder ID, then the pending order is cancelled. This provides a CSRF attack (provided the attacker knows the value of one of victim's
bsorder_id's) that can be used to cancel a user's order, but it is not needed because…
- Coindrawer does not check that a given
bsorder_idactually belongs to the user submitting a
cancel_order=truerequest. This gives a Direct Object Reference attack that allows an attacker to cancel any user's pending
Sell BTCorder, provided the attacker knows the value of the
bsorder_id(or is willing to iterate over a large number of values. Values do not seem to be sequential.)
These bugs aren't terribly exciting, as knowing a
bsorder_id is difficult unless it's one of your own. However, only due to these conditions can we prepare an XSS attack that will work against any victim account, bypassing CSRF protection and the need to know of a
bsorder_id that the victim has access to (as all users have access to all
Coindrawer's actions are in bold.
- 3 April 2014 - Submission of JSEC1065 (Non-persistent XSS in cancel_order param, buy/sell function) and notification of disclosure date (1 May 2014) due to lack of confidence in Coindrawer's Bug Bounty program.
- 14 April 2014 - Mike Lucente, CTO of Coindrawer acknowledges disclosure date.
- 15 April 2014 - Discussion back and forth regarding disclosure and Coindrawer's Bug Bounty program I remind Coindrawer that they can ask for an extension to the disclosure dates if needed. No response.
- 26 April 2014 - Coindrawer resolves issue by totally removing buy/sell functionality from platform
- 1 May 2014 - Public disclosure.
I have a series of posts regarding Coindrawer:
- Coindrawer Bug Bounty experience
- JSEC1046 - Coindrawer Persistent DOM XSS Disclosure (Paycoin Feature)
- JSEC1051 - Coindrawer Payment Replay Disclosure, Create Multiple Merchant Orders
- JSEC1053 - Coindrawer Provide Arbitrary Exchange Rate Disclosure
- JSEC1065 - Coindrawer Non-persistent XSS Disclosure (Buy/sell Orders Feature, Cancel_order Param)
- Coindrawer Bug Bounty finale