简体   繁体   English

在加载并运行脚本之前,在<head>中编辑<script>标记

[英]Edit a <script> tag in the <head> before it loads and runs the script

I am on an e-commerce platform where I can edit the <head> , however some things that are injected into the head are out of reach for users. 我在一个电子商务平台上,我可以编辑<head> ,但是注入头部的一些东西对用户来说是遥不可及的。 So even though we can edit the <head> , there are injections which are out of reach and therefore unremovable via the traditional method. 因此,即使我们可以编辑<head> ,也会出现无法触及的注射,因此通过传统方法无法移除。
PS: I can put script before or after these injected JS script tags, which are generated and populated along with my scripts. PS:我可以在这些注入的JS脚本标记之前或之后放置脚本,这些脚本标记是与我的脚本一起生成和填充的。 And so my script would run before the injected tags if I place my script before their "tag injection line." 因此,如果我将脚本放在“标记注入行”之前,我的脚本将在注入标记之前运行。


The Problem 问题

The problem is, this platform started injecting analytics and spam into the head, basically jacking our customers info and selling it to third parties. 问题是,这个平台开始将分析和垃圾邮件注入头部,基本上是在向客户提供信息并将其出售给第三方。 So I want to disable their crappy scripts. 所以我想禁用他们糟糕的脚本。

<script type="text/javascript" async="" src="/some.JS.file.min.js"></script>
<script type="text/javascript" async="" src="/another.JS.file.min.js"></script>

The Question 问题

Is it possible with javascript or jquery to write a script that will edit tags before they run? 是否可以使用javascript或jquery编写一个脚本,在运行之前编辑标签? I can insert this custom script before the tags are in injected. 我可以在注入标记之前插入此自定义脚本。 I was wrong -- the unwanted <script> tags are always PREpended to the first non-commented <script> tag, and so no javascript will work to hack up the tags before they run. 我错了 - 不需要的<script>标签总是预先添加到第一个未注释的<script>标签,因此在运行之前没有javascript可以用来破解标签。


What I Have Tried So Far 我迄今为止所做的一切

I found this incomplete and not working answer from this SO question . 我发现这个不完整而且没有从这个SO问题回答

When I run the full script with the right details entered for my own site, I get so many errors it's difficult to know where to begin as I have no idea what all the XHR stuff is for or what it does, and some of the errors are ones I've never even seen before. 当我运行完整的脚本并为我自己的网站输入正确的详细信息时, 我会收到很多错误 ,很难知道从哪里开始,因为我不知道所有XHR的内容是什么或它做了什么,以及一些错误是我以前从未见过的。

When I run just this part, which I somewhat understand: 当我运行这部分时,我有点理解:

doc = document.implementation.createHTMLDocument(""+(document.title || ""));

scripts = doc.getElementsByTagName("script");
//Modify scripts as you please
[].forEach.call( scripts, function( script ) {
    if(script.getAttribute("src") == "/some.JS.file.min.js"
       || script.getAttribute("src") == "/another.JS.file.min.js") {

        script.removeAttribute("src");
    }
});

EDIT UPDATE: 编辑更新:

Their script is inserted AFTER my scripts. 他们的脚本是在我的脚本之后插入的。 That is, I can insert the script into the <head> before their script tags or after. 也就是说,我可以在脚本标记之前或之后将脚本插入<head> We are looking into new platforms now but I still need to solve this in the meantime as it will be months before we switch. 我们现在正在寻找新的平台,但我仍然需要在此期间解决这个问题,因为我们需要几个月才能切换。 I was hoping g there is some JavaScript I am not aware of that can edit HTML script tags before they run, if this script runs before they do. 我希望有一些我不知道的JavaScript可以在运行之前编辑HTML脚本标记,如果这个脚本在它们运行之前运行的话。

EDIT 2: 编辑2:

Nit's answer window.bcanalytics = function () {}; Nit的答案 window.bcanalytics = function () {}; works great and breaks most of it by breaking window.bcanalytics.push but somehow some of it still survives. 通过打破window.bcanalytics.push工作得很好并打破了大部分,但不知何故,其中一些仍然存在。

In this block: 在这个块中:

    <script type="text/javascript">

(function() {
    window.bcanalytics || (window.bcanalytics = []), window.bcanalytics.methods = ["debug", "identify", "track", 
        "trackLink", "trackForm", "trackClick", "trackSubmit", "page", "pageview", "ab", "alias", "ready", "group", 
        "on", "once", "off", "initialize"], window.bcanalytics.factory = function(a) {
        return function() 
        {
            var b = Array.prototype.slice.call(arguments);
            return b.unshift(a), window.bcanalytics.push(b), 
            window.bcanalytics
        }
    };
    for (var i = 0; i < window.bcanalytics.methods.length; i++) 
    {
        var method = window.bcanalytics.methods[i];
        window.bcanalytics[method] = window.bcanalytics.factory(method)
    }
    window.bcanalytics.load = function() {
        var a = document.createElement("script");
        a.type = "text/javascript", 
        a.async = !0, a.src = "http://cdn5.bigcommerce.com/r-2b2d3f12176a8a1ca3cbd41bddc9621d2657d707/app/assets/js/vendor/bigcommerce/analytics.min.js";
        var b = document.getElementsByTagName("script")[0];
// This line still runs and loads analytics.min.js
// This line still runs and loads analytics.min.js
// This line still runs and loads analytics.min.js
        b.parentNode.insertBefore(a, b)
// ^^^ This line still runs and loads analytics.min.js
// This line still runs and loads analytics.min.js
// This line still runs and loads analytics.min.js
    }, window.bcanalytics.SNIPPET_VERSION = "2.0.8", window.bcanalytics.load();
    bcanalytics.initialize({"Fornax": {"host": "https:\/\/analytics.bigcommerce.com","cdn": "http:\/\/cdn5.bigcommerce.com\/r-2b2d3f12176a8a1ca3cbd41bddc9621d2657d707\/app\/assets\/js\/vendor\/bigcommerce\/fornax.min.js","defaultEventProperties": {"storeId": 729188,"experiments": {"shipping.eldorado.ng-shipment.recharge-postage": "on","shipping.eldorado.label_method": "on","cp2.lightsaber": "on","PMO-272.cp1_new_product_options": "on","cart.limit_number_of_unique_items": "control","cart.auto_remove_items_over_limit": "control","BIG-15465.limit_flash_messages": "control","BIG-15230.sunset_design_mode": "control","bigpay.checkout_authorizenet.live": "on","bigpay.checkout_authorizenet.live.employee.store": "control","bigpay.checkout_authorizenet.test": "on","bigpay.checkout_authorizenet.test.employee.store": "control","bigpay.checkout_stripe.live": "on","bigpay.checkout_stripe.live.employee.store": "control","bigpay.checkout_stripe.test": "on","bigpay.checkout_stripe.test.employee.store": "control","sessions.flexible_storage": "on","PMO-439.ng_payments.phase1": "control","PMO-515.ng_payments.phase2": "control","PROJECT-331.pos_manager": "control","PROJECT-453.enterprise_apps": "control","shopping.checkout.cart_to_paid": "legacy_ui","onboarding.initial_user_flow.autoprovision": "on","faceted_search.enabled": "off","faceted_search.displayed": "off","themes.previewer": "enabled"}},"defaultContext": {"source": "Bigcommerce Storefront"},"anonymousId": "24a35a36-7153-447e-b784-c3203670f644"}});
})();
</script>

window.bcanalytics.load manages to survive and loads analytics.min.js (according to the Network tab), though I can't tell if the script then runs or doesn't. window.bcanalytics.load设法生存并加载analytics.min.js(根据网络选项卡),虽然我无法判断脚本是否运行或不运行。

Also, I've figured out that these pesky HTML lines: 另外,我已经发现这些讨厌的HTML行:

