4

I had a client contact me today because a website I developed (that deals with sensitive information) wasn't loading correctly on one computer on Chrome. After poking around for a while it appears to be caused by the underlying source code being manipulated in Chrome. The code injection (a javascript snippet) appears BEFORE any DOM is parsed, and is actually happening to all sites she visits that have a <title> tag (the code is inserted before any <title> text in the code... it isn't parsing the DOM because the insertions are happening even if the <title> string is inside a pre tag or textarea. Given that you can see the injection directly in view-source I'm fairly certain this isn't being injected by a plugin/extension (which I don't believe can modify source code before the DOM is registered). And the fact that it is happening on https sites means I assume it's something installed on the client's computer that's doing the code manipulation.

The injected code (reformatted for readability) is:

function getRandomInt(max) {
    return Math.floor(Math.random() * Math.floor(max));
}

function shuffle(array) {
    var currentIndex = array.length,
        temporaryValue, randomIndex;
    while (0 !== currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }
    return array;
}

var __toUserAgent = window.navigator.userAgent;
Object.defineProperty(window.navigator, "userAgent", {
    get: function () {
        return __toUserAgent + '/b3S2rCM5-8';
    }
});
var testPlugins = [];
for (var s = 0; s < window.navigator.plugins.length; s++) {
    var plg = {
        'name': window.navigator.plugins[s].name,
        'description': window.navigator.plugins[s].description,
        'filename': window.navigator.plugins[s].filename,
    };
    plg[0] = {
        'type': window.navigator.plugins[s][0].type,
        'suffixes': window.navigator.plugins[s][0].suffixes,
        'description': window.navigator.plugins[s][0].description
    };
    testPlugins.push(plg);
}
if ({
        'name': 'VT AudioPlayback',
        'description': 'VT audio playback',
        'filename': 'vtaudioplayback.dll',
        '0': {
            'type': 'application/vt-audio',
            'suffixes': '',
            'description': ''
        }
    }, {
        'name': 'ChanWebPlugin',
        'description': 'Chanw checking plugin',
        'filename': 'chanwebplugin.dll',
        '0': {
            'type': 'application/chan-web',
            'suffixes': '',
            'description': ''
        }
    }) testPlugins.push({
    'name': 'VT AudioPlayback',
    'description': 'VT audio playback',
    'filename': 'vtaudioplayback.dll',
    '0': {
        'type': 'application/vt-audio',
        'suffixes': '',
        'description': ''
    }
}, {
    'name': 'ChanWebPlugin',
    'description': 'Chanw checking plugin',
    'filename': 'chanwebplugin.dll',
    '0': {
        'type': 'application/chan-web',
        'suffixes': '',
        'description': ''
    }
});
testPlugins = shuffle(testPlugins);
Object.defineProperty(window.navigator, "plugins", {
    get: function () {
        return testPlugins;
    },
    enumerable: true,
    configurable: true
});

Basically, it seems to be editing the browser userAgent string slightly and then randomizing an array of plugin details, and then attempting to set the registered plugins on the browser.

Two questions:

  1. I don't see how this would actually do any damage, but are there specific security concerns about the JS code being rendered here (we checked her bank's website and the code was being injected there as well)?

  2. How is it possible for the underlying source to be changed? I understand JS-powered code injection attacks, but in this case the actual original source appears to have been edited. So html served via https is being changed on the fly (so it looks like the remote server actually sent the code). I was wondering if her Antivirus (AVG) might have been the culprit, but disabling protected temporarily didn't seem to fix it.

  3. If AVG didn't cause or prevent the issue, any thoughts on how to prevent this?

5
  • Just to rule out any sort of MITM attack - When she connects to the site in Chrome, does Chrome show the true and correct certificate for the site?
    – mti2935
    Commented Dec 30, 2020 at 22:07
  • @mti2935 - that's a good question - briefly checked that the certificate was registering as valid (browser recognized it as a valid issuer) but if the browser was compromised it's possible that the CACert is broken too. I'll check and report back.
    – Ben D
    Commented Dec 30, 2020 at 23:00
  • 1
    Did you look for browser plugins on the affected machine? Does the same thing happen in IE, Chrome, Firefox, etc?
    – Polynomial
    Commented Dec 31, 2020 at 0:03
  • @Polynomial - it was only impacting Chrome when I checked.
    – Ben D
    Commented Dec 31, 2020 at 4:19
  • 1
    @BenD Probably a plugin injecting the content, then.
    – Polynomial
    Commented Dec 31, 2020 at 6:08

3 Answers 3

6

tl/dr: It's definitely a plugin doing this, and is almost certainly a privacy-focused plugin that is trying to randomly obfuscate your user agent and plugin list to hide you from sites performing browser fingerprinting. However it is doing it very poorly and I'm dubious that the people who wrote this knew what they were doing. So while there likely isn't a security risk, I'd probably ditch this particular plugin anyway.

Since this is injected into the source of just a single browser there are only two ways it could happen:

  1. Compromised browser
  2. A plugin/extension

However, it is almost certainly a plugin/extension. You can verify it easily by turning off all the extensions on the browser and seeing if it goes away. I expect this will solve the issue immediately. Turn them back on one-by-one to find the culprit.

Potential Security Concerns

Are there potential security concerns here? Yes and no. The fact that this code seems innocuous doesn't mean it is safe, because there is something injecting code into every website you visit. Without knowing where the code is coming from, who is to say it doesn't turn into a keylogger on your bank website tomorrow?

