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:
- Removal of weak ciphers and key exchange algorithms, along with other TLS improvements
- Fail-secure handling of NULL bytes in path names and environment variables
- Better support for compiling BEAM as a Position Independent Executable (PIE)
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.
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
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.
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 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
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!