<script type="text/javascript" defer="" async="" src="http://tracker.boostable.com/boost.bigcommerce.js"></script>
<script type="text/javascript" async="" defer="" src="http://cdn5.bigcommerce.com/r-2b2d3f12176a8a1ca3cbd41bddc9621d2657d707/javascript/jirafe/beacon_api.js"></script>
<script type="text/javascript" async="" src="http://cdn5.bigcommerce.com/r-2b2d3f12176a8a1ca3cbd41bddc9621d2657d707/app/assets/js/vendor/bigcommerce/analytics.min.js"></script>
<script type="text/javascript" async="" src="http://www.google-analytics.com/plugins/ua/ecommerce.js"></script>

are Always PREpended to the first non-commented <script> opening tag, so unfortunately, none of the creatively destructive methods below will work, as any script I try to insert ahead of these tags will automatically find the pesky unwanted lines appended before it. 总是预先添加到第一个未注释的<script>开始标记,所以不幸的是,下面没有任何创造性破坏性的方法可以工作,因为我尝试在这些标记之前插入的任何脚本将自动找到在它之前附加的讨厌的不需要的行。

Assuming the offending code is similar to that of the question you linked to, I would simply try to break the offending code so it fails to execute. 假设违规代码与您链接的问题类似,我只想尝试打破违规代码,使其无法执行。
From hereon the answer relies on code from the other question since you didn't provide any. 从这里开始,答案依赖于另一个问题的代码,因为你没有提供任何代码。

The offending code relies on analytics, which is ensured on the page at the beginning of the script: 违规代码依赖于分析,这在脚本开头的页面上得到了保证:

(function(){
    window.analytics||(window.analytics=[]),window.analytics.methods=["debug","identify","track","trackLink","trackForm","trackClick","trackSubmit","page","pageview","ab","alias","ready","group","on","once","off","initialize"],window.analytics.factory=function(a){return function(){var b=Array.prototype.slice.call(arguments);return b.unshift(a),window.analytics.push(b),window.analytics}};for(var i=0;i<window.analytics.methods.length;i++){var method=window.analytics.methods[i];window.analytics[method]=window.analytics.factory(method)}window.analytics.load=function(){var a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src="http://cdn2.bigcommerce.com/r6cb05f0157ab6c6a38c325c12cfb4eb064cc3d6f/app/assets/js/analytics.min.js";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b)},window.analytics.SNIPPET_VERSION="2.0.8",window.analytics.load();
    //The rest of the script
})();

To break the whole script and prevent it from running you should simply assign window.analytics a value that will conflict with the methods that are used. 要破坏整个脚本并阻止它运行,您应该只为window.analytics分配一个与使用的方法冲突的值。
So, for example, you could run a script before the offending script that simply assigns the following: 因此,例如,您可以在简单地分配以下内容的违规脚本之前运行脚本:

window.analytics = function () {};

Which will result in the offending script failing due to a type error. 这会导致违规脚本因类型错误而失败。

If you know you can at least get your scripts to run first, one (albeit hacky) solution is to just absolutely "trash" the JS environment for the next script, so it has some problems. 如果你知道你至少可以让你的脚本首先运行,那么一个(尽管是hacky)解决方案就是绝对“废弃”下一个脚本的JS环境,所以它有一些问题。 For example: 例如:

//trash it
document.getElementById=null;
document.querySelector=null;
document.querySelectorAll=null;
window.console=null;
window.alert=null;
document.getElementsByTagName=null;
document.getElementsByClassName=null;

As soon as the enemy script tries using one of those functions, it will just crap out. 一旦敌方脚本尝试使用其中一个功能,它就会被废弃。 Those are just some common methods off the top of my head... find out which ones its using, and nuke those. 这些只是我头脑中的一些常见方法...找出它使用哪些,并核对那些。 Of course, nuking anything you need for events on your own page could be an issue. 当然,在您自己的页面上为事件所需的任何东西都可能是一个问题。

How are the scripts being injected? 如何注入脚本? If it's through something like document.createElement , you could attempt to hijack that function and disable it if the element name is script : 如果它是通过document.createElement之类的东西,你可以尝试劫持该函数并在元素名称是script禁用它:

var origCreate = document.createElement;
document.createElement = function (name) {
  if (name.toLowerCase() !== 'script') {
    origCreate.call(document, name);
  }
};

