可靠地检测基于 PhantomJS 的垃圾邮件机器人
Posted
技术标签:
【中文标题】可靠地检测基于 PhantomJS 的垃圾邮件机器人【英文标题】:Reliably detecting PhantomJS-based spam bots 【发布时间】:2014-01-18 16:58:41 【问题描述】:有什么方法可以持续检测 PhantomJS/CasperJS?我一直在处理一些用它构建的恶意垃圾邮件程序,并且能够根据某些行为基本上阻止它们,但我很好奇是否有一种可靠的方法可以知道 CasperJS 是否在使用中,如处理不断的适应会有点烦人。
我不相信使用验证码。它们是一种负面的用户体验,而且 ReCaptcha 从未在我的 MediaWiki 安装中阻止垃圾邮件。由于我们的网站没有用户注册(匿名讨论区),我们需要为每个帖子提供一个验证码条目。我们每天会收到数千个合法帖子,而验证码会看到这个数字的爆炸。
【问题讨论】:
你试过QuestyCaptcha,你在哪里选择了一组静态问题?除非您的网站专门针对垃圾邮件机器人,否则机器人将无法取胜,而人类则非常容易。 【参考方案1】:没有坚如磐石的方法:PhantomJS 和 Selenium 只是用于控制浏览器软件的软件,而不是用户控制它。
特别是对于 PhantomJS 1.x,我相信有一些 javascript 可以用来让浏览器崩溃,它会利用正在使用的 WebKit 版本中的错误(它相当于 Chrome 13,所以很少有真正的用户应该被影响)。 (我记得几个月前在 Phantom 邮件列表中提到了这一点,但我不知道是否描述了要使用的确切 JS。)更一般地,您可以使用用户代理匹配与特征检测的组合。例如。如果某个浏览器声称是“Chrome 23”,但没有 Chrome 23 具有(而 Chrome 13 没有)的功能,那么就要怀疑了。
作为用户,我也讨厌 CAPTCHA。但它们非常有效,因为它们增加了垃圾邮件发送者的成本:他必须编写更多的软件或雇佣人类来阅读它们。 (这就是为什么我认为简单的验证码就足够了:那些让用户烦恼的是那些你不知道它在说什么并且必须不断按下重新加载才能得到你识别的东西。)
一种方法(我相信 Google 会使用)是有条件地显示验证码。例如。登录的用户永远不会看到它。已经在此会话中发布过一篇文章的用户不会再次显示。来自白名单中 IP 地址的用户(可以从以前的合法帖子中构建)不会显示给他们。或者相反,只是将它们显示给来自 IP 范围黑名单的用户。
我知道这些方法都不完美,抱歉。
【讨论】:
【参考方案2】:您可以通过检查window.callPhantom
属性在客户端检测幻象。客户端的最小脚本是:
var isPhantom = !!window.callPhantom;
这是一个gist with proof of concept,它有效。
垃圾邮件发送者可能会尝试使用page.evaluate
删除此属性,然后这取决于谁更快。在您尝试检测后,根据您的检测结果,您是否使用帖子表单和验证码重新加载。
问题是您会招致可能会惹恼您的用户的重定向。这对于客户端上的每种检测技术都是必要的。可以用onResourceRequested
来颠覆和改变。
一般情况下,我认为这是不可能的,因为只能在客户端检测,然后将结果发送到服务器。添加 CAPTCHA 与仅加载一个页面的检测步骤并没有真正添加任何内容,因为它可以使用 phantomjs/casperjs 轻松删除。基于用户代理的防御也没有意义,因为它可以在 phantomjs/casperjs 中轻松更改。
【讨论】:
page
没有暴露在窗口中。这是请求实际页面的内部 phantomjs 属性。问题是在使用phantomjs执行页面时,从js窗口范围检测phantom。
这只是为了说明工作检测器。如果看起来很混乱,我会减少代码。【参考方案3】:
我非常赞同您对 CAPTCHA 的看法。我将列出到目前为止我能够检测到的内容,用于我自己的检测脚本,具有类似的目标。这只是部分内容,因为它们还有更多 headless browsers。
使用暴露的窗口属性来检测/假设那些特定的无头浏览器相当安全:
window._phantom (or window.callPhantom) //phantomjs
window.__phantomas //PhantomJS-based web perf metrics + monitoring tool
window.Buffer //nodejs
window.emit //couchjs
window.spawn //rhino
以上内容来自jslint doc,并使用phantom js进行测试。
浏览器自动化驱动程序(由 BrowserStack 或其他网络捕获服务用于快照):
window.webdriver //selenium
window.domAutomation (or window.domAutomationController) //chromium based automation driver
这些属性并不总是公开的,我正在寻找其他更强大的方法来检测此类机器人,我可能会在完成后将其作为完整的脚本发布。但这主要回答了你的问题。
这是另一种相当完善的方法,可以更广泛地检测支持 JS 的无头浏览器:
if (window.outerWidth === 0 && window.outerHeight === 0) //headless browser
这应该很好用,因为属性是 0 默认情况下即使虚拟视口大小是由无头浏览器设置的,并且 默认情况下它不能报告大小一个不存在的浏览器窗口。特别是 Phantom JS doesn't support outerWith or outerHeight。
附录:然而,外部/内部维度存在 Chrome/Blink 错误。 Chromium does not report those dimensions when a page loads in a hidden tab,例如从上一个会话恢复时。 Safari 似乎没有这个问题。.
更新:原来 ios Safari 8+ 有一个 bug,outerWidth 和 outerHeight 为 0,而 Sailfish webview 也可以。因此,虽然它是一个信号,但如果不注意这些错误,就不能单独使用它。因此,警告:除非您真的知道自己在做什么,否则请不要使用此原始 sn-p。
PS:如果您知道这里未列出的其他无头浏览器属性,请在 cmets 中分享。
【讨论】:
在我正在调查的情况下,navigator.onLine
属性为 FALSE(PhantomJS 也恰好是这种情况)。我测试的常规浏览器都为 onLine 返回了 TRUE。
另外,navigator.plugins
在我的情况下是空的,这也与 PhantomJS 一致。
@PeterK 谢谢。 navigator.plugins
可以仅被仔细考虑为附加组合信号。因为它在许多移动环境中也是空的,并且最终在未来的某些桌面上也是空的。
navigator.plugins
确实是弱证据。在我们的测试中,IE11 和 android Chrome 没有报告任何插件,桌面版 Chrome 和 Firefox 有。然而,这可以对我们有利,因为我们知道哪些浏览器应该报告插件。例如,如果浏览器声称是桌面 Chrome,但没有提供插件列表,我们可以判断它是在伪造 User-Agent,这已经很可疑了。
@PeterK 不,它们无法区分。而且我已经在生产中拥有一个 JS 脚本,可以完全检测移动设备上的欺骗性“桌面模式”代理。但是这个主题超出了这个问题的范围。以上是关于可靠地检测基于 PhantomJS 的垃圾邮件机器人的主要内容,如果未能解决你的问题,请参考以下文章