文档章节

数据安全(反爬虫)之「防重放」策略

杭城小刘
 杭城小刘
发布于 03/05 15:23
字数 2353
阅读 2W
收藏 71

大前端时代的安全性一文中讲了 Web 前端和 Native 客户端如何从数据安全层面做反爬虫策略,本文接着之前的背景,将从 API 数据接口的层面讲一种技术方案,实现数据安全。

一、 API 接口请求安全性问题

API 接口存在很多常见的安全性问题,常见的有下面几种情况

  1. 即使采用 HTTPS,诸如 Charles、Wireshark 之类的专业抓包工具可以扮演证书颁发、校验的角色,因此可以查看到数据
  2. 拿到请求信息后原封不动的发起第二个请求,在服务器上生产了部分脏数据(接口是背后的逻辑是对 DB 的数据插入、删除等)

所以针对上述的问题也有一些解决方案:

  1. HTTPS 证书的双向认证解决抓包工具问题
  2. 假如通过网络层高手截获了 HTTPS 加证书认证后的数据,所以需要对请求参数做签名
  3. 「防重放策略」解决请求的多次发起问题
  4. 请求参数和返回内容做额外 RSA 加密处理,即使截获,也无法查看到明文。

关于 HTTPS 证书双向认证和 Web 端反爬虫技术方案均在大前端时代的安全性一文中有具体讲解。接下来引出本文主角:防重放

二、 请求参数防篡改

在之前的文章也讲过,HTTPS 依旧可以被抓包,造成安全问题。抓包工具下数据依旧是裸奔的,可以查看Charles 从入门到精通文中讲的如何获取 HTTPS 数据。

假如通过网络层高手截获了 HTTPS 加证书认证后的数据,所以需要对请求参数做签名。步骤如下

  • 客户端使用约定好的密钥对请求参数进行加密,得到签名 signature。并将签名加入到请求参数中,发送给服务端
  • 服务端接收到客户端请求,使用约定好的密钥对请求参数(不包括 signature)进行再次签名,得到值 autograph
  • 服务器对比 signature 和 autograph,相等则认为是一次合法请求,否则则认为参数被篡改,判定为一次非法请求

因为中间人不知道签名密钥,所以即使拦截到请求,修改了某项参数,但是无法得到正确的签名 signature,这样构造的一个请求,会被服务器判定为一次非法请求。

三、 防重放策略

在工程师文化中,我们要做一个事情,就首先要对这个事情下个定义。我们才能知道做什么、怎么做。

理论上,一个 API 接口请求被收到,服务会做校验,但是当一个合法请求被中间人拦截后,中间人原封不动得重复发送该请求一次或多次,这种重复利用合法请求进行得攻击被成为重放

重放会造成服务器问题,所以我们需要针对重放做防重放。本质上就是如何区别去一次正常、合法的请求。

3.1 基于 timestamp 的方案

理论上,客户端发起一次请求,到服务端接收到这个请求的时间,业界判定为不超过60秒。利用这个特征,客户端每次请求都加上 timestamp1,客户端将 timestamp1 和其他请求参数一起签名得到 signature,之后发送请求到服务器。

  • 服务器拿到当前时间戳 timestamp2,timestap2 - timestamp1 > 60s,则认为非法
  • 服务端接收到客户端请求,使用约定好的密钥对请求参数(不包括 signature、timestamp1)进行再次签名,得到值 autograph。比对 signature 和 autograph,若不相等则认为是一次非法请求

假如中间人拦截到请求,修改了 timestamp 或者其他的任何参数,但是不知道密钥,所以服务器依旧判定为非法请求。 中间人从抓包、篡改参数、发起请求的过程一般来说大于60秒,所以服务器依旧会判定为非法请求。

基于 timestamp 的设计缺陷也很明显,种种原因下,60秒内的请求,会钻规则漏洞,服务器判定为一次合法请求。

3.2 基于 nonce 的方案

既然时间戳会有漏洞,那么新方案是基于随机字符串 nonce。也就是说每次请求都加入一个随机字符串,然后将其他参数一起利用密钥加密得到签名 signature。服务端收到请求后

  • 先判断 nonce 参数是否能存在于某个集合中,如果存在则认为是非法请求;如果不存在,则将 nonce 添加到当前的集合中
  • 服务端将客户端请求参数(除 nonce)结合密钥加密得到 autograph,将 signature 和 autograph 比对,不相等则认为非法请求

但是该方案也有缺点,因为当次的请求都需要和集合中去搜索匹配,所以该集合不能太大,不然匹配算法特别耗时,接口性能降低。所以不得不定期删除部分 nonce 值。但是这样的情况下,被删除的 nonce 被利用为重放攻击,服务器判定为合法请求。

假设服务器只保存24小时内请求的 nonce,该存储仍旧是一笔不小的开销。

3.3 基于 timestamp + nonce 的方案

根据 timestamp 和 nonce 各自的特点:timestamp 无法解决60秒内的重放请求;nonce 存储和查找消耗较大。所以结合2者的特点,便有了 「timestamp + nonce 的防重放方案」。

  • 利用 timestamp 解决超过60秒被认为非法请求的问题
  • 利用 nonce 解决 timestamp 60秒内的漏网之鱼

步骤:

  1. 客户端将当前 timestamp1、随机字符串和其他请求参数,按照密钥,生成签名 signature
  2. 服务端收到请求,利用服务端密钥,将除 timestamp1、随机字符串之外的请求参数,加密生成签名 autograph
  3. 服务端对比 signature 和 autograph,不相等则认为非法请求
  4. 拿到服务端时间戳, timestamp2 - timestamp1 < 60,则判定为一次合法请求,然后保存 nonce
  5. 服务端只保存60秒内的 nonce,定时将集合内过期的 nonce 删除

该集合不应该直接操作文件或者数据库,否则服务端 IO 太多,造成性能瓶颈。可以是 mmap 或者其他内存到文件的读写机制。根据场景可以选择乐观锁、悲观锁。

其中有一个 timestamp 的问题,服务器会将请求参数中的 timestamp 判断差值,其中一个致命的缺点是服务器的时间和客户端的时间是存在时间差的,当然你也可以通过校验时间戳解决此问题。时间同步请继续看下面部分。

四、 计算机网络时间同步技术原理

客户端和服务端的时间同步在很多场景下非常重要,举几个例子,这些场景都是经常发生的。

  • 一个商品秒杀系统。用户打开页面,浏览各个类目的商品,商品列表界面右侧和详情页都有倒计时秒杀功能。用户在详情页加购、下单、结算。发现弹出提示“商品库存不足,请购买同类其他品牌商品”
  • 一个答题系统,题目是该公司核心竞争力。所以有心的程序员为接口设计了「防重放」功能。但是前端小哥不给力,接口带过去的 timestamp 与服务器不在一个时区,差好几秒。别有用心的竞品公司的爬虫工程师发现了该漏洞,爬取了题目数据。

所以该现象在计算机领域有非常普遍,有解决方案。

  1. 如果精度要求不高的情况下:先请求服务器上的时间 ServerTime,然后记录下来,同时记录当前的时间 LocalTime1;需要获取当前的时间时,用最新的当前时间 (LocalTime2 - LocalTime1 + ServerTime)

    拿 iOS 端举例:

    • App 启动后通过接口获取服务器时间 ServerTime,保存本地。并同时记录当前时间 LocalTime1
    • 需要使用服务器时间时,先拿到当前时间 LocalTime2 - LocalTime1 + ServerTime
    • 若获取服务器时间接口失败,则从缓存中拿到之前同步的结果(初始的时间在 App 打包阶段内置了)
    • 使用 NSSystemClockDidChangeNotification 监测系统时间发生改变,若变化则重新获取接口,进行时同步
  2. 如果需要精度更高,比如 100纳秒的情况,则需要使用 NTP(Network Time Protocol)网络时间协议、PTP (Precision Time Protocol)精确时间同步协议了。

NTP、PTP 不在本文的范畴,感兴趣的可以查看这篇文章

© 著作权归作者所有

下一篇: 上架包预检
杭城小刘

杭城小刘

粉丝 63
博文 109
码字总数 105882
作品 0
杭州
iOS工程师
私信 提问
加载中

评论(53)

s
super_L
我就破解过这种方案.app客户端甚至用了阿里的加密框架来生成签名 .一样破解掉. 其实说实话, 没有绝对的反爬策略.单纯防网络层的重放, 这是一个行之有效的方案. 如果客户端没有有效防护, 任何加密方案也都是纸糊的. 起不到实质作用, 其实最终反爬方案还是放在服务端. ip验证+人脸验证之类+频率限制或者验证码来限制爬虫访问. 但相对的反爬成本下的越大. 用户体验度就越差. 最终还是用户吃苦头. 建议没啥重要数据还是不要考虑这些反爬不反爬了. 反爬力度小了, 只能限制小白. 力度大了. 又坑到用户. 吃力不讨好. 何苦?
杭城小刘
杭城小刘 博主
所以也就是根据场景选择方案的过程,发现别人非要爬,那我就非要你爬不了。看了下你的动态,说实话我没看到你的客户端逆向能力和卓越的网络知识,所以我对你这句话很好奇,也不是说怀疑你能力。「app客户端甚至用了阿里的加密框架来生成签名」能不能距离呢?他的通信机制是什么,确实有难度吗?我简单举个例子,HTTPS certificate 双向认证 + RSA,请问如何破解?
s
super_L
我不想跟你吵,我逆向也不发技术贴,我已经说的很客观了,如果你非要纠结,那就继续纠结吧,您天下无敌请去国防部
s
super_L
另外,阿里的某加密框架已经不维护了,如果你非要详细点的话,它的加密逻辑为:nonce+时间戳+盐+某特殊算法,阿里的加密框架加密了盐值,操作方法为在阿里的网页内输入你的秘钥,然后人家把秘钥生成一张图片返回给你,同时返回一个sdk用来调取自己的加密。如果你要模拟,你就要从图片里解出秘钥,之后再重写加密进行发送。请问这种加密方法比起您文章这种如何?
并非说你的这个方法不行,我发言也做出了肯定,这是一种防重放的行之有效的方法,但他只是限制了网络层,仅此而已。
杭城小刘
杭城小刘 博主
密钥通过图片传送又不是一件很神奇的事情,比如图片本身就可以通过字节提取出相应的数据。然后返回 SDK 调用自己的加密?感觉说的很不清楚。不过算了,这个问题就不讨论了。没啥大意思。另外没正面回答我上句话最后提出的问题
l
linkzp
方案理论上很完美,但是建议不要做得这么绝,也不要宣扬这些方法。何必呢,攻防对抗,互相消耗成本
杭城小刘
杭城小刘 博主
我作为 iOS 工程师在之前公司帮爬虫团队解决过安全问题、也帮忙爬过。然后对爬虫和反爬也有点好奇,所以方案和思考过程可以分享出来。另外我在公司落地的其实比这个更安全点。所以分享出来也是脱敏过的
兮若
兮若
除了这些,还有投毒的方案,如果爬的数据是错误的或者部分错误的,那对于爬虫来说也没有意义,我觉的关键不是防,而是识别,然后投毒。
杭城小刘
杭城小刘 博主
这也算是一种策略,策略和方案这种东西都是根据具体场景选择的。比如内容很重要的情况下,我觉得可以不识别再加投毒,因为用户是 VIP 用户,付费用户体验很重要,万一某些原因误伤,感觉不太合理
一个程序猿的异常
一个程序猿的异常
只是破解成本问题~
杭城小刘
杭城小刘 博主
是的,应该来说我这个成本很高了,我调研了几个爬虫工程师对于该方案下如何爬虫,他们说 OCR,那我觉得成本非常高了,假如数据很有价值,你上 OCR,那我也有办法,基于 canvas 绘图,加参数,让 OCR 识别的成本更加大
justintung
justintung
除非你不接受别人访问。要么你就没法防。防也只能防小白。
就我们公司的采集。某知名站点直接说,把你的爬虫的ip给我,我给你加白名单吧😂
杭城小刘
杭城小刘 博主
哈哈,我之前帮爬虫工程师攻克过他们爬不了的小程序数据。我也涉及过反爬方案。我是 iOS 资深工程师,给你 ip 干嘛?另外说防小白?你可以针对我的反爬方案找出爬虫方案吗?听听你的意见,效果图 https://github.com/FantasticLBP/Anti-WebSpider/blob/master/Anti-WebSpider.gif
justintung
justintung
好好看看别的网站怎么做的,你的方案别人都用浪了。 建议你去申请专利?这样全球公司都来向你付专利费了。而且你也为他们省了大笔的钱,因为再也不要为爬虫付高额的带宽、服务器费用了。 让开源中国给你开一个保证金,谁反扒成功,给他来个几万的?没利益,谁和你反爬?
杭城小刘
杭城小刘 博主
建议你好好看看内容,别人也有字体技术,但是我的字体技术每次刷新都不一样,你怎么破?我不至于为这种东西申请专利
麦壳原野
麦壳原野
前端js看不懂跟破解不了是两码事情,ssl本身就是为了解决安全交换密钥的问题,你现在又把密钥暴露就两者冲突相悖了吧
杭城小刘
杭城小刘 博主
SSL 是为了建立链接。可以专业转包工具还是可以获取 HTTPS 数据,所以业界常见做法是针对数据额外做 RSA 加密。情况1、JS 环境最弱的情况,项目是跑在浏览器环境下,JS 代码可以调试、甚至拦截网络,所以诞生了防重放策略和我的另一个方案,你即使拿到数据也是无意义的,因为数据需要结合浏览器才可以正确的展示;情况2、前端代码跑在客户端容器内,js 混淆过,且 Native 对网络操作能力非常强,比如针对抓包工具,可以做 HTTPS 证书的双向认证、RSA 加密(即使被网络高手连双向认证都破解了,他拿到的数据还是无法解密的),JS 通过桥接 Native 的能力调度网络,客户端 callBack给 js 。所以不冲突呀
robortly
robortly
一句话,你客户端怎么拿数据 我爬虫就怎么拿数据,这个不矛盾吧?
多年的C# 虫师,配合Fiddler+浏览器来搞 可以大胆的说 无孔不入。^o^
杭城小刘
杭城小刘 博主
你原封不动发起请求:我有防重放 你用无头浏览器:我有我设计的反爬方案:https://github.com/FantasticLBP/Anti-WebSpider 建议你看看内容再说。你拿到了数据,数据也是无意义的。建议你思考下浏览器显示网页做了什么事情
robortly
robortly
不是原封不动,可以改包。也可以hook你的渲染完成逻辑的js。那些字体文件加密 你怎么混淆的我都可以缓存,下次我可以用它来跟你网站一样的逻辑加载显示,有必要的可做下字体文件的识别转换成通用字体。
robortly
robortly
补充下,防重放的策略是服务器的策略。我的策略是中间者缓存策略,一旦数据第一次被拉取到了 可以想办法通过中间者恢复的。
杭城小刘
杭城小刘 博主
防重放本来是服务端策略,我是一个全栈,所以出方案不是只单纯在某个层面思考或者给出一个方案。 「一旦数据第一次被拉取到了 可以想办法通过中间者恢复的」这个我觉得很难恢复,因为对于汉字和数字的字体还原策略不一样的,而且每次刷新这个策略都会改变
robortly
robortly
这个看你怎么去理解了,我中间缓存的本身就是浏览器真实渲染的数据。请注意 每次刷新我用的是你第一次的。只要前端渲染是正常的数据我就有办法通过中间者找到是哪个版本的字体的。对我来说服务器防重放对爬虫没有意义,我本身就只要拉取一次,第二次再次拉也是从前端一样的逻辑第二个逻辑采集,例如翻页采集。
杭城小刘
杭城小刘 博主
hook?JS 混淆后我觉得不是 JS 专家级别读不懂,基于 AST 语法抽象树层面做了混淆。且每次刷新字体都是变得,所以不管内容还是数据,你最多只能拿当前一次的。另外策略也不知是一种,结合封锁 IP 等策略,我觉得还是蛮安全的
robortly
robortly
hook 的目的不是读懂js的源码,vm 动态执行的js闭包逻辑很难调试且调出来来了,咋也不会修改里面的逻辑。正常hook 都是 基于 before request 之类 或者 替换他们js加载的逻辑文件。不知道你用不用Fiddler这款软件,它可以简单的全局修改你网站的js加载。 所有的服务端策略只能阻碍爬虫 或者 影响 用户体验,无法做到真正意义的阻止爬虫。
杭城小刘
杭城小刘 博主
理解为 Map local、Map remote 的功能,这很简单也很正常的功能。「对我来说服务器防重放对爬虫没有意义,我本身就只要拉取一次,第二次再次拉也是从前端一样的逻辑第二个逻辑采集,例如翻页采集」针对一个站点进行爬虫研究,不可能一上来就知道思路,所以肯定要抓包分析,重复发起第二次请求,所以防重放解决的就是这个环节的攻击。   其实你的思路错了,爬虫爬数据的目的是将别人的内容保存到自己这边,所有难免需要入库,所以入库这个过程你就不可达,接口来的数据无意义、网页展示的内容是合理,但是你去查看源码或者审查元素确实无效的,所以入库这条路就断了。
robortly
robortly
回复 @杭城小刘 : 看你对数据怎么要求了,采集目的是能对有用的数据存储。入库需要经过:存储,解析。 一般解析入库都是可以作为延缓设计来弄。
杭城小刘
杭城小刘 博主
回复 @robortly : 异步解析入库是正常操作,我的意思是缓存了每个页面后,一般情况下需要「提取出文本内容」,可能还需要经过处理、分析再入库。问题就是在提取这部,常规的提取就是 xpath 或者 OCR 等,OCR 成本非常高,xpath 又不可行。
专业写BUG的程序员
专业写BUG的程序员
应该说是浏览器怎么拿数据,爬虫一定能够模拟出相同的请求拿到数据。 安卓客户端或者ios客户端拿到的加密数据你不一定解得了。
杭城小刘
杭城小刘 博主
总结下来就是即使能拿,拿到了不一定能用,因为需要破解显示原理;客户端安全性很好,再加上技术手段,所以更难破解
开源中国首席罗纳尔多
开源中国首席罗纳尔多
您好,请问别人有些js库是vip收费的?他是怎么做到判断是否付费用户,js的源码只能混淆按道理都是可以看见的才对?假如把vip码写死在js库上,那第一次购买的人分享出去也可以的啊?
杭城小刘
杭城小刘 博主
看不懂你的意思。假设你问的是某些功能是需要付费使用的。那么正常做法是判断用户的身份类型,你登录后会存储 token,你购买充值 vip 也会更新凭证。使用其他功能调用接口 token 都是携带的,服务端的逻辑判断就是先判断用户身份信息
开源中国首席罗纳尔多
开源中国首席罗纳尔多
您好,不是,类似layer.js vip版
杭城小刘
杭城小刘 博主
刚刚搜了下,看到是免费的 😂
开源中国首席罗纳尔多
开源中国首席罗纳尔多
您好,这种,https://www.layui.com/demo/layim.html,要授权才能下载layim.js,但是假如A网站买了,我访问A网站就能拿到layim.js,不明白它的原理是怎么防止泄露?
杭城小刘
杭城小刘 博主
看上去是别人的财路,不太想花时间去研究这个
开源中国首席罗纳尔多
开源中国首席罗纳尔多
回复 @杭城小刘 : 您好,是的我懂。我只是好奇一下如果自己写有什么思路可以类似它做vip授权
z
zjh6
真有那么多值得爬的数据?
杭城小刘
杭城小刘 博主
你经历过类似的需求就不知道数据的重要性。你思考的角度决定了你的想法和你说出的话
杭城小刘
杭城小刘 博主
简单和你聊聊吧,首先如果是电脑端浏览器环境跑 JS 代码,因为 JS 代码在浏览器开发者模式下可以查看,但是可以混淆代码。如果你拦截了请求,原封不动的去发起一个请求。方案1:这种情况查看我的文章顶部的文章,Web 端的反爬虫策略,请求到的数据是需要配合字体文件才可以得到正确结果,所以你单纯拿数据没用;方案2:引入了防重放策略;原封不动的请求也无效;方案3:如果是在客户端容器中,客户端对网络的操作能力很强,你都没办法抓包分析网络。即使你是网络高手,自定义的 RSA 算法,你也破解不了
深度解析移动应用安全的四大常见问题及解决方案

