长亭-运营仙子🧚‍♀️。
发布于 IP属地北京

长亭产研发对于雷池 WAF 的人机识别设计思考

摘要 人机识别是现代网站应用安全的重要保障手段之一,通过区分用户中的人类与机器人,将应用资源优先提供给人类用户,不仅能够优化资源配置,还能保护应用避免恶意机器人的危害。雷池 WAF(简称:雷池) 作为网站应用防火墙,识别出用户是人类还是机器人,对防护效果有很大帮助。雷池从自身定位出发,选了非侵入式的、在线的、渐进式的、问题解答式的人机识别方案。非侵入式表示雷池不会侵入业务,不需要业务进行任何功能的引入或集成;在线的表示雷池的人机识别需要用户能够访问在线服务(针对离线用户需要配合离线人机验证服务,这需要用户单独部署);渐进式表示雷池会分为两个阶段进行人机验证,第一个阶段认为当前用户为人类用户则通过,如果疑似机器人则进行第二阶段的问题解答;问题解答表示雷池会给用户“出一道题”,答对了就是人类,错误就是机器人。并且在人类用户识别的问题解答上,采用了一种创新的旋转图片拼接问题方式。

人机识别简述

在 2000 年,卡耐基大学的 Luis von Ahn 和 Manuel Blum 创建了一个工具,用来保护网站避免被机器人和垃圾邮件骚扰,起名叫做 Completely Automated Public Turing Test To Tell Computers and Humans Apart 简称 CAPTCHA。最初 CAPTCHA 的功能是生成一张图片,包含几个很扭曲的随机字符(如图),用户在访问网站前,需要识别并输入这几个字母。

这在当时是一个图灵问题,因为机器人能力有限,无法识别图片,能够识别出字符的就代表访问者是人类用户。 CAPTCHA 技术出现后,von Ahn 创建了 reCAPTCHA 项目用于推广该方案。但在 CAPTCHA 的实践中,有的对文字做了简单的模糊,有的直接使用未加工文字,有的则需要进行简单的计算,比如 “ 1 + 1 = ?”,这些问题过于简单,很容易被机器人破解。而 reCAPTCHA 项目则坚持原始的扭曲文字方案,并且会在图片上叠加混淆图层来提高识别难度。2009 年谷歌获得了 reCAPTCHA项目(谷歌利用该项目,识别了大量图片内容,间接积累了日后用于深度学习的训练数据),下面是谷歌对于 reCAPTCHA 的定义

What is reCAPTCHA?
reCAPTCHA is a free service from Google that helps protect websites from spam and abuse. A “CAPTCHA” is a turing test to tell human and bots apart. It is easy for humans to solve, but hard for “bots” and other malicious software to figure out. By adding reCAPTCHA to a site, you can block automated software while helping your welcome users to enter with ease.

其本质是一个图灵测试过程,核心是构造一个问题,具有明显的不对称算力要求:对人很简单,对机器人很难。在谷歌的加持下,reCAPTCHA 项目的市占率持续超过 50%,很大程度上,它的发展影响着 CAPTCHA 技术的发展。目前,reCAPTCHA 发展到了 v3 版本:

版本 发布时间 识别方法 用户体验
v1 2009 年 图片识别 按要求识别图片内容
v2 2014 年 勾选框
v3 2018 年 隐形分析 (无感)

经过 3 次大升级,reCAPTCHA 已经非常成熟,v3 版本已经做到用户无感知识别。不过 reCAPTCHA 并非无懈可击,已经有产品可以破解人机识别。其实不止 reCAPTCHA,其它主要人机识别服务亦无幸免(如图)。

那么如何防止人机识别被破解,最终又回到了它的本质:图灵问题。reCAPTCHA 在使用过程还有一个问题,必须 侵入式集成,网络应用必须引入 reCAPTCHA 的 sdk 才能使用。这对于要求无感的服务集成是非常致命的。

雷池 Waf 的人机识别

雷池是网络应用防火墙(Waf),需要预防各种网络威胁,机器人访问无论是否携带恶意代码,对 web 应用都是一种潜在威胁,识别出流量中的机器人用户也是 waf 的必备功能之一。雷池的人机识别设计方案,按照的功能的先后顺序,逐个分析解决下面的问题:

  1. 集成方式
  2. 验证方式
  3. 误判方案
  4. 图灵问题
集成方式

