【问题标题】:Is it possible to detect page modification through userscripts? [duplicate]是否可以通过用户脚本检测页面修改? [复制]
【发布时间】:2013-02-07 07:01:38
【问题描述】:

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

【问题讨论】:

  • 您要检测什么样的修改以及在哪个浏览器中?
  • 简短回答:是的。 ...更长的答案:以用户无法阻止的方式检测模组要困难得多。 ...理论上,用户可以阻止网站所做的任何事情(除了变黑)。

标签: javascript web-applications greasemonkey userscripts


【解决方案1】:

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


并非所有更改都可以跟踪。大多数变化都很难跟踪,因为有很多事情可以改变。

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

无法可靠地检测到对标准方法的更改,除非通过手动比较每个方法和属性 (eeeek)。这包括需要引用大量对象,例如 Array.prototype.splice(当然还有 ArrayArray.prototype),并定期运行 heavy 脚本。但是,这不是用户脚本通常会做的事情。

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

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


有一个对你有利,并且可能是唯一一个:用户脚本在页面加载时运行(永远不会更快),所以你有足够的时间来准备你的防御。 not even that plays in your favor(感谢 Brock Adams 的注意和链接)

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

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

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

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

一开始我没有意识到一个完全不同的问题:用户脚本在页面加载时运行,但它们也可以创建 iFrame。用户脚本会:1) 检测到您的脚本拦截器,2) 将页面从轨道中删除(您无法阻止 document.body.innerHTML =,至少不会没有严重篡改document.body),3)插入一个带有原始URL的iframe(防止双重加载服务器端?)和4)有足够的时间在你的保护被加载之前对那个空的iframe采取行动。

另外,请参阅the duplicate found by Brock Adams,其中显示了我认为不应该进行的其他几项检查。

【讨论】:

  • Re: user scripts run on page load (never sooner), so you have plenty of time to prepare your defenses. ...不,每个可编写脚本的浏览器都支持starting before any of the page loads. 用户脚本可以覆盖原型并隐藏各种观察者和保护措施。对于 Firefox 和 Opera,在页面执行之前选择性地阻止或编辑页面的 javascript 并不难。在 Chrome 中这并不容易。此外,Firefox 对象可以被冻结,因此页面不能覆盖它们。
  • @BrockAdams 划掉了,谢谢
  • 回复:Rather, decide what needs to be guarded, and guard that. 为此 +1。不信任客户。始终在服务器端进行验证、清理和交叉引用。最后,如果数据是好的(并且没有违反游戏规则对他人造成伤害),那么客户做什么或如何做都无关紧要。 (不过,我怀疑 OP 是一个担心对策的脚本编写者。)
【解决方案2】:

如果你自己没有脚本来改变你冷的比较 document.body.innerHTML 和 document.head.innerHTL 的东西。

当您在脚本中更改 DOM 时,您可以更新值以进行比较。使用 setInterval 定期比较。

【讨论】:

  • 并非所有更改都可以通过这种方式检测到
  • 比如什么变化不会被检测到?我唯一能想到的就是调整窗口大小。使用 JS 进行的任何更改都会对 DOM 的属性/值或添加/删除 DOM 元素产生影响。这将改变innerHTML
  • 对不起,你是对的。输入文本值,用户定义的属性在更改时不显示,可能还有更多。
  • 更不用说您尝试进行的任何比较都必须使用可以由用户脚本修改的代码(即用户脚本可以修改您的控件,或者如果您比较,则修改与服务器的通信在服务器等)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2011-09-03
  • 1970-01-01
  • 2016-03-11
  • 2023-03-21
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多