Identifying non-default global variables in JavaScript
好的,我现在需要帮用户总结这篇文章的内容。用户的要求是用中文总结,控制在100字以内,不需要特定的开头,直接写描述。 首先,我仔细阅读了文章。文章主要讨论了单页应用中JavaScript如何存储全局变量,特别是通过window对象。作者提到通过比较不同网站的全局变量来检测差异,并提供了一个函数checkGlobal()来实现这一点。此外,还提到了使用哈希算法来更深入地比较变量变化,并开发了一个Chrome扩展来自动化这个过程。 接下来,我需要提取关键点:单页应用、JavaScript全局变量、window对象、比较方法、函数示例、哈希算法、Chrome扩展。这些都是文章的核心内容。 然后,我要将这些信息浓缩到100字以内。要确保涵盖主要方法和工具,同时保持语句简洁明了。 最后,检查是否有遗漏的重要信息,并调整句子结构以确保流畅自然。 </think> 文章讨论了单页应用中JavaScript通过`window`对象存储全局变量的方法,并介绍了一种通过比较默认全局变量和目标网站的全局变量来检测差异的技术。作者提供了一个函数`checkGlobal()`用于提取新增或修改的全局变量,并提到使用哈希算法进行更深入的比较。此外,还开发了一个Chrome扩展来自动化这一过程。 2019-4-1 01:22:31 Author: blog.jonlu.ca(查看原文) 阅读量:0 收藏

With the transition to single page apps, a lot of websites now store core information in actual stateful JavaScript rather than in text in HTML.

Comparing Windows

Web JavaScript stores its global variables within the window object (node, on the other hand, stores them in global).

The easiest and most straightforward way is to get all the default global variables in an empty page in Chrome and compare them to that of any other website we might want to check.

We can open up a new tab in Chrome and type:

This'll return a large array with all the default keys in the window namespace.

["postMessage", "blur", "focus", "close", "parent", ...]

From here we can write a quick function that checks what keys in a site aren't included.

function checkGlobal() {
  const currWindowKeys = Object.keys(window);
  const windowKeys = [...];
  return currWindowKeys.filter(value => !windowKeys.includes(value));
}

We can try our first check with a site like GitHub. Running checkGlobal() returns the following:

["System", "u2f", "ga", "gaplugins", "IncludeFragmentElement", "AutocompleteElement", "DetailsMenuElement", "GEmojiElement", "ImageCropElement", "MarkdownHeaderButtonElement", "MarkdownBoldButtonElement", "MarkdownItalicButtonElement", "MarkdownQuoteButtonElement", "MarkdownCodeButtonElement", "MarkdownLinkButtonElement", "MarkdownUnorderedListButtonElement", "MarkdownOrderedListButtonElement", "MarkdownTaskListButtonElement", "MarkdownMentionButtonElement", "MarkdownRefButtonElement", "MarkdownToolbarElement", "TabContainerElement", "TaskListsElement", "LocalTimeElement", "RelativeTimeElement", "TimeAgoElement", "TimeUntilElement", "ClipboardCopyElement", "DetailsDialogElement", "AutoCheckElement", "PollIncludeFragmentElement", "FileAttachmentElement", "FuzzyListElement", "FilterableInputElement", "_octo", "EmojiSuggesterElement", "checkGlobal"]

This was a somewhat naive check - we're just comparing key names, the check function does not compare overloaded or renamed, functions, or differences at nested depths. However, we're able to actually extract quite a bit of information. We can guess that the ga and gaplugins keys are for Google Analytics. The first key that pops out of interest is clearly _octo - we can then check out the object, and figure out what they're storing there. Oftentimes this'll include core state of the application, and make it so we don't actually need to scrape the webpage.

Deeper comparisons

We'd also like to define some sort of check for whether a variable has been overridden or renamed. All of the window variables can be renamed, so we want to make sure that we catch any changes a web page makes. There's an npm packaged called object-hash that defines per-object unique hashes. We can import this and pre-hash all the default window variables. We can then compare the hashes of any given pages global variables to the known ones. We'll run into some small issues (window.pageYOffset, for instance, is a variable that changes based on each site, and as such the hash will always be different) but for the most part it'll be a good indicator for any changes.

We can do that like so:

function checkGlobal() {
  const currWindowKeys = Object.keys(window);
  const unique = currWindowKeys.filter((value) => !Object.keys(originalWindowKeys).includes(value));
  const diffHash = [];
  for (const key of currWindowKeys) {
    if (Object.keys(originalWindowKeys).includes(key)) {
      try {
        // if hashes don't match and the hash isn't an unhashable (marked with _ above)
        if (objectHash.sha1(window[key]) !== originalWindowKeys[key] && originalWindowKeys[key] !== "_") {
          diffHash.push(key);
        }
      } catch (e) {
        // do nothing, fail silently
      }
    }
  }
  return {
    unique,
    diffHash,
  };
}

I made a small chrome extension that does this for you - it compares unique keys, and hash keys, and logs them to the console for any given page.

This works well - clicking the chrome extension icon immediately shows me the different global variables, which for my site are different analytics modules.

Personal sites different global vars

Personal sites different global vars

My personal sites global variable differences

Future work

In the future I hope to do recursive object checks (for instance, verify that window.Array doesn't have any appended keys) as well as smarter hashes of objects. The library we're using now is ok but it still fails to hash a non-trivial amount of objects.


文章来源: https://blog.jonlu.ca/posts/window-vars
如有侵权请联系:admin#unsafe.sh