发布于 

高阶防御爬虫策略分析 · 浅尝辄止

0x01爬虫

防爬虫,就是在尽量减少对正常用户的干扰的情况下尽可能的加大爬虫的成本。
为何是尽可能加大爬虫成本?

有过网络安全知识基础的或许都知道,网络没有绝对安全,只有相对安全,积极的加强自我的网络安全技术水平有利于网络技术的各个方面。

举个例子:
在网络安全下,只有相对安全,一个服务器(组织)不论如何严防死守,在技术更新迭代快速的环境下,漏洞总是无穷无尽,攻击更是防不胜防。

在互联网与用户数据交互的过程中,有了一个新的成员,爬虫。
除非产品不是面向用户,否则,就无法阻挡爬虫(无限接近真实用户行为的程序)。Emmm本质很是相似。

所以,防爬与爬取之间的战斗,比较的是技术门槛!

0x02防御爬虫

一些不再实用的操作,这里就不多赘述了,网上有很多。

0x001特征

一些关于User-Agent的检测逻辑判断在1202年可能已经不太实用。当然,这里不包含一些浏览器特性(特征) 这个就让爬虫很难受了。
比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
var dstr = "";

if (navigator.__driver_evaluate) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__webdriver_evaluate) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__selenium_evaluate) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__fxdriver_evaluate) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__driver_unwrapped) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__webdriver_unwrapped) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__selenium_unwrapped) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__fxdriver_unwrapped) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__webdriver_script_func) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.__webdriver_script_fn) {
dstr += "1"
} else {
dstr += "0"
}

if (navigator.webdriver) {
dstr += "1"
} else {
dstr += "0"
}

另外,如果使用的是Token即时验证,还可以加上鼠标点击事件进行异步二次验证。

1
2
3
4
5
6
// 判断是否在frame框架内
if (window.self != window.top) {
return false;
} else {
return true;
}

为什么要强调特征?
谁用谁知道,真香。

0x002偷梁换柱

这里可以说是一些骚操作了,首先我们知道:

  1. 在爬取的过程中,是对原始的数据进行抓取分析。
  2. 爬虫没有眼睛。
  3. 程序的等待和人类的等待是有本质区别的(确信)

那么,如何使自己的程序,不满足以上条件?

  1. 原始数据 不等于 最后数据
  2. 原始数据 不等于 最后数据(进阶)只有有屏幕才可以看到
  3. 伪造等待?

我们知道,每一个字符都有一个二进制的Unicode,如果我们将字符的Unicode替换新建,但是字,还是那样。

由此我们知道“我”的Unicode为 6211 \u6211

让字在页面中显示依旧,但是改变其Unicode需要借助字体。
如何更好地理解这个概念?就好像图标一样。

或者这么想,将“我”与“你”的Unicode调换,那么,用户看到的是“我爱你”。
而爬虫爬取的源字符串是“你爱我”,从而使其进行错误的下一步。
通过博主调查折腾得知,要完成这样的操作,通过现有的JS接口和继承关系无法做到
只能使用“字体文件”来进行修改。
这里有 百度字体编辑

0x003暗渡陈仓

我们知道:

  1. CSS有伪元素,它有一个必要的“content”的属性
  2. 爬虫对于Style的有着不敏感的接口(这里基本上可以理解为,很难去抓取标签的Style,更何况是伪元素的)

那么:

使用伪元素(真)来遮盖源(假)数据使用户看到的是真数据
就能够达到防爬虫的目的

0x03行则将至

很多实例,其实也带有很多坑,博主踩到过很多。
主流的防止拦截的短链接网站所用的核心其实就是请求头和响应头的高度耦合,站内还有授权Refer,也足以满足绝大部分防爬需求了。(注意,这里说的并不是所谓的人机验证)

博主甚至还写过,页面一直pendding,直到css的hover元素被激活(也就是用户“不耐烦的”点击了等待中的页面)才向后端发送请求,效果是出奇的好。
同理的,博主写过监控页面中的指针动作,如果满足一定的条件,就向后端发送请求,效果也是出奇的好。
当然,如果使用机器学习,进行行为预测?

让我们假设

假设每秒钟获取用户的指针位置,不存在以0标记,持续10秒,点击位置和次数,任何一切作为客户端能获取到的内容。
随后,
我们整理为一个csv文件,它可能像这样:

行为1行为2行为3行为993行为994行为995行为996行为997行为998行为999行为1000目标
3-254-75340035450033
1-654-763478636803303
7-923-43340034200000
0-00-0000000000爬虫
00000000000爬虫
xxxxxxxxxxx爬虫

值得注意的是,上面的数据为正常用户的数据收集,这就意味着我们需要针对于爬虫再次收集一次数据,并且都做好标记。

我们送入机器学习进行训练和建模。

随后,我们就可以通过训练好的模型,来判断当前用户的行为,是否为爬虫。

当然,回归的模型是一个概率的判断,终究是存在误差的,但是在不断迭代和更新中,我们可以越来越接近100%准确率

在最后

  1. 低级过筛UA,不多解释
  2. 在请求头中获取关键要素,比如所规定的入口Refer地址,SSL还可要求Auth,可以参见OAuth,算是一个模态的简易化版本吧
  3. 在一个frame中收集用户信息请求接口进行人机判断,这也是cloudflare的方法
  4. 根据返回进行服务端决策是否放行请求

人工智能会慢慢贯穿我们的生活,在未来,我们可能不需要什么爬虫,甚至不需要什么反爬,因为,数据几乎都以透明,人工智能会提供我们所需的绝大部分信息,我们要做的,是正确接待信息。