分享

How Effective is ASLR on Linux Systems? | Security et alii

 astrotycoon 2015-11-23

Address Space Layout Randomization (ASLR) is an exploit mitigation technique implemented in the majority of modern operating systems. In a nutshell, the idea behind ASLR is randomizing the process’ memory space in order to prevent the attacker from finding the addresses of functions or gadgets (s)he might require to successfully complete the exploit. Since an in depth explanation of ASLR is beyond the scope of this brief blog post, if you feel like reading more about ASLR, I suggest you start with these (I,II).

The Good

Linux introduced ASLR with kernel 2.6.12 back in 2005, followed by Microsoft, who did the same thing with Vista in 2007. While Linux’s ASLR is forced on every executable, Microsoft’s implementation requires the binary to be linked with ASLR support. The aforementioned randomization affects both shared libraries and executables in order to provide a fully randomized process address space. Starting 2013, one would like to think that this mechanism is mature as well as it is widely adopted, thus increasing the overall security of the operating systems (am I being too naive?).

Linux ASLR can be configured through /proc/sys/kernel/randomize_va_space. The following values are supported:

  • 0 – No randomization. Everything is static.
  • 1 – Conservative randomization. Shared libraries, stack, mmap(), VDSO and heap are randomized.
  • 2 – Full randomization. In addition to elements listed in the previous point, memory managed through brk() is also randomized.

I don’t mean to talk about the math involved in ASLR, but a quick word is hopefully not completely uncalled for. Effectiveness of ASLR is limited by the amount of entropy assigned or available. Theoretically, a 32 bit system provides less entropy to be used with ASLR than a 64 bit one. However, other constraints apply to the amount of entropy, such as those related to memory layout. For example, in order to allow the stack to continue growing from higher memory down towards the heap, the most significant bits are usually not randomized. In some scenarios, this limits the entropy of mmap() in a 32 bit system to only 16 bits. PAX patch is available to increase this amount to 24 bits.

The Bad

Leaving the math elements aside, it’s obvious that for ASLR to be effective, all segments of a process’ memory space must be randomized. The existence of a single area in memory not randomized completely defeats the purpose of ASLR. This is so because the attacker could use that single area not randomized to locate valuable gadgets in order to build a successful exploit. This has been a recurring problem with Windows implementations, since third party software (and often Windows’ software) contained some DLLs not participating in ASLR, it was easy to build exploits leveraging those libraries. Linux kernels prior to 2.6.22 had a similar problem where VDSO (linux-vdso.so) was always located at a fixed location.

On the other hand, current Linux has its own set of problems. In spite of ASLR being forced on every process, not every memory area is randomized for all executables. The code segment (or text segment; .text) of the main binary is located at random locations only if the executable has been compiled as a Position Independent Executable (PIE). A position independent executable is compiled in such a way that can be located anywhere in memory and still execute properly without modification. This is achieved through the use of PC relative addresses instead of absolute addresses. All shared objects (.so, libraries) are compiled as PIE as it’s mandatory for them to work, thus they’re always at random memory addresses when ASLR is enabled.

Based on the above paragraph, we can assume that Linux executables not compiled as PIE are not effectively protected by ASLR, even though it might be set to 2 (Full Randomization). The attacker could leverage the .text segment, and other areas located within the main executable, such as GOT/PLT to build a successful exploit against a non-PIE executable on a system with ASLR enabled. As a result, any non-PIE executable leaves the door open to return-2-plt/GOT dereferencing and ROP attacks.

The following code is used to demonstrate that main executable is not randomized despite ASLR being enabled unless it’s compiled as PIE.

1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <stdio.h>
void* getEIP () {
return __builtin_return_address(0)-0x5;
};
int main(int argc, char** argv){
printf("EBP located at: %p\n",getEIP());
return 0;
}

Execution of the above code as non-PIE is displayed on the image below.

.text not randomized on Non-PIE executable

.text not randomized on Non-PIE executable

As can be seen, libraries are located at random addresses each time, meanwhile the .text section remains static. When compiled as a PIE, the following image shows how the address of the .text section is also randomized, and therefore unguessable for the attacker.

.text is random in PIE executables

.text is random in PIE executables

The Ugly

So far so good. Non-PIE executables do not benefit from ASLR protection, so? Linux binaries are surely compiled as PIE to make the most of the available exploit mitigations, or do they? According to some studies, the Linux flavours most used as web server are CentOS, Ubuntu Server and Debian (although I guess RedHat enterprise has some nice share as well). Based on that, I’ve compiled some statistics about the number of PIEs present in the above Linux distributions. The systems studied are:

  • Ubuntu Server 12.10 x86_64 + apache2 + mysql + php5 +sshd
  • Debian 6 x86_64 + web server + mysql + php5 + sshd
  • CentOS 6.3 x86_64 + apache2 + mysql + php5 + sshd

All of them installed with the standard options. The following results were compiled using Checksec, a nicely done script that checks for the presence of common security mechanisms such as ASLR, NX, Canaries, RELRO, etc. You can obtain Checksec here. These are the numbers:

Distro Num Binaries PIE Enabled Not PIE
Ubuntu 12.10 646 111 (17.18%) 535
Debian 6 592 61 (10.30%) 531
CentOS 6.3 1340 217 (16.19%) 1123

Surprisingly enough, the use of PIE is not widely embraced by the above Linux versions. However, network daemons are usually compiled as PIE, alleviating the problem and reducing the attack surface. Whether the reason not to enable PIE is performance (PIE binaries require an extra indirection) or not, the security implications greatly compensate for that. Quick and dirty math shows that between 82.82% and 89.7% of binaries are not effectively protected by ASLR in Linux systems.

In the same way, other protections such as stack canaries and RELRO were taken into account during this exercise and the results are both uneven and shocking. However, in order to obtain a truthful vision of the state of those security mechanisms, further work is required. For example, GCC would only include stack canaries in functions that match specific criteria; in other words, functions that GCC considers a likely target for buffer overflows. The result being that the lack of canaries in some binaries does not necessarily mean the executable is missing some mitigation mechanism, it may as well not be needed at all.

Well, so much for a Sunday evening. Any questions or corrections, use the comments!

Take care.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多