背景
521 可不是浪漫的表白数字哦,它还是一个http 请求响应码,碰到它能让你头大啊。最近在做一个漏洞爬取项目,上周发现 CNVD 网站升级了,使用了动态 JS 混淆技术,导致爬虫程序大量返回 521 响应码。解决过程,颇费周折,希望爬虫能维持一段时间、这个网站不要继续升级才好。
一个请求两次 JS 混淆
使用 Fiddler 抓包,分析请求数据发现规律如下。
第一次请求,响应码 521 ,响应头域包含一个 Cookie 信息:
响应内容是一段 JS ,包含另一段动态拼接的 Cookie 和重定向的代码:
第二次重定向请求,带上前两一次响应头域和 JS 的动态 Cookie 信息:
这次的响应码还是 521 ,响应内容是一段 JS:
第三次请求,带上第二次动态计算出来的 Cookie 后才真正进入网站主页:
这里的重点是,第三次请求时使用的那个 Cookie 跟第二个请求的 Cookie 不一样了,是通过第二次响应的一大段混淆的 JS 执行粗来的。
这说明,第二次返回的 JS 动态执行后,又生成了新的 __jsl_clearance_s
值,并带上它发起了第三次相同请求。
破解第二次响应的 JS 、获得最新的 Cookie 信息后才能顺利进入页面。
混淆 JS 的原貌
第一次请求 521 时返回的是一段 JS :
第二次返回 521 时是另一大段混淆的 JS :
第二段的 JS 包含 windows 等 JS 内置对象,可以用 HtmlUnit 工具来执行。执行之前,需要对其进行处理,替换掉所有的 location.href
等代码,只保留 Cookie 的计算,最后返回 document.cookie
信息,有了它就可以顺利请求网站数据了。
Java 执行动态JS解析Cookie
用 HttpClient 工具,按照 Fiddler 的流程请求并解析 Cookie 信息,最终可以顺利拿到页面。
关键代码是第二次执行 JS 获取 Cookie 的过程:
核心代码在于:
- JS 片段的处理,去掉脚本标签,还有重定向 JS
- 对 JS 添加 return 获取 cookie 的语句
- 执行 JS,而且如果获取到的是无效的 Cookie ,再进行二次执行
- UserAgent 信息很重要,一般的信息都无效,只有一个是有效的。
最终这个爬虫请求得到了完整的响应页面:
启示录
这个爬虫 521 攻破的核心是 UserAgent 信息
get.setHeader("User-Agent", "Mozilla/4.0
(compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)");
诡异的是,只有 Mozilla/4.0
(compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322) 这一个是有效的,网站是以该信息为主要依据生成 Cookie 的,三次请求的这个头域必须相同。
最后一点,是 Cookie 的时效,基本上是一小时左右,所以当遇到下一次 521 的时候,需要重新执行上述流程获取新的 Cookie 。