是否可以通过用户脚本检测页面修改?

Out*_*ack 0 javascript greasemonkey web-applications userscripts

如果您有一个网站,您能否以某种方式找出访问者是否正在使用 javascript 用户脚本修改您的网站?

Joh*_*rak 5

简而言之:EEEEEEEK!不要这样做!相反,决定需要保护的东西,并保护。不惜一切代价避免轮询(定期检查)。尤其要避免定期对任何东西进行大量检查。


并非每个更改都可以跟踪。大多数变化都非常难以追踪,因为有很多事情可能会发生变化。

可以检测到 DOM 的更改(新节点、删除的节点、更改的属性)。另一个答案建议innerHTML定期检查,但最好使用突变观察者(Firefox、Chrome 支持)或较旧的突变事件(DOMSubtreeModified等)(支持因事件而异)。

无法可靠地检测对标准方法的更改,除非手动比较每个方法和属性 (eeeek)。这包括需要参考万吨的对象包括,比如说,Array.prototype.splice(和ArrayArray.prototype为好,当然),并运行一个沉重的周期性脚本。但是,这不是用户脚本通常所做的。

输入的状态是一个属性,而不是一个属性。这意味着文档 HTML不会改变。如果状态被脚本改变,change事件也不会触发。同样,唯一的解决方案是手动轮询每个输入(eeek)。

没有可靠的方法来检测是否已附加事件处理程序。对于初学者,您需要保护onX属性(第 2 段),检测对addEventListener(ek) 的任何调用(不触发第 2 段检查),检测您的库(jQuery.bind以及其他几个)对相应方法的任何调用。


件事对您有利,也可能是唯一件事:用户脚本在页面加载时运行(绝不会更快),因此您有足够的时间准备防御。 甚至对你不利(感谢布洛克亚当斯的注意和链接)

您可以通过将其替换为您自己的 (ek) 来检测已调用的标准方法。有许多方法需要以这种方式 (eek) 进行检测,有些通过浏览器,有些通过您的框架。IE(甚至可以指示 firefox,感谢@Brock)不会让您接触 DOM 类的原型,这一事实在“eek”中添加了另一个“e”或两个“e”。某些方法只能通过方法调用(返回值、回调参数)获得的事实添加了另一个“e”或两个“eeeek”。爬行整个的想法window将被安全异常和无法捕获的安全异常所挫败。也就是说,除非您不使用 iFrame 并且您不在 iFrame 内。

即使您检测到每个方法调用,也可以通过写入innerHTML. Firefox 和 Chrome 支持 Mutation Observers,因此您可以使用它们。

即使您检测到对预先存在的方法的每个方法调用并侦听突变,大多数属性都不会反映,因此您还需要观察每个对象的所有属性。祈祷有人不要使用您永远猜不到的键添加不可枚举的属性。顺便说一句,这也将捕获 DOM 突变。在 ES6 中,可以观察对象的属性集。我不确定您是否可以将 setter 附加到 ES5 中的现有对象属性(同时遵守 ES3 语法)。轮询每个属性都是 eeeek。

当然,您应该允许自己的脚本进行一些更改。工作流程是设置一个标志(不能从全局范围访问!)“我是合法的”,做你的工作,并清除标志 - 记住也要在你所有的回调旁边。然后方法观察者将检查标志是否设置。属性看门狗将更难检测更改是否有效,但可以从每个合法更改的脚本中通知它们(手动;再次确保用户脚本无法看到该通知流)。哎呀。

有一个完全不同的问题,我一开始没有意识到:用户脚本在页面加载时运行,但它们也可以创建 iFrame。这不是完全inconcievable(但仍不太可能现在)是一个userscript将:1)检测你的脚本拦截,2)从轨道核武器攻击的页面(你不能阻止document.body.innerHTML =,至少在没有与严重篡改document.body),3)插入一个具有原始 URL 的单个 iframe(防止双重加载服务器端?)和 4) 在您的保护加载之前,有足够的时间对该空 iframe 采取行动。

另外,请参阅Brock Adams 发现的副本,其中显示了我认为不应该进行的其他几项检查。