Caputchin
理解 Caputchin

探测

Proof of work 证明了 耗费 了努力。它不证明 什么 耗费了它。一个拥有一群真实浏览器的执着攻击者,可以廉价地磨穿那些谜题。探测是那个堵上这个缺口的第二层:它证明这份工作发生在一个货真价实的浏览器里。

它如何运作

在每个请求上,Caputchin 生成一个全新的、一次性的 JavaScript 程序,并在访客的浏览器里跑它。这个程序运转只有真实浏览器才有的机件,并把它观察到的回报上来:

  • 浏览器 API 探针,检查货真价实的浏览器功能存在且行为正确。
  • 位运算整数操作的 计算链
  • DOM 算术,它构建元素的树、读布局引擎为它们计算的值,再把它们拆掉。

诀窍是一种不对称:一个真实的渲染引擎几乎不费力就产出正确答案,而一个 headless 或脚本化的运行时把这些操作打桩、错误地实现它们、或为速度跳过它们。这种不匹配把访客出卖了。

Content-Security-Policy

因为这个程序在访客的浏览器里跑 eval,嵌入你组件的那个页面必须在它的 script-src Content-Security-Policy 里允许 'unsafe-eval'。这个没有回退:如果 'unsafe-eval' 被挡掉,这个程序跑不了,验证就失败。如果你的策略无法允许它,就在密钥的 安全 页上把探测关掉,那会以失去自动化浏览器检测为代价移除这个要求(proof of work 和任何必需的游戏照样会跑)。完整的宿主页策略见 游戏沙箱

为什么它和 proof of work 配对

这两层互相罩住对方的盲点。单凭 proof of work 可以被真实浏览器廉价地挖;单凭探测可以被一个从不真做这份工作的脚本伪造。两者合在一起,在两条独立的轴上抬高成本:proof of work 证明努力,探测证明环境。

混淆

因为这个程序交付给访客,一个有动机的攻击者可以研究它并试图预先算出答案。为了让那更难,这个程序被混淆。一个密钥的 安全 页暴露一个 混淆级别:把它调高让程序更难被逆向,代价是更多的服务端 CPU。同样这些信号支撑 阻止自动化浏览器 选项,它直接拒绝检测到的 headless 和 WebDriver 客户端。

一个诚实的局限

探测不是万无一失的。隐身浏览器会打补丁修掉它寻找的那些破绽,而这些检查本身也指出它们能被攻破。它是几层里的一层,当和 proof of work 以及一个密钥其余的 安全 设置叠在一起时最强。

本页内容