Most likely though this is a plugin, so the only question is "What plugin is doing this?". If it is a plugin from a reputable company that is doing exactly what it is supposed to be doing (more about that below), then you are probably fine. Injecting code into all websites is actually perfectly normal for plugins, and is why you need to be very careful about installing plugins judiciously, only when necessary, and from entities you trust.

Purpose

Based on your code though, I think we can say a bit more about what this plugin is doing, and so which one may be responsible. As you say, this (poorly) written code is trying to "change" the user agent string and list of plugins. It's important to note though that neither of those things can be changed with Javascript like this, and a plugin author would (probably) know that.

Instead, what this is doing is changing the user agent and list of plugins as reported to JavaScript running on the page. Keep in mind that this would not affect the actual User Agent that the browser reports in requests, nor would it affect the actual plugins running on the tab.

Instead, this is most likely meant to help hide the browser from JavaScript libraries that use browser fingerprinting to track users. User agents and the plugin list are two common items used for browser fingerprinting. Therefore, this is likely the result of a privacy-focused plugin.

I have to say though that this is very poorly executed, for a number of reasons:

  1. You hide from fingerprinting with conformity, not randomness. Having a random user agent actually makes you stick out more.
  2. Since it only fires on pages with a <title> tag, and not all pages have one, it doesn't protect you everywhere. It's not that hard to inject it in a smarter way that will cover 100% of sites.
  3. User agent string and the list of plugins are only a small part of browser fingerprinting, and not necessarily the most important parts. If that is all they are trying to obfuscate then this may not be very effective anyway.
  4. The code is just poorly written.

As a result, I might suggest ditching this particular plugin, especially since it is causing usability issues.

7
  • OP, if this is the case, can you please report back here with the name of the plugin that is doing this? WRT, Given that you can see the injection directly in view-source I'm fairly certain this isn't being injected by a plugin/extension (which I don't believe can modify source code before the DOM is registered). I'm fairly certain as well that a plugin cannot directly modify the source, only the DOM. If this plugin is in fact directly modifying the source, I would be curious to see how it is doing this.
    – mti2935
    Commented Dec 31, 2020 at 11:18
  • @mti2935 plugins can arbitrarily modify HTTP responses and are specifically designed so that they can inject content into pages, so it is certainly possible. It's just a question of whether or not that would also apply to the view source page. It probably would but I have never checked that detail Commented Dec 31, 2020 at 12:41
  • You're right, I think this is how the extension might be modifying the page source: developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/… +1. I think this is the most plausible explanation for what the OP is seeing.
    – mti2935
    Commented Dec 31, 2020 at 13:12
  • @mti2935 I'd love to get confirmation from the OP as well. This makes enough sense that it seems very likely that my answer is correct, but I'm not 100% sure. After all, who knows what is going on in some random person's browser! Commented Dec 31, 2020 at 13:35
  • Thanks for the thorough review! I did check the installed extensions on the browser (my understanding is that plugins are no longer available in Chrome and chrome://plugins resulted in a 404). There were only two non-default plugins" Dragon Dictation and an AVG extension. AVG seems like the most plausible culprit here (privacy would be within its scope) BUT I actually tried disabling it and the injection continued. I'll have the client uninstall it, but are Extensions capable of direct injection like plugins? Anywhere else I could look?
    – Ben D
    Commented Dec 31, 2020 at 16:38
3

The same code as in the question appears on every site I visit. It happens in all browsers I have (Edge, Chrome, Firefox).

Then it occurred to me that I use software from Piriform (distributor of the famous/infamous CCleaner). This software is called Kamo and one thing it does is to mask user metadata that can be collected on the internet by randomizing it.

When I turn "Browser Protection" in Kamo settings off the injected code is removed. Turning it on again and it appears again.

2
  • Do you happen to know how "Kamo" does this? My best guesses are browser extensions (easy, mostly reliable, but somewhat visible) or DLL/SO injection that hooks some browser functions (possible but much more work, fragile to major browser updates, much harder to see). You could check for this by comparing the list of loaded modules (binary images, including DLLs) with it on and off, and in particular seeing if the browser loads one from Kamo. On Windows, you can see loaded modules using tools like Resource Monitor or the CLI tasklist.exe via e.g. tasklist /m /fi "IMAGENAME eq firefox.exe".
    – CBHacking
    Commented Aug 16, 2021 at 22:14
  • Sorry to say, but that's above my knowledge. I disabled all extentions in my browsers when testing so I'm quite sure that's not how they do it. Commented Aug 17, 2021 at 16:51
-1

So it's only happening on that one computer, other machines don't see this, correct?

I've seen something similar before and it was a compromised JavaScript remote library call.

If it's only on the one computer, it may be a hosts file issue directing the library call to a compromised site. If it's on all machines, it may be a compromised library itself.

In either case, running the connection through a proxy like Fiddler or Zap should nail it pretty quickly.

3
  • 2
    The OP is saying he sees the injected script when he hits view-source after the page loads. I think this means that the indected script is being inserted into the root HTML document, not a subresource script referenced through a remote library call.
    – mti2935
    Commented Dec 31, 2020 at 2:08
  • Yeah, the code is being injected before JavaScript is being executed (the raw source shows the injected code). And if it were a hosts issue that I'd assume that the browser would throw a certificate error because this is being served over https
    – Ben D
    Commented Dec 31, 2020 at 4:20
  • @Ben D - OK, interesting! The Fiddler or Zap proxy suggestion still holds. It will tell you if the content is actually being fetched and if so from where. Commented Dec 31, 2020 at 4:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .