JS 防护流派全景解析:四种技术路线与它们的对抗成本

JS 防护流派全景解析:四种技术路线与它们的对抗成本

同样是「前端 JS 防护」,瑞数、同盾、极验、Cloudflare 走的是完全不同的路。
把它们的原理摊开对比,会发现真正决定逆向成本的,往往不是算法有多复杂,而是「防护目标」定在哪里。


引言:为什么会有「流派」

前端防护的本质是在做一件事:在客户端不可信的前提下,尽量判断请求是不是人发出来的。

但「判断」这件事可以有很多切入点:

  • 判断发起请求的代码对不对(执行流校验)
  • 判断发起请求的环境像不像真人设备(设备指纹)
  • 判断发起请求的动作像不像真人操作(行为轨迹)
  • 判断这次访问的整体信誉够不够(边缘挑战)

四个切入点,长出了四类产品,也对应四种完全不同的对抗难度。很多人把它们的难度混为一谈,实际上差距非常大。


流派一:动态执行流(瑞数 BotGate / 部分顶象)

原理

这是国内最「硬核」的一路。核心思路不是校验请求参数,而是校验执行请求的那段代码本身。

1~5 代:动态混淆 + eval

每次页面加载时,服务端下发一段 JS,其中:

  • 字符字典顺序每次随机(同一个函数,今天叫 a.b(c),明天叫 x.y(z))
  • 变量名、函数名全是随机生成的短标识符
  • 控制流被打散重排,插入大量无效分支
  • 关键逻辑(参数生成、Cookie 写入)被拆成碎片,运行时拼接

每次加载都不一样,意味着你无法通过「找特征码」来定位逻辑——上一次抓到的函数结构,下一次就找不到了。所有碎片最终被 eval 或 Function 还原执行,产出签名参数和 Cookie。

6 代 + VMP 版:自定义字节码

再往上走一层,不再给你可读的 JS。原始逻辑被编译成自定义 opcode 字节码,页面上只有一段解释器代码,运行时把字节码喂给解释器执行。这时候静态分析基本失效——你面对的不是 JS,是一门只有它自己认识的小语言。

这一派的强度在哪

它防的不是「你会不会抓包」,而是「你能不能稳定复现出一模一样的参数」。

  • 静态分析:基本无效(尤其 VMP 版)
  • 动态调试:可以,但要对抗反调试(debugger 陷阱、toString 校验、时间差检测、格式化检测)
  • 稳定性:极高。因为「代码不可预测」+「请求一次一密」,任何硬编码方案都会在换版本时失效

识别特征

  • 页面首屏 HTML 里就带着一段极长的混淆 JS
  • 首次访问返回 412 / 521 之类的状态码,并 Set-Cookie 一个看起来随机的短 Cookie
  • 同一 URL 连续刷新几次,返回的 JS 内容完全不同
  • 全局搜索能看到 eval、Function、大数组下标访问密集

顺带一提:这一派的「强度」在纯混淆类里是最高的,但放到整个谱系里,它仍然只挡静态分析这一件事——它不判断环境像不像人,也不判断行为像不像人。所以单靠它,在有完整浏览器环境的情况下是可以被绕过的,只是成本高。


流派二:设备指纹 + 风控打分(同盾、数美、顶象、部分腾讯)

原理

这一路的哲学完全不同:不硬拦,只打分。

页面加载时注入一段采集脚本,尽可能多地收集环境特征:

维度 采集内容
图形栈 Canvas 渲染哈希、WebGL 的 vendor/renderer/参数、图像解码差异
音频栈 AudioContext 的波形指纹
字体 已安装字体列表、字体度量差异
时区/语言 时区偏移、语言列表、Date 精度
硬件 CPU 核数、内存容量、屏幕分辨率/色深、设备像素比
传感器 陀螺仪、加速度计是否存在及数值
网络 出口 IP、IP 归属、代理特征
行为 鼠标轨迹、键盘节奏、页面停留、滚动模式

这些特征组合成一个 deviceId(或 token),随业务请求一起上送。后端用模型打分,输出一个风险等级:

  • 高风险 → 直接拒绝 / 强制验证码
  • 中风险 → 降权、限频、加二次校验
  • 低风险 → 放行