当前移动安全中恶意攻击的现状可以归结为四个主要方向:网络安全、数据安全、代码安全、设备安全。 网络安全 网络安全分为四个部分:数据防泄露、请求防重放、内容防篡改、身份防伪装。 解决...

个推
2019/10/01
27
0
安全协议——Internet安全协议(Internet Protocol Security,IPSec)工作原理

IPSec的使用是建立在安全关联的基础上的,所以在讲IPSec之前要先了解一下安全关联,然后再详细讲述IPSec的工作过程。 一、安全关联 安全关联的定义:为了实现数据发送者至接收者的安全传输,...

0rambot
2018/12/16
0
0
云妹浅谈 | 纵深防爬的“抗战”之路

0x00 爬虫=爬数据? 之所以又提“什么是爬虫”这个老生常谈的问题,是前几天有个验证码接口被刷的用户在群里讨论防护方案,他认为这种不算是爬虫,爬数据的才叫爬虫(这里的“爬数据”指的是...

阿里云科技快讯
2018/08/30
0
0
一场无休止的战争 浅谈纵深防爬的“抗战”之路

0x00 爬虫=爬数据? 之所以又提“什么是爬虫”这个老生常谈的问题,是前几天有个验证码接口被刷的用户在群里讨论防护方案,他认为这种不算是爬虫,爬数据的才叫爬虫(这里的“爬数据”指的是...

云安全专家
2018/08/27
0
0
Java开发手册(五):安全规约与单元测试

一、安全规约 1. 操作权限 隶属于用户个人的页面或者功能必须进行权限控制校验。防止没有做水平权限校验就可随意访问、修改、删除别人的数据,比如查看他人的私信 内容、修改他人的订单。 2....

思与学
2017/11/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

解决pycurl安装失败

现象描述 现象一:ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other) 现象二: There was a problem importing one ......

项昂之的微博客
8分钟前
23
0
Redis 简介

Redis 是一种基于键值对(key-value)的NoSql 数据库。Redis 中的值可以是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、HyperLogLog...

jackdawl
8分钟前
15
0
Scala的相等性

Scala和java中的相等性 - scala java == 归约相等性 对象一致性 equals 归约相等性 归约相等性 eq 对象一致性 无 - 对象一致性 归约相等性 java == equals Scala eq ==和equals 简而言之, ...

dreamness
13分钟前
20
0
项目讲解1

1.数据采集到hadoop中; 2.数据在采集过程中,一部分丢给hdfs,一部分丢该实时的处理系统(kafka) kafka严格上说并不是消息队列,消息队列是符合 gms 规范的,有先后顺序的,kafka不保证顺序,...

七宝1
14分钟前
12
0
横空出世一周年,百度ERNIE再夺权威语义评测5项世界冠军

近日,全球规模最大的语义评测比赛 SemEval 2020 结果出炉,百度基于飞桨平台自研的语义理解框架 ERNIE 一举斩获 5 项世界冠军,囊括视觉媒体的关键文本片段挖掘、多语攻击性语言检测和混合语...

飞桨PaddlePaddle
15分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部