0x00 0ctf2019-Wallbreaker Easy
在刚刚结束的0ctf中有一个Web题,提供了webshell,但是禁用了执行命令的函数。在查询资料的时候知道了可以通过LD_PRELOAD
绕过disbale_functions
的方法。学到的东西在这里记录一下。
0x01 Wallbreaker Easy Writeup
首先记录一下这道题的解题过程。
index.php
1 |
|
index.php就是一句话木马,密码是backdoor
。提示我们用Imagick
插件绕过disable_functions
,执行/readflag
来获得flag。并给出了open basedir
。
首先查看一下disable_functions
。payload:backdoor=echo ini_get('disable_functions');
除了默认设置禁用的pcntl的一系列函数还禁用了system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,mail
。
一开始去找了Imagick
插件的漏洞,但都在当前版本中被修复了。之后看到了LD_PRELOAD
利用mail()
函数绕过disable_functions
的方法。和Imagick
结合,成功拿到了flag。
0x02 Sendmail+LD_PRELOAD绕过disable_functions
1 | 在 UNIX 的动态链接库的世界中,LD_PRELOAD 是一个有趣的环境变量,它可以影响程序运行时的链接,它允许你定义在程序运行前优先加载的动态链接库。 |
当程序运行时需要调用系统共享对象中的函数时,我们可以通过设置LD_PRELOAD
来优先加载我们编写的恶意代码来劫持原本系统共享对象的代码。
攻击过程:
1、生成含有恶意代码的动态链接程序。
2、运用putenv
来设置LD_PRELOAD
,优先调用我们编写的程序。
3、通过webshell触发函数。
很多文章以sendmail为例子。利用readelf -Ws /usr/sbin/sendmail
查看其调用的库函数,从中选择了geteuid()
函数来劫持。
1 |
|
程序运行,共享库的geteuid()
被调用时,通过system()
执行命令。
在尽量和服务器相同的环境中将它编译为一个共享对象。
gcc -shared -fPIC exp.c -o exp.so
将.so
文件传输到服务器中,运用php代码设置为LD_PRELOAD
1 | putenv("LD_PRELOAD=/var/www/exp.so"); |
此时在/var/www/html/目录下就会产生test.txt。
因为利用了sendmail调用geteuid()
,进行了劫持,所以没有安装sendmail时无法使用这个函数。
在这道题中,并没有sendmail,也就无法劫持getuid()函数。
0x03 C 语言扩展修饰符 attribute((constructor))
1 | GNU C 的一大特色就是__attribute__ 机制。__attribute__ 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。 |
如果我们在我们的函数之前采用这个修饰符,那么程序在加载系统共享对象的时候会优先执行我们的函数,这样就可以不用对特定的函数进行劫持,直接绕过disable_functions
。
修改后的payload:
1 |
|
同时上传一个doc文件,用Imagick加载。
因为没有了特定函数劫持的限制,只要我们执行mail函数,不管有没有安装sendmail都可以直接绕过disable_functions
。
参考文章
PHP disable_functions Bypass 的方法探究
无需sendmail:巧用LD_PRELOAD突破disable_functions
bypass_disablefunc_via_LD_PRELOAD/bypass_disablefunc.c