Since the scripts are being inserted server-side , you won't be able to disable the running of the scripts in your JavaScript. 由于脚本是在服务器端插入 ,因此您将无法在JavaScript中禁用脚本的运行。 However, if you're able to inject any arbitrary text before and after the scripts being inserted, you could try commenting out the script tags by inserting this first: 但是,如果您能够在插入脚本之前和之后注入任意文本 ,您可以尝试通过先插入脚本标记来注释掉它:

<!--

...then this after: ......然后这个:

-->

If the scripts get injected between these, it will hopefully cause the HTML parser to ignore the scripts. 如果脚本在这些脚本之间注入,则有望使HTML解析器忽略脚本。

Update : 更新

Sounds like you need to disable just some of this content, so commenting everything out won't work. 听起来你需要禁用其中的一些内容,所以评论一切都行不通。 However, if before/after hijacking works, you could potentially wrap the injected scripts in a DOM element, parse that content, strip out the scripts you don't want, and inject the scripts so they run: 但是,如果在劫持之前/之后工作,您可以将注入的脚本包装在DOM元素中,解析该内容,删除不需要的脚本,并注入脚本以便它们运行:

Inject something like this before: 之前注入这样的东西:

<style id="hijack" type="text/html">

...and this after: ......之后:

</style>
<script>
  var hijackedWrapper = document.getElementById('hijack');
  var scripts = hijackedWrapper.textContent;
  scripts = scripts.replace('<script src="http://some.domain.com/foo.js"></s' + 'cript>', '');
  document.write(scripts); // There's better ways to do this, but is just an illustration
</script>

Like the others, I would suggest sabotaging the js environment for the hostile script, and then recovering it back once you need it. 和其他人一样,我建议破坏js环境以获取敌对脚本,然后在需要时将其恢复。

For example, if the script relies on document.getElementById , you can do this 例如,如果脚本依赖于document.getElementById ,则可以执行此操作

var restore = {
  getElementById: document.getElementById
};
document.getElementById = null;

and then if you have a need to use document.getElementById later, you can restore it back: 然后,如果您以后需要使用document.getElementById ,则可以将其恢复:

document.getElementById = restore.getElementById;

I also wanted to note that removing the actual script tags, as far as I can tell, is not possible: 我还想注意,据我所知,删除实际的脚本标签是不可能的:

  • If you put in a script before the hostile scripts, then they will not be loaded in the DOM yet, so it can't see anything to remove. 如果你在恶意脚本之前放入一个脚本,那么它们将不会被加载到DOM中,所以它看不到要删除的内容。
  • If you put in a script after the hostile scripts, the hostile scripts will already be loaded. 如果您在恶意脚本之后放入脚本,则已经加载了恶意脚本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 $(document).ready(function(){…})在插件脚本加载之前运行 - $(document).ready(function() {…}) runs before plugin script loads <Tag>之前<Script> Tag - <Tag> before <Script> Tag 是不是写的比较快<script defer> just before the </ head> tag than before the </ body> tag until the processing is completed? - Is it faster to write <script defer> just before the </ head> tag than before the </ body> tag until the processing is completed? 用于加载脚本标签的 Polyfill<head> - Polyfill for onload of script tag in <head> 在之前的Echo PHP var </head> (闭合头)标签,以便使用Java脚本进行检索 - Echo php var before the </head> (closing head) tag in order to retrieve it with java script uiOutput 忽略<head>要么<script> tag - uiOutput ignores <head> or <script> tag "在 iframe 加载之前运行脚本" - Run script before iframe loads 我发现在 </head> 我有标签 <script id=“__isTpiViewExists”></script> 。 这是病毒吗? - I have found that just before the </head> tag I have <script id=“__isTpiViewExists”></script>. Is this a virus? 确保在另一个脚本之前加载某个脚本 - Ensure that a certain script loads before another script 里面的Javascript代码 <BODY> 在*之前运行* <SCRIPT>s in <HEAD> are fully loaded? - Javascript code inside <BODY> runs *before* <SCRIPT>s in <HEAD> are fully loaded?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM