Scriptlets icon indicating copy to clipboard operation
Scriptlets copied to clipboard

Improve `prevent-xhr` — blob response, randomized responseText with given length

Open AdamWr opened this issue 3 years ago • 2 comments

  • [x] Blob response
  • [x] Improve randomize responseText function - https://github.com/AdguardTeam/Scriptlets/issues/206#issuecomment-1158621281 (second part of the comment)

There is a website - https://www.kijk.nl/programmas/uefa-conference-league/FMLIrjHkfhXMWv which detects ad blockers if some xmlhttprequest are blocked.

Unfortunately, in this case, rule like this:

kijk.nl#%#//scriptlet('prevent-xhr', '/prebid/ad.gif')

breaks video player.

Screenshot

image

Anti adblock script:
case 0:
    (n = document.getElementById(p)) && n.remove(),
    (r = document.createElement("img")).setAttribute("id", p),
    r.setAttribute("class", "pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links ad-text adSense adBlock adContent adBanner"),
    r.setAttribute("style", "width: 1px !important; height: 1px !important; position: absolute !important;"),
    a = "".concat(c.a.getFeatureVariable(l.r.ADBLOCK_DETECTION, "baitURL") || "https://static.kijk.nl/prebid/ad.gif", "?user=").concat(f, "&slot=pre&ad-sense=1&adId=").concat(Date.now()),
    (i = new XMLHttpRequest).onreadystatechange = function() {
        if (4 === this.readyState && 200 === this.status) {
            var e = window.URL || window.webkitURL;
            return r.setAttribute("src", "function" === typeof(null === e || void 0 === e ? void 0 : e.createObjectURL) ? e.createObjectURL(this.response) : a),
                document.body.appendChild(r),
                t(!1)
        }
        if (4 === this.readyState)
            return t(!0)
    },
    i.open("GET", a),
    i.responseType = "blob",
    i.send();
case 12:
    case "end":
    return e.stop()
}

As far as I understand, it's due to this part:

e.createObjectURL(this.response)

Maybe we could check XMLHttpRequest.responseType and if it's a blob, then we could return something like new Blob(), as value here: https://github.com/AdguardTeam/Scriptlets/blob/9d4d2292aa249fbaf1e59a418dfffb7669088267/src/scriptlets/prevent-xhr.js#L131

AdamWr avatar Apr 07 '22 17:04 AdamWr

Very good idea!

ameshkov avatar Apr 08 '22 06:04 ameshkov

I think that it would be good idea to add something similar to prevent-fetch scriptlet. For example, this website - https://il.investing.com/indices/nasdaq-composite is checking Response.type if it's equal to opaque, and if it's not then it display adblock notice. Example rules:

investing.com#%#//scriptlet('prevent-fetch', 'pagead2.googlesyndication.com')
investing.com#%#//scriptlet('prevent-fetch', 'yandex.ru/ads/system/context.js')

Adding something like (as an additional option):

Object.defineProperty(response, 'type', { value: 'opaque', writable: false });

should fixes this issue (similar like in this case - https://github.com/AdguardTeam/Scriptlets/issues/216)


One more thing regarding prevent-xhr, related to this - https://github.com/AdguardTeam/Scriptlets/issues/199#issuecomment-1063271758 This website - https://streamingcommunity.press/watch/5190?e=37368 is checking length of responseText, something like:

a.get("https://thaudray.com/5/3523301")
  .then(function (e) {
    e.data.length < 2e4 && (t.adBlock = !0), s();
  })
  .catch(function (e) {
    console.log(e), o.can("bypass.ads") ? s() : (t.adBlock = !0);
  });

e.data.length < 2e4

Could randomize argument be improved, so we could manually set range of length of the responseText?

AdamWr avatar Jun 17 '22 08:06 AdamWr