对抗难点在哪

关键点:难点不在「解算法」,而在「环境一致性」。

它的加密算法通常并不复杂(甚至不加密,就是明文 JSON + 简单签名),你很快就能把 deviceId 的生成逻辑扒出来。但问题是——

你补出来的环境,只要有一个维度跟真实设备不一致,分数就上不去。

比如:Canvas 哈希对不上、WebGL 拿不到真实 GPU 参数、navigator 属性是补出来的静态值、时区跟着服务器而不是用户、鼠标轨迹是匀速直线。任何一项露馅,后端不一定立刻拒绝,而是把你丢进「可疑池」——表现就是请求能通,但一直弹验证码,或者数据被降级返回。

这种「不明确报错、只默默降权」的设计,是这一派最难受的地方:你很难判断自己到底是哪里错了。

识别特征

  • 页面里有采集 Canvas / WebGL / AudioContext 的代码
  • 请求头或参数里带一个长字符串 token,且每次会话固定、换环境会变
  • 同一个接口,换 IP / 换浏览器就要求验证码
  • 返回内容「看起来正常但字段不全」,或频繁触发滑块

流派三:行为验证码流(极验、网易易盾、腾讯天御)

原理

这一派把判断点放在具体动作上,形态是滑块、点选、无感验证。

以滑块为例,流程是:

  1. 前端向服务端申请挑战,拿到背景图、缺口位置、以及一个会话 ID
  2. 用户拖动滑块,前端采集全过程数据:每个采样点的坐标、时间戳、按下/抬起时刻、加速度变化
  3. 这些轨迹数据被加密成 w、validate 之类的参数,连同会话 ID 一起上送
  4. 后端用轨迹模型判定:是不是机器生成的

模型看的不是「终点对不对」,而是过程像不像人:

  • 起步有加速段,中段匀速,末段减速微调(真人特征)
  • 有轻微的回拉、抖动、Y 轴漂移
  • 采样间隔不均匀
  • 总耗时在合理区间(太快 = 脚本,太慢 = 可疑)

对抗难点在哪

逆向通常是「轨迹模拟」,而不是纯算法还原。

算法层面:w 参数的加密逻辑经常是 RSA / AES 组合,扒出来不算特别难,但每次版本升级都可能变。

真正的难点是轨迹的真实性。用贝塞尔曲线 + 抖动噪声能过一部分老版本,但新版模型会检测:

  • 轨迹点的采样率是否与真实事件循环一致
  • 坐标是否来自真实 mousemove(而不是合成事件)
  • 多设备下的轨迹分布是否落在合理人群范围内

外加设备指纹交叉校验(极验自己也做指纹),所以纯算法 + 假轨迹这条路越来越窄。

识别特征

  • 页面出现明显的验证码组件(gt.js、yidun、tcaptcha 之类)
  • 请求里带 w、gt、challenge、validate 等参数
  • 无感模式下:正常访问无感,一旦被判定可疑就弹滑块

流派四:边缘挑战流(Cloudflare、Akamai、部分 CDN WAF)

原理

这一派在网络边缘做判断,业务服务器根本不参与。核心是三个手段叠加:

1. JS Challenge

首次访问时,边缘节点不返回真实内容,而是返回一个中间页,里面是一段 JS。这段 JS 在浏览器里做几件事:

  • 跑一段计算(早期是简单的数学题,现在有更复杂的 PoW)
  • 采集少量环境特征
  • 把结果连同边缘节点下发的 token 一起提交
  • 校验通过后,边缘节点下发 cf_clearance Cookie

之后带着这个 Cookie 的请求才被放行到源站。

2. Turnstile(无感验证)

Cloudflare 的托管挑战方案。不弹可见验证码,而是后台静默跑一段检测(环境 + 行为 + 信誉),给出通过/不通过。对真人几乎无感,对自动化环境则大概率卡住。

3. IP 信誉

这是最容易被忽略、也最容易被低估的一层。Cloudflare 手里有全网级别的流量数据:

  • 这个 IP 段历史上有没有大量异常请求
  • 这个 IP 是不是机房/云厂商/代理出口
  • 这个 ASN 的整体信誉
  • TLS 指纹(JA3/JA4)、HTTP/2 指纹是否与声称的浏览器一致

哪怕你的 JS 全跑通了、Cookie 也拿到了,一个脏 IP 依然会让你反复被挑战。

对抗难点在哪

难在它是多层联动的:

  • JS 层:要能跑通挑战,拿到有效 Cookie
  • 传输层:TLS 指纹要对得上(这是很多人栽的地方——用 requests 直连,TLS 指纹一眼假)
  • 网络层:IP 信誉要干净
  • 时间层:Cookie 有有效期,且与 IP/UA 绑定,换环境就失效

单点突破没用,要四个维度同时对齐。

识别特征

  • 返回 403 / 503,页面标题是「Just a moment...」或「Attention Required」
  • 响应里有 cf-ray、server: cloudflare 头
  • 需要 cf_clearance Cookie

横向对比

流派 判断对象 核心技术 静态分析难度 环境要求 综合强度 典型产品
动态执行流 代码本身 动态混淆 / eval / VMP 字节码 极高 中(需完整 JS 执行环境) 高 瑞数 BotGate、顶象
设备指纹风控 设备环境 多维特征采集 + 模型打分 低(算法易扒) 极高(环境一致性) 高 同盾、数美、顶象
行为验证码 操作动作 轨迹采集 + 行为模型 中 高(需真实事件链) 中高 极验、易盾、天御
边缘挑战 整体信誉 JS Challenge + 指纹 + IP 信誉 中 极高(四层联动) 最高 Cloudflare、Akamai

一句话总结各自防的是什么

  • 动态执行流:防「静态读代码」——强度最低,但门槛最直观
  • 设备指纹:防「假环境」——算法简单,环境最难
  • 行为验证码:防「假操作」——轨迹真实性是核心
  • 边缘挑战:防「不像人的整体流量」——维度最多,联动最紧

现实:大厂从来不是只用一种

单一流派都有明显短板,所以真实部署基本是混着上:

典型组合 A:瑞数 + 风控 SDK

瑞数负责让参数无法静态复现,风控 SDK 负责判断环境真伪。你就算把瑞数的参数跑出来了,环境分不够照样被降权。

典型组合 B:Cloudflare + 极验

Cloudflare 在边缘先筛一遍(挡掉大部分低成本流量和脏 IP),剩下的进源站再过极验(挡掉环境勉强过关但行为可疑的)。两层筛子,成本递增。

典型组合 C:指纹 + 无感验证 + 动态签名

首访静默采集指纹,可疑则触发无感验证,全流程参数由动态签名保护。用户几乎无感,但自动化成本极高。

这类组合的共同逻辑是:用低成本手段过滤掉 90% 的流量,把高成本手段留给剩下的 10%。


如果你是防守方:怎么选

  • 只是想挡掉无脑爬虫和采集脚本 → 边缘 WAF + 基础频率限制,成本最低,收益最快
  • 核心数据资产,且已被针对性研究 → 动态执行流(提高单次复现成本)+ 设备指纹(提高环境伪造成本)
  • 涉及账号、交易、注册等敏感动作 → 行为验证码 + 设备指纹,重点在「动作真实性」而非「访问频率」
  • 面向公网、流量大、来源杂 → 边缘挑战优先,先把脏流量挡在源站之外

一个常被忽略的点:分级防护比堆强度更有效。 全站上最重的方案,用户体验和运维成本都会失控;按接口价值分层,才是可持续的做法。


结语

把四个流派摆在一起看,会发现一个规律:

防护强度不取决于算法多复杂,而取决于它要求对手同时满足多少个独立条件。

动态执行流要求「代码可复现」,一个条件,所以能挡静态分析,但挡不住执行。
设备指纹要求「环境处处一致」,几十个条件,所以算法好扒、环境难补。
行为验证码要求「动作符合人类分布」,一个连续性条件,所以能挡脚本、难挡真人代理。
边缘挑战要求「代码 + 传输 + 网络 + 时间四层对齐」,四类条件叠加,所以综合最强。

理解了这条规律,再看任何新的防护产品,判断它属于哪一派、要求你满足哪些条件,会比记具体算法有用得多。

posted @ 2026-11-08 01:18  Johnjincaaa  阅读(5)  评论(0)    收藏  举报