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.
Estimated severity
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.
Non-persistent XSS
The Order Detail
function retrieves order data using AJAX. The AJAX response has a Content-Type
of text/html
and the parameter cancel_order
is returned to the requester unsanitized. This leads to non-persistent XSS in the cancel_order
parameter:
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 thecancel_order
parameter is set totrue
(or some similar value, I didn’t keep logs and the function has since been disabled) and thebsorder_id
is set to a user’s pendingBuy BTC
orSell BTC
order ID, then the pending order is cancelled. This provides a CSRF attack (provided the attacker knows the value of one of victim’sbsorder_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_id
actually belongs to the user submitting acancel_order=true
request. This gives a Direct Object Reference attack that allows an attacker to cancel any user’s pendingBuy BTC
orSell BTC
order, provided the attacker knows the value of thebsorder_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 bsorder_id
’s)
Disclosure Timeline
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