MENU

LD_PRELOAD与绕过PHP禁用函数和提权

January 22, 2022 • Read: 905 • 常山阅读设置

LD_PRELOAD与绕过PHP禁用函数和提权

前言

前些天晚上看https://xxe.one/index.php?threads/146这个文章,其中的第17个问题引起了我的注意,之前在某次的攻防中遇到过大佬绕过宝塔的PHP函数禁用,当时大概看了一下报告,觉得是一种我之前没有学到的bypass,然后大概了解了一下,没有仔细深究。没想到半年过去了,这第17个问题勾起了我的回忆,于是打算再仔细看看。

本文主要原理参考于Dynamic linker tricks: Using LD_PRELOAD to cheat, inject features and investigate programs

LD_PRELOAD

LD_PRELOAD是Linux系统中的可选环境变量,该环境变量可以控制动态链接库的加载位置。在任何操作系统中,几乎所有代码都依赖库,库可以说是现代操作系统的基石之一,库同时又分为静态链接库和动态链接库,在代码进行编译时链接到代码中的库成为静态链接库,相反,编译时未链接到代码中,每次执行时才进行加载的是动态链接库,相比较而言,动态链接库具有更加灵活,内存占用少,更易维护等优点。

在Linux中,动态链接库按照如下顺序查找执行:

  1. 编译时指定的动态链接库路径
  2. 环境变量LD_PRELOAD
  3. 环境变量LD_LIBRARY_PATH
  4. /etc/ld.so.cache目录
  5. /lib目录
  6. /usr/lib目录

从上面动态链接库加载的顺序来看,LD_PRELOAD的加载级别是相当高的,所以可以通过使用LD_PRELOAD来劫持动态链接库,以实现绕过一些限制。

之所以使用LD_PRELOAD而不是LD_LIBRARY_PATH,是因为LD_LIBRARY_PATH需要修改环境变量

Example

就使用参考文章中的例子,简单易懂

rand.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
  srand(time(NULL));
  int i = 10;
  while(i--) printf("%d\n",rand()%100);
  return 0;
}

使用gcc rand.c -o rand编译,从代码不难看出这是一个输出10个随机数的程序,结果不言而喻。

接着编译另一个文件:

unrand.c

int rand(){
    return 1;
}

使用gcc -shared-fPIC unrand.c -o unrand.so将该文件编译为动态链接库

执行命令LD_PRELOAD=$PWD/unrand.so ./rand,可以观察到输出为10个1,而非随机数

通过ldd randLD_PRELOAD=$PWD/unrand.so ldd rand可以观察到,第二条命令加载了一个新的动态链接库,在Linux中,rand()函数在libc.so.6这个动态链接库中,但是LD_PRELAOD的优先级更高,所以rand程序优先加载了我的动态链接库,使用了我自定义的rand()函数

所以使得通过加载LD_PRELOAD来实现某些Bypass成为可能。

绕过PHP禁用函数

绕过PHP禁用函数的思路来自于yangyangwithgnu大佬的bypass disable_functions via LD_PRELOAD,详情可阅读上述仓库中的README

提权

在阅读bypass disable_functions via LD_PRELOAD时,我在该仓库中发现了一个issues,该页面的最后有人贴出了一个利用LD_PRELOAD来提权的操作,详见Sudo (LD_PRELOAD) (Linux Privilege Escalation)

Last Modified: May 7, 2022
Archives QR Code Tip
QR Code for this page
Tipping QR Code
Leave a Comment

4 Comments
  1. 兄弟是干什么行业的?可有合作的意向?

    1. @爱玩的大叔

  2. 代码看不懂还是来踩踩
    留下脚印!

    1. @一泽圆圆嘿嘿?