Erlang/OTP 21

Posted 2018-06-23 08:36:19.000000

It’s that time of the year: there is a new major release of Erlang/OTP. Much has been said already about the performance enhancements, but as usual I am mostly interested in the security contents. And this release does not disappoint:

In this post I will look at each of these items in more detail. For the full contents of the release, check the release notes here.

‘:ssl’ application

The default cipher suites offered by TLS clients and servers using the :ssl application no longer include 3DES ciphers and RSA key exchange. This is in line with current best-practices, as described here and here. Secure renegotiation is now enabled by default, and compatibility with SSLv2 clients has been dropped.

On a related note, users of Plug will want to check out the latest 1.6 version, which adds support for hardened server configuration profiles, independent of the Erlang/OTP version used. TLS configuration is now done through Plug.SSL, and a predefined profile can be selected through the :cipher_suite parameter.

Back to Erlang/OTP 21. Improvements have been made to the TLS adapter for the Erlang distribution protocol. Hopefully this will make it easier to add more flexibility in the future: I would still like to see support for PSK authentication as an alternative for using certificates.

Finally, support for DTLS is now official, which opens up new possibilities for Erlang and Elixir in the IoT space, for example using the CoAP protocol.

NULL bytes

When coding in C, one has to be weary of issues related to NULL-terminated strings: there are quite a few things that can go wrong when unexpected NULL characters show up in user input, or when they go missing. Erlang’s charlist type and Elixir’s UTF-8 binaries do not use NULL termination, but interfaces with the outside world often do.

The fixes in this release are a result of one of Griffin Byatt’s Plug vulnerabilities. The root cause of the second issue is the fact that the Erlang standard library did not disallow NULL characters in pathnames. The underlying OS system calls do look for NULL termination, so any user-provided NULL characters would be treated as the end of the pathname by the OS. This meant that the pathname “test.txt\x00.js” would refer to a .txt file on disk, while being treated as a JavaScript file by Erlang/Elixir.

The Plug issue was resolved by looking for NULL bytes in the request URI, but other applications could potentially be affected by the behaviour of the Erlang standard library. The fact that NULL characters now cause these functions to fail provides a safety net for such applications. In general, though, it is always better to do input validation close to the trust boundary of an application. And keep in mind that 3rd party libraries that wrap native code, e.g. using NIFs or Ports, might suffer from similar issues.

ASLR with HiPE on a PIE BEAM

Address Space Layout Randomization, or ASLR, is a commonly used technique to mitigate the impact of security vulnerabilities in applications. The goal is to make it harder for an attacker to exploit a memory corruption bug to achieve remote code execution. ASLR has been available on Linux for more than 15 years, but even today, not all binary executables benefit from it: the binary needs to be compiled as a Position Independent Executable (PIE).

Last time I checked, most binary distributions of Erlang/OTP did not ship the BEAM executable as a PIE. But when building from source, it is enough to set CFLAGS=-fpie and LDFLAGS="-pie -z now" before running ./configure. I would encourage anyone to run production applications with ASLR enabled. Check this article for more information, including how to check whether a process (such as ‘beam.smp’) is using a PIE.

All this used to come with one catch: High-Performance Erlang (HiPE) was not supported on a PIE-compiled BEAM. In Erlang/OTP 21, HiPE is now supported in combination with PIE. I’m not sure anyone was consciously running Erlang in production without ASLR just because of HiPE, but it’s nice to know that this hurdle has now been removed. So no more excuses: go compile Erlang/OTP 21 with ASLR support now!