【问题标题】:Can a webpage detect a tampermonkey userscript?网页可以检测到篡改用户脚本吗?
【发布时间】:2019-06-29 21:41:24
【问题描述】:

我的问题有两个方面。 首先,沙盒模型的工作原理,它如何影响用户脚本,从网页和用户脚本的角度可以访问/看到的内容,以及使用不同的沙盒模型是否会影响页面能够注意到您的脚本被注入页面(或不注入)。 ,脚本是如何注入页面的,页面能检测到吗?

第一

据我所知,当您使用@grant none 时,沙箱被禁用,您将可以访问该网页及其 javascript。如果您对 javascript 和/或 DOM 进行任何更改,页面可能会检测到它。

我的理解是,如果你使用@grant unsafeWindow,你的脚本将被隔离在它自己的js上下文中,你对window所做的任何事情都不会被网页看到,但是你可以通过@访问网页和javascript 987654325@。您将可以定期访问 DOM,例如document 返回常规页面文档,而不是您需要说 unsafeWindow.document。显然,您对 DOM 或页面 js 上下文(例如unsafeWindow.foo = 'bar';)所做的任何更改仍然可以检测到。它是unsafe 的原因不是因为是否被检测到,而是因为您可以在此模式下潜在地授予不受信任的页面访问特权GM_* 功能(在常规模式下不授予这些功能,这意味着@grant GM_* 任何函数都会隔离 js 上下文,除非你 @grant unsafeWindow)

第二

脚本是如何注入页面的?网页是否有可能注意到用户脚本注入(假设用户脚本在页面上没有修改任何内容)。

例如,如果一个脚本是使用script标签注入的,我认为页面可能会注意到脚本注入,甚至看看它的代码?

沙盒模型在这种情况下是否起任何作用,并使其“更安全”不被看到?例如,如果使用@grant unsafeWindow,js上下文是隔离的,那么网页上的js可能甚至看不到任何用户脚本加载事件,使@grant unsafeWindow从根本上更安全,除非你去修改DOM或unsafeWindow当然。

我还假设没有泄漏特殊功能、对象、属性等(例如 GM_info 到网页,这会暴露 Tampermonkey 的存在?)。在@grant none 模式或@grant unsafeWindow 模式下都不行(前提是您没有向页面泄露任何内容)

这让我觉得unsafeWindow 在不被发现方面实际上更安全(因为 js 上下文是隔离的),只要你不去修改任何东西(特别是不要暴露特权 GM_* unsafeWindow 的功能)。 例如,如果你在@grant none模式下使用了一个eventListener,它可能会被检测到,但是如果你在@grant unsafeWindow模式下使用它,它可能因为隔离而无法被检测到?此外,如果页面可以检测到用户脚本加载(我不知道这是否真的可能),它不会知道 js 上下文是否被隔离

简而言之,如果您不背叛,页面能否检测到您的用户脚本或篡改猴子的存在?

我上面的任何想法在任何领域都不正确,如果是,它实际上是如何工作的?

更新

需要澄清的一点信息:

用户脚本只能被动地从页面读取信息(可能使用 MutationObserver)。它不会以任何方式改变任何东西,不使用任何 js 库(既来自用户脚本也来自网页)没有 ajax 调用,没有脚本节点,绝对没有点击等。脚本可以从 JS vars 读取一些信息页面(让我们假设这些变量和函数没有被诱杀),以及使用 WebSocket(内部服务)。也使用 IIFE。所以问题主要是,tampermonkey 本身(如果它运行页面脚本)是否可以检测到?

在这个答案中:https://stackoverflow.com/a/8548311 我可以排除1、4、5、6和7;可能还有 2 和 3,但我不知道 Tampermonkey 本身是否会影响其中任何一个