最佳实践中 waf 应该是让 web 应用完全无感,这样可以提供最好的兼容性,只要是符合 HTTP 协议的 web 应用就都可以代理并实施保护。根据是否侵入 web 应用,可以将集成方式分为 侵入式非侵入式 两种,下面列出了两种方式的部分差别

侵入式 非侵入
集成方法 网页中添加 sdk.js 拦截请求验证
是否需要修改 web 应用
是否可以保护 API
是否修改 cookie

通过对比,雷池 waf 在选择了便于与 web 应用集成的 非侵入式 集成方案。主要原因一个是不用在 web 应用中集成 sdk,另一个则是可以保护 API。在网页中集成 sdk.js 虽然可以做到无感识别,但它只能在网页中生效,如果机器人跳过网页,直接访问 API 接口,像谷歌的 reCAPTCHA 是无法防护的。

对 API 的防护会导致一个副作用,在 SPA(单页面应用)下,用户会在一个页面上保持不变,不刷新页面,只调用 API 接口。如果这是 API 接口被人机识别功能拦截,页面上会出现 “接口异常” 的报错,但用户无法及时得知具体原因。

确定了非侵入集成方式后,下一步是如何对请求进行验证。因为 waf 在网络中的位置是在 web 应用前面的,所以非侵入方式下,人机验证过程需要拦截请求进行验证。如果验证结果通过,则放行,不通过则拦截。

验证方式

人机验证是的流程越严格,结果就越准确,但用户体验也越糟糕。为了区分人类与机器人,可以从 3 个方面入手:

人类 机器人 检查方法 关联请求数量
运行环境不同 浏览器 脚本、模拟环境、无头浏览器 JavaScript 检查器 一次
能力不同 图像识别能力强 图像识别能力有限 图片识别问题 一次
行为特征不同 访问速度慢,不符合随机性 访问速度快,符合随机性 流量特征统计 多次
  1. 运行环境

    检查客户端是否具有一个普通浏览器的特征,例如客户端是否能够创建一个 iframe ,然后通过 postMessage 与 iframe 通信

  2. 用户能力

    是否能解答一个图灵问题,比如听一段录音问题,能解答的是人类用户,不能解答就是机器人用户

  3. 行为特征

    人类用户访问网站有目的性,访问路径(页面的跳转路径)也就具有规律性,而机器人则是漫无目的的爬数据,符合离散的均匀分布

机器人爬虫识别与防护(反爬)的思路基本上围绕这三个方面展开,特定业务场景下会加强特定方向的检查能力。其中 行为特征 与业务场景关联度非常高,比如电商网站,我想让自己的价格保密,但又想知道竞争对手的产品价格是多少?而竞争对手也是这么想的。这样,电商网站之间就会围绕产品 SKU 信息进行爬取和反爬竞争。

雷池 waf 的目标是通用网站服务,因此不会添加特定的业务流量检查模型。所以雷池 waf 的验证方式更加强调 运行环境用户能力。为了兼顾准确率和用户体验,雷池采用了二段式验证的方法:先进行 运行环境 检测,如果为发现一点,则通过验证;如果疑似机器人(可能是误判,也可能是特殊浏览器,也可能是机器人),则需要再进行一次 用户能力 检测,通过一个图灵问题来判断当前是为为机器人。因为需要提供图灵问题,所以需要一个单独的人机验证服务来提供素材以及验证答案。而一般情况下 waf 只能代理业务服务,自身不能包含服务(因为会占用端口,暴露攻击面),这也是雷池 Waf 选择了云服务来提供人机验证服务的原因。

将上述的设计思路总结为流程,人机验证一共分为以下几个阶段:

阶段 动作 状态 结果
请求 是否包含人机 cookie 包含
不包含
通过验证,结束
引导去人机页面
进入人机页面 检查执行环境 人类用户置信度高
疑似机器人
通过验证,设置 cookie
发起图灵问题挑战
图片识别 识别图片内容 识别成功
识别失败
通过验证,设置 cookie
拦截请求

完整人机验证流程

效果演示

下面来实际演示雷池人机验证效果,并做功能的分步解释

演示

将下面文件保存成 demo.html 文件,然后用浏览器打开,可以测试人机识别的效果。

<!DOCTYPE html>

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width" />
  <script src="https://challenge.rivers.chaitin.cn/recaptcha/api/sdk.js"></script>
</head>
<body>
  <script>
    $Recap
      .create({
        once_id: "test",
        image_type: 2,
        force: true,
        entrypoint: "https://challenge.rivers.chaitin.cn/recaptcha/api",
      })
      .run();
  </script>
</body>
分步解释

