适用对象:搜索或类似功能会调用外部API的站点运营者。本文概括了本站运营者所运营的一个站点上确实发生过的事情。文中不提及站点、外部服务,也不给出具体限制值或日期,不涉及攻击步骤。
发生了什么
在本站运营者运营的一个站点上,搜索功能会在每次搜索时调用外部API。几天之内,搜索流量升至正常水平的约20倍。外部API设有并发上限,绝大多数搜索(超过90%)返回503。
最初的假设是每IP限制(每分钟N次)可以遏制它。这一假设是错误的。
几天内搜索流量升至约20倍
外部API的并发上限被触发,几乎所有搜索都返回503。此时看起来只是错误增多了。
最初的假设:每IP限制可以遏制它(错误)
按每IP每分钟计数,可以捕捉到少数IP发出的大量调用。但这不是这种类型的流量。
测量结果
某一天约60,000次搜索来自约60,000个不同IP,每个IP大约一次请求。该模式看起来像住宅代理网络。用户代理是普通浏览器,Referer是站点本身,查询内容是真实的商品名称。采集价格很可能是其目的。
外部API的每日配额在当天早些时候就用完了
机器人的搜索很早就耗尽了配额,正常访问者在当天大部分时间都无法搜索。
为何它看起来不是真正的问题
配额受到保护,因此外部API看起来运行正常,站点只看到错误增多。保护配额与让用户正常使用该功能,原来是两回事。
预期情况:少数IP发出大量调用
触发每IP限制 → 已阻止 ✓
实际情况:约60,000个IP,每个一次请求
没有任何IP达到限制 → 只有外部API的配额被耗尽
= 只要计数单位是IP,这种形态就是不可见的
上游配额受到保护,并不代表用户能使用该功能
保护外部API配额或并发的机制,其存在是为了防止该API崩溃。它在运行时,上游不会显示错误。代价落在失去配额的一方:你自己的访问者。
正是因为保护机制在正常工作,问题才难以察觉。应当关注的是真实访问者搜索时的成功率。
如何阻止的
未能阻止它的设计
任何人的每次搜索请求都会调用外部API。唯一的限制是每IP计数。分布式流量使每个IP的计数保持较低,因此从未触发限制。
有效的设计
只有携带由站点自身页面签发的签名令牌(Cookie)的搜索,才会调用外部API。没有令牌时,返回轻量页面或403。在此基础上,设置全局及每令牌的每小时上限。
- 签名令牌
- 由站点自身页面签发的令牌成为调用外部API的条件。没有令牌则返回轻量页面或403
- 保护汇总数据
- 无令牌的搜索被排除在热门搜索排行之外,该排行曾被机器人的查询放大
- 每小时上限
- 同时设置全局上限和每令牌上限
发布后,503立即降至零。现在每天约100,000次无令牌请求会收到403,正常搜索得以通过。
经验教训
- 每IP限制对分布式机器人无效。每个IP只发一次请求,无论限制多低都无法阻止。
- 上游配额受到保护,并不等于用户能使用该功能。保护机制可能掩盖问题。
- 排行等汇总数据会被污染。在保护外部API的同时,应限制输入汇总数据的内容。
你可以做什么
以下顺序是本站自己的建议,并非引用来源的表述。
在任何高成本步骤之前检查站点签发的令牌
在消耗成本或配额的步骤(例如调用外部API)之前,先检查由你自己的页面签发的签名令牌。为令牌设置有效期,并在服务器端验证。若缺少令牌,则不再继续,返回轻量页面或403。
将无令牌的流量排除在汇总数据之外
热门搜索、查询统计和推荐只基于带令牌的搜索生成,避免机器人的查询进入站点的展示内容。
设置全局及每令牌上限
使用每小时全局上限和每令牌上限,而不是每IP计数。全局上限是最后的防线,用于防止外部API的配额被耗尽。
增加结果缓存和排队
对重复查询使用缓存,无需再次调用外部API;繁忙时对请求排队。当某一措施被绕过时,配额不太可能瞬间耗尽。
监控访问者看到的成功率
记录真实访问者搜索成功的比例,而不只是外部API的错误率,并在其下降时发出告警。这就是组织安全基线中所说的“能够察觉异常”的状态。
令牌不是身份验证,它提高的是攻击者的成本
令牌不是身份验证。令牌能做到的,是阻止那些只是反复请求搜索URL的流量;它不是完整的防御。
因此需要将其与缓存、排队和每令牌上限结合使用。在本站看来,如果机器人每次都获取新令牌,每令牌上限就没有帮助,所以务必将其与全局上限和缓存配合使用。本站的观点与速率限制与滥用控制一致:目标是让滥用的成本超过收益,而不是把其成功率降到零。
来源(一手)
- OWASP API Security Top 10 2023,“API4:2023 Unrestricted Resource Consumption” — api-security.owasp.org(限制客户端在一定时间内与API交互的频率;为外部服务配置支出上限)
- OWASP Automated Threats,“OAT-011 Scraping” — owasp.github.io(将爬取定义为收集内容或数据以供他处使用,例如价格操纵;无需身份验证的数据可能成为目标)
延伸阅读
- 设计:速率限制与滥用控制:设计能阻止暴力破解和失控成本的限制
- 前置知识:X-Forwarded-For欺骗与可信代理(按IP计数的基础)
- 运维:组织安全基线(如何察觉异常)