【问题讨论】:

    标签: javascript google-chrome sandbox tampermonkey userscripts


    【解决方案1】:

    浏览器和 Greasemonkey/Tampermonkey/Violentmonkey (大部分)改进了注入、作用域和沙盒的方式。用户脚本不是使用普通的<script> 标签注入的(尽管您的脚本在某些情况下可能需要创建这样的标签)。

    其实现在there's almost no need to use an IIFE

    但是,除了previously linked question中的检测方法:

    1. @grant none模式下,如果你@require一个库自己复制到window作用域,页面可以看到。大多数库不这样做,但有一个是 jQuery
    2. Tampermonkey actually provides the installed script version 到在高级设置中列入白名单的网站。这主要适用于 greasyfork.org 等脚本宿主。
    3. 我不知道页面是否可以检测到用户脚本正在使用的 WebSocket。我对此表示怀疑。

    底线是对于“只读”用户脚本,在@grant none 模式下不require 全局库,页面无法检测到它。 (除非页面是 greasyfork.org 等,并且你有 Allow communication with cooperate pages 设置为默认值。)

    如果您发现一些泄漏,页面可以检测到“被动”脚本,请告诉我们,它可能会被堵塞。

    【讨论】:

    • 这主要是我的想法。因此,(至少)常规和明显的方法不应该能够检测到存在。在@grant none 模式下,window 作用域是真正的窗口作用域,但在@grant unsafeWindow 模式下,js 上下文是分开的,从而使用户脚本window 对象更安全,对吧?因此,在某些情况下,就检测而言,unsafeWindow 可能更安全(只是不要公开你的存在,也不要通过unsafeWindow 泄露特权功能)?
    • 正确,在授权模式下,脚本更难被检测到(你几乎可以偷偷地@require 任何东西)。但是@grant unsafeWindow 有一些怪癖;没有调查它们是否已修复。我改用@grant GM_addStyle
    • 似乎使用授权模式允许人们在不改变原始页面范围的情况下污染window 范围。同时,您仍然可以访问原始页面的 javascript。凉爽的!对于您建议的@grant GM_addStyle,无需通过unsafeWindow 访问它。不知道它如何阻止用户脚本污染window,但同时允许它检索任何东西,但很酷!
    【解决方案2】:

    正如答案https://stackoverflow.com/a/8548311 所提到的,如果你做了类似的事情它肯定是可以检测到的。 但是,根据你想用 Tampermonkey 脚本做什么,它会更容易或更容易难以检测,在某些情况下不可能

    根据您的要求,您想要做的似乎只是从页面调用 IIFE,然后停在那里,“假设它只是读取信息”。

    这真的很难捕捉,通常为此,页面应该必须将其他用户的分析器和执行时间等与您或其他一些时髦的东西进行比较,并且没有真正简单的方法来找出是否用户在页面中执行了额外的 JS(只要您使用 IIFE),它具有 NO SIDE EFFECT。我并不是说它是 100% 无法检测到的,而是说它真的很棘手。

    如果您要修改 DOM、对外部或内部服务进行 API 调用、用户的虚假移动 或其他类似的事情,您将被检测到。所以,这取决于你想对页面做什么,但你可以“很容易”被检测到。

    简而言之,如果您不背叛,页面能否检测到您的用户脚本或篡改猴子的存在?

    是的,在您在页面中留下痕迹的情况下(如上所述),页面可以检测到这些情况。请记住,只有在页面有理由想知道这种情况是否发生时,才会发生这种情况。还要记住,没有任何页面会仅仅为了它而实现这样的东西,所以不要指望普通页面会抱怨这一点。

    【讨论】:

    • 你是对的。我的想法是用户脚本只能被动地从页面读取信息(可能使用 MutationObserver)。它不会改变任何东西,没有 ajax 调用,没有脚本节点,绝对没有点击,绝对没有以任何方式修改页面。但是,脚本可以从页面上的 JS 变量中读取一些信息(假设这些变量和函数没有被诱杀),以及使用 WebSocket(内部服务)。是的,也使用 IIFE。所以问题主要是,tampermonkey 本身是否会以这样的方式做事,让网站知道脚本正在运行?
    • 正如其他用户解释的那样,对于 只读 脚本不,页面将无法检测到它。
    【解决方案3】:

    亚马逊实现了一些等待 3 或 4 秒然后检索所有控制台信息的东西。

    这就是它的样子

    {
        "logs": [{
            "level": "error",
            "message": "Cannot set property 'checked' of null",
            "error": {
                "errorMessage": "Cannot set property 'checked' of null",
                "errorName": "TypeError",
                "errorStackTrace": "TypeError: Cannot set property 'checked' of null\n    at storageUpdate (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/userscript.html?name=myUserscript).user.js&id=ea4d27bb-1f9a-44e5-847c-2f61122b4d75:14467:86)\n    at Window.configModal (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/userscript.html?name=myUserscript).user.js&id=ea4d27bb-1f9a-44e5-847c-2f61122b4d75:14488:29)\n    at <anonymous>:3:100\n    at E.z.<computed> (eval at exec_fn (:1:157), <anonymous>:43:442)"
            },
            "context": {
                "logTime": 1610058101393
            }
        }]
    }
    

    它是新的,无论他们是否针对我,他们都可以清楚地看到 Tampermonkey 正在工作:

    chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/

    【讨论】:

    • 我们如何重现它?它发生在哪些页面上?以及具有哪些脚本权限等?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2012-01-10
    • 2021-09-13
    • 1970-01-01
    • 2011-09-03
    相关资源
    最近更新 更多