雷池 waf 在开启人机识别功能后,对每个 HTTP 请求都会校验是否包含人机验证 cookie ,每个 cookie 都对应一个人机有效期,在有效期内则通过,不在有效期内则直接返回人机拦截页面(类似上面的 demo.html 文件内容)。

  1. 页面加载后,会从云服务加载 sdk.js

sdk.js 是深度混淆过的代码,这是为了防止暴露环境检查项,一旦暴露就会被针对,环境检查也就失去了效果。如果机器人不针对检查项,而是直接模拟一个完美浏览器环境,则会大大增加机器人的成本。所以人机识别 sdk.js 都是 不开源 的,开源既失效。

如果用户当前网络无法访问 sdk.js,那么人机验证就无法执行下去。需要提前确认用户与人机服务的连通性。

  1. 环境检查结果

在环境检查项的选择上,我们使用了比较传统的方法:浏览器特定能力检查,根据浏览器的类型来检查是否具备特定功能。除了特定能力外,还有新的 AI 检测方法,比如利用机器学习来对鼠标轨迹进行识别,判断人类与机器人。但根据我们的调研,AI 在人机识别的场景下能力非常有限。还是以鼠标轨迹识别为例,在手机或平板电脑设备上没有鼠标的时候,就无法使用,即使在 PC 上 AI 的识别率也不准确。

搜索 “AI 鼠标轨迹识别”、“AI 爬虫行为识别” 等关键字的论文,查看论文影响因子,就知道这种方法有多水。实际上 AI 的效果只在特定条件下的某个环节才有奇效。

为了隐藏检查项目和检查结果,sdk.js 会把环境检查结果加密上报给云服务。这样做的好处是,只要更新云服务就可以实现人机识别的整体功能升级,避免了 sdk 分发的缓慢升级过程。但这样做可能给用户带来一个疑虑:雷池 waf 会不会偷偷搜集用户数据?不会,三个理由:首先是雷池的免费服务算力少,无持久化存储;其次是人机识别页面与用户页面是分开的,无法统计数据;最后是雷池 waf 的品牌信誉,我们不搜集与人机识别无关的信息。

  1. 疑似爬虫

如果在环境检查后,当前用户为人类用户的置信度较低时,会提示检测失败,但为了防止误判,会给用户一个“申诉”的机会。sdk.js 会在环境检查为爬虫后,会发起一次图灵问题,雷池 waf 的人机识别更新到了 v2 版本,目前使用“旋转对齐图片”问题作为人机识别的核心问题


  1. 结果判断

经过图片识别问题后,人机验证云服务会生成一个 jwt 返回给 sdk.js,再本地写入 cookie 后再刷新页面。此时,刷新后的页面会带上刚刚得到的人机验证加过 jwt 再次来到雷池 waf。雷池 waf 会验证 jwt 是否正确,如果正确,则放行当前请求,并用一个 session 替换掉 jwt。到此,人机验证完成。在当前的 session 内,用户的都被标记已通过人机验证。

统计数据

经过一段时间的试运行,雷池 waf 的人机识别已经正式发布,下面节选了某个服务实例 24h 的统计数据。

实测数据中请求人机识别数据

节选其中某个时刻的数据

我们来估算一下机器人用户的比例是多少?可以看到从环境检查(inspect)到图灵问题挑战(appeal)的转化率是 ~10%,从挑战(appeal)再到验证答案(verify)的转化率也是 ~10%。也就是所有被保护请求中约 10% 疑似人机,其中约 1% 通过验证是人类用户,也就是大约 9% 的访问量来自机器人,并被成功拦截。从统计结果来看,机器人的流量是超出了我们最初预期的(十分之一是爬虫),同是也证明了雷池 waf 的人机验证是有效的。

总结

人机验证是网络应用安全的重要环节,通过回顾 CAPTCHA 的发展来总结机器人识别的技术特征。根据雷池 waf 的业务场景选择了 非侵入式 集成的 云服务 人机识别功能,为了完善图灵问题,雷池 waf 还改善了图片识别的方法(已申请专利)。通过一段时间的云服务测试,证明雷池的人机方案思路是可行的。机器人识别和反识别是一对儿矛和盾的关系,双方都在成长,雷池 waf 的人机识别也还有很大进步空间,如果利用好 云服务 + 本地流量入口的天然优势,雷池的人机识别功能可以实现其他集成服务无法实现的能力。


产品创新团队 王德龙

浏览 (1192)
点赞 (4)
收藏
打赏
评论