检测代码是否作为Chrome扩展运行

kuhbmx9i  于 2022-12-06  发布在  Go
关注(0)|答案(8)|浏览(131)

我正在处理一些需要作为页面运行的代码,如果它作为Chrome Extension运行,我希望能够做其他事情。我使用的是:

<script>
if (chrome && chrome.extension) {
    // extension stuff
}
</script>

这看起来像是一个很好的capabilitydetection。使用用户代理字符串给我带来了麻烦,因为它是相同的,无论上下文(网页与扩展)。
问:是否有其他更可靠的技术来检测一段代码是否在Chrome扩展中运行?

**更新:**我想知道是否有什么东西可以放进我的manifest.json文件中,然后我可以读回来。注意,我正在开发的扩展并不是一个持续运行的东西,它是一个在单个窗口或浏览器标签中运行的内容应用程序,不需要与其他窗口或标签或其他任何东西交互。

hc2pp10m

hc2pp10m1#

这里有很多复杂的答案,而你可以通过检查chrome.runtime.id的存在性和非空性来轻松检测你是否在Chrome扩展中运行:

if (window.chrome && chrome.runtime && chrome.runtime.id) {
    // Code running in a Chrome extension (content script, background page, etc.)
}
332nm8kg

332nm8kg2#

我也需要类似的东西。
但是我不需要关心那些试图欺骗代码的网站。

const SCRIPT_TYPE = (() => {
    if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) {
        return 'BACKGROUND';
    } else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) {
        return 'POPUP';
    } else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) {
        return 'WEB';
    } else {
        return 'CONTENT';
    }
})();

以上应检测4种情况

  • javascript在后台页面中运行
  • javascript在弹出页面/ iframe中运行
  • javascript在上下文脚本中运行
  • javascript直接在网站上运行
t0ybt7op

t0ybt7op3#

实际上这是一个很好的方法。理论上(不确定这是否相关,例如可能提供漏洞)它很容易被欺骗。我想这取决于你的上下文。
这里有一个稍微强一点的想法:

if (chrome &&
    chrome.windows &&
    chrome.windows.get &&
    typeof chrome.windows.get === 'function' &&
    chrome.windows.get.toString() === 'function get() { [native code] }')

这个想法和你的想法是一样的,尽管它稍微更强一些,因为AFAIK让一个对象是一个函数,让它的toString()值具有该值是不可能的,因为它不是有效的语法,所以即使试图欺骗该值也不会起作用,除非你改变本机代码(这需要完全不同级别的黑客)。
不要随便记住检查这样的东西是否需要权限,但我希望这个想法是明确的。

更新

我刚刚意识到,“本地代码”语法的想法可能会被愚弄,通过别名一个现有的函数。

var FakeFn = Object.create;
FakeFn.toString(); // "function create() { [native code] }"

但是可以通过仔细选择使用哪个函数来解决这个问题,因为名称出现在字符串中。get可能太常见了,但是如果我们使用一个模糊的函数名(如chrome.tabs.captureVisibleTabcaptureVisibleTab),但它仍然是一个非常可移植的解决方案,因为与代码可能被其他本地用户代码欺骗的基本检查不同,我们事先知道浏览器不会实现任何具有此名称的本机函数,因此它在所有浏览器和所有用户代码中仍然是安全的。

更新

正如@Mathew所指出的,这个想法是愚蠢的(尽管看起来只是恶意的)。我以为我可以通过与Function.prototype.toString进行比较来修补这个问题,但我发现即使这样也可以通过别名化原始的toString方法并创建一个新的方法来欺骗,该方法对某些函数返回假字符串,对其他函数返回原始字符串。
总之,我的想法比原来的稍微强一点,因为它实际上排除了所有无意碰撞的机会(比OP的想法稍微强一点),但肯定不能像我最初认为的那样防御恶意攻击。

zf9nrax1

zf9nrax14#

我知道这是旧的,但我只是想提供一个替代方案。你可以添加另一个javascript文件到chrome扩展名,这样它就包含两个.js文件。manifest.json会有:

"js": ["additionalscript.js", "yourscript.js"]

js可以简单地声明一个变量var isextension = true。yourscript.js可以检查typeof isextension != 'undefined'
但也许一个更有趣的例子,它可以声明

var adminpassword='letmein'

现在yourscript.js只有在扩展中运行时才能访问adminpassword。
(Of当然,如果插件安装在可能受到危害的机器上,您不会在脚本文件中嵌入密码)

t3psigkw

t3psigkw5#

我注意到在Chrome中,chrome对象,也就是全局window对象的property,不能被删除.如果是用户自定义的property,删除操作就成功了.所以可以这样测试:

var isRunningInExtension = (!(delete window.chrome) && chrome.extension) ? 
                           true : false;

UPDATE:上面的行并不能保证代码在chrome扩展中运行。每个人都可以创建一个名为"chrome"的对象,并使用"extension"属性,然后冻结/密封该对象-这样做就足以通过检查,并得到一个错误的结果,即您的代码在chrome扩展中运行。
为了确保你在一个扩展中运行你的代码,你必须在运行任何javascript之前测试全局chrome对象--这样你就可以保证在测试之前没有假的chrome对象被创建。
One possible solution is to use an iframe - in my example below i use iframe's sandbox property to instruct the iframe not to execute any scripts(even scripts included with script tag) - in that way i can ensure no script will be able to modify the global window.chrome object.

(function() {
  var isChromeExtension = (function () {
    var contentWindow,
        iframe = document.createElement("iframe"),
        isChromeExtension;
    // test for sandbox support. It is supported in most recent version of Chrome
    if ("sandbox" in iframe) {
      try {
        iframe.sandbox = "allow-same-origin";
        iframe.src=location.href;
        iframe.style="display: none";
        document.body.appendChild(iframe);
        contentWindow = iframe.contentWindow;
        isChromeExtension = !!(contentWindow.chrome && contentWindow.chrome.extension);
        document.body.removeChild(iframe);
      } catch(e) {}
    }
    return isChromeExtension;
  }());
}());

结果可以是:

  • true-如果代码在Chrome扩展内运行
  • false-如果代码未在Chrome扩展内运行
  • undefined-如果浏览器不支持iframe的沙箱或在测试期间发生了一些错误
x9ybnkn6

x9ybnkn66#

Chrome没有提供任何直接的API来检查应用程序的运行状态,即它是在扩展弹出窗口中运行还是在Chrome页面视图中运行。然而,一个间接的技巧可以工作,我们可以匹配等于或小于CSS中指定的扩展体分辨率(在这种情况下,扩展弹出窗口将打开)或大于CSS中指定的分辨率(在这种情况下,网页视图将打开)。

lnxxn5zx

lnxxn5zx7#

Credit to Chad Scira for the original answer mine is based of.
I grabbed Chad's answer and I compacted it to ES2021 standards. Removed a lot of repeated content required for previous versions too.

const runningAt = (() => {
    let getBackgroundPage = chrome?.extension?.getBackgroundPage;
    if (getBackgroundPage){
        return getBackgroundPage() === window ? 'BACKGROUND' : 'POPUP';
    }
    return chrome?.runtime?.onMessage ? 'CONTENT' : 'WEB';
})();

The above should detect the 4 scenarios

  • javascript is run in a background page
  • javascript is run in a popup page / iframe
  • javascript is run in a context script
  • javascript is run in a directly on a website
oprakyz7

oprakyz78#

要检测chrome应用程序和扩展,请用途:

chrome.app.getDetails()

相关问题