双写绕过
- 此题是2024鹏城杯 ezupload这道题
第一阶段
题目是很常见的httpd文件,出题人只写了GET和POST两种请求。可以看都GET请求带参数(也就是有?),POST请求,或者访问的文件具有用户读权限、组执行权限或其他用户执行权限中的任意一个权限,v2 被设置为 1。此时会进入bbbb函数
而serve_file函数其实就是进行一个文件读然后写到输出中,但是想要直接访问flag文件是不行的,因为看到dockerfile中flag具有用户读权限,所以进不到serve_file函数中去
COPY ./flag/flag /
RUN chown root:root /flag
RUN chmod 744 /flag
相关系统调用
pipe
pipe 系统调用用于创建一个单向数据通道,通过文件描述符实现进程间通信。pipe 的语法如下:
#include <unistd.h>
int pipe(int pipefd[2]);
参数:pipefd 是一个包含两个整数的数组,pipefd[0] 是读取端,pipefd[1] 是写入端。
向 pipe[1] 写入数据,pipe[0] 就会接收到数据。这是管道在进程间通信中的核心原理。
管道的工作机制:
单向数据流:管道(pipe)创建后会提供两个文件描述符,pipe[0] 和 pipe[1]。
pipe[0] 是读取端。
pipe[1] 是写入端。
数据传递:向 pipe[1] 写入的数据会自动流向 pipe[0],这样读取端的进程就可以获取写入端写入的数据。数据在进程之间传递时不会经过磁盘,而是直接在内存中传输,这样通信速度更快。
dup2
dup2 是一个系统调用,用于将一个文件描述符复制到另一个文件描述符。它通常用于重定向标准输入、输出和错误。其定义如下:
#include <unistd.h>
int dup2(int oldfd, int newfd);
oldfd:要复制的文件描述符。newfd:要将 oldfd 复制到的文件描述符。如果 newfd 已经打开,它会首先被关闭,然后指向与 oldfd 相同的文件。
dup2 常用于将标准输入、标准输出或标准错误重定向到一个文件或管道的文件描述符,以便控制输出或输入的来源。例如,将标准输出重定向到一个文件。比如dup2(file_fd, STDOUT_FILENO)
第二阶段
子进程就是根据file去调用execl函数
父进程就是把content通过管道写入到子进程中(注意子进程调用了dup2,把标准输入输出重定向到管道)
同时题目中给了个cgibin.cgi文件,这个bbbb函数应该就是为cgibin.cgi服务的,我认为漏洞可能也在cgibin.cgi这个二进制文件中。但是发现httpd中filename = handle_url(s, “../”, byte_501A);中有个漏洞。
看似好像把"../“这个字符串给移除了,但是这里的移除可以绕过。利用”….//“这个形式(也就是双写绕过),题目移除”../“后刚好还剩下”../",仍然可以进行目录穿越
但是注意我们无法通过serve_file直接读flag,因为flag具有读权限。但是我们已经可以目录穿越,同时bbbb函数中可以进行任意文件执行,那么可以直接执行/bin/sh,然后content内容为cat flag\n,那么就可以得到flag
第三阶段
主要是要留意一些小问题:
第一个是content中的cat flag记得要带上\n,因为在httpd中经常以\n作为recv的终止符,不加上可能就一直卡在那里了
第二个是cat flag后需要再次访问页面才看得到flag,不知道是什么原因,这个感觉类似再次访问页面会刷新输出缓冲区一样
- exp
data=requests.post(url=b"http://192.168.18.27:8080/....//....//bin/sh", data=b"cat /flag\n\n\n")
- 最后可以在web页面看到flag(这里是用docker复现)