1 puntos por GN⁺ 2024-01-29 | 1 comentarios | Compartir por WhatsApp
  • En los registros de acceso de una IP pública autoalojada durante más de 10 años aparecen intentos de ataque habituales contra servicios expuestos a Internet, desde búsqueda de credenciales hasta inyección de comandos contra dispositivos IoT
  • El patrón más común fue la búsqueda de archivos de configuración y directorios como .env, .aws/credentials, .git/config, backup/ y test/, y algunas solicitudes usaban User-Agent con errores tipográficos como Mozlila/5.0
  • Los intentos de Shellshock incluían payloads con forma de función de Bash dentro del User-Agent para leer /etc/passwd, además de adivinar repetidamente varias rutas CGI
  • Los ataques dirigidos a LuCI y Zyxel intentaban insertar comandos en las interfaces web de routers y dispositivos embebidos para descargar y ejecutar scripts remotos y binarios para múltiples arquitecturas
  • Hay que reducir al mínimo lo que se expone a Internet pública, aplicar autenticación y restricciones por IP a las herramientas o directorios necesarios, y mantener los dispositivos IoT actualizados y, de ser posible, separados de la red pública

Tráfico que reciben los servicios expuestos a Internet pública

  • Tras más de 10 años de autoalojamiento, la experiencia ha sido mantener control directo sobre los propios datos y reducir la dependencia de plataformas ajenas a un host en la nube
  • Cuando una IP queda expuesta a Internet pública, enseguida empieza a recibir mucho tráfico malicioso, y los registros de acceso permiten rastrear qué tipos de ataques se han recibido recientemente
  • Este análisis se parece más a la observación de un desarrollador curioso que a una investigación forense hecha por un especialista en seguridad
  • Por precaución, se ocultaron las direcciones IP de los atacantes y algunas expresiones insultantes usadas por ellos

Búsqueda de credenciales y archivos de configuración

  • El ataque más común fue el intento de encontrar credenciales mediante recorrido de directorios, y en particular aparecieron muchas solicitudes al archivo .env
    • Ejemplos de rutas solicitadas: /laravel/.env, /backend/.env, /api/.env, /.env, //.env
    • .env normalmente se maneja como un archivo que contiene secretos de la aplicación
  • También se buscaban archivos relacionados con AWS y configuraciones de repositorios Git
    • Ejemplos: /aws.yml, /.env.bak, /info.php, /.aws/credentials, /config/aws.yml, /.git/config
  • También se solicitaron repetidamente directorios comunes que podrían haber quedado por error
    • Ejemplos: /old/, /new/, /test/, /backup/, /temp/
  • Algunos User-Agent incluían Mozlila/5.0, que parece un error tipográfico de Mozilla/5.0
    • Los resultados de búsqueda en GitHub sugieren que este error pudo haberse generado en una herramienta común y luego haberse copiado y pegado
  • También se detectaron solicitudes que buscaban herramientas de acceso remoto o de configuración
    • Ejemplos: /actuator/gateway/routes, /hudson, /ui/login.action, /?XDEBUG_SESSION_START=phpstorm
  • Conviene exponer a Internet pública solo lo estrictamente necesario, y si se deben exponer herramientas o directorios, hace falta una capa de autenticación y, cuando sea posible, restricciones a IP específicas

Intentos de Shellshock

  • Varias solicitudes parecían apuntar a la vulnerabilidad Shellshock
  • Este ataque busca ejecutar comandos arbitrarios en servidores web que ejecutan scripts CGI con versiones vulnerables de Bash
    • Al iniciarse un programa CGI, se establecen variables de entorno a partir del contenido de la solicitud, y HTTP_USER_AGENT es una de ellas
    • Si incluye caracteres como () { :; };, Bash lo interpreta como una función que debe ejecutar
  • En los registros reales, el User-Agent contenía payloads como estos
    • () { ignored; }; echo Content-Type: text/html; echo ; /bin/cat /etc/passwd
    • () { ignored; }; tiene la forma de una definición de función de Bash
    • echo Content-Type: text/html; echo ; imprime el Content-Type de la respuesta HTTP y una línea vacía
    • /bin/cat /etc/passwd es un comando que intenta mostrar el contenido de /etc/passwd, donde está la información de cuentas de usuario
  • Si el ataque hubiera tenido éxito, podría haber derivado en acceso a credenciales de usuario y ejecución de código arbitrario en el servidor
  • Igual que en el recorrido de directorios, el atacante adivinaba rutas comunes como /cgi-bin/status, /cgi-bin/stats, /cgi-bin/test, /cgi-bin/status/status.cgi, /test.cgi, /debug.cgi, /cgi-bin/test-cgi

Inyección de comandos dirigida a LuCI

  • Una solicitud parecía apuntar a LuCI, la interfaz web para routers OpenWRT
  • La URL del ataque estaba estructurada para insertar comandos en el campo country y así descargar y ejecutar el script de shell remoto tenda.sh
    • Después de decodificar la URL, el comando seguía un flujo de ir a /tmp, borrar archivos, descargar el script con wget, darle permisos de ejecución y luego ejecutarlo
  • El script descargado contenía instrucciones para bajar y ejecutar binarios adicionales
    • Incluía nombres que parecen corresponder a arquitecturas objetivo como mips, mpsl, x86_64, arm, arm5, arm6, arm7, i586, i686, powerpc, sh4, m68k, sparc
    • Intentar binarios para varias arquitecturas parece una forma de ampliar el alcance del ataque cuando no se conoce la arquitectura exacta del dispositivo objetivo
  • Para investigar más, se descargó un binario incompatible con el entorno y se examinó con Ghidra
    • Al principio solo había 3 funciones y muy pocos datos de texto
    • En una gran región de datos aparecieron las cadenas $Info: This file is packed with the UPX executable packer y UPX 3.94
  • Era un binario ELF comprimido con UPX, y si el encabezado de UPX o el binario empaquetado no fueron modificados, puede desempaquetarse con upx -d
    • De hecho, al ejecutar upx -d mips, el tamaño del archivo aumentó de 34932 a 93732, y fue posible ver muchas más cadenas
  • Entre las cadenas del binario desempaquetado aparecían M-SEARCH * HTTP/1.1, ST: urn:dial-multiscreen-org:service:dial:1 y un payload XML para actualizar dispositivos Huawei
    • Esto parece ser un comando UPnP para buscar en la red dispositivos compatibles con el protocolo DIAL
    • El payload XML parece estar preparado para escanear dispositivos Huawei vulnerables a inyección de comandos
    • Este comportamiento parece haber sido identificado como parte de la botnet Mirai
  • El archivo referenciado yeye.mips no estaba disponible cuando se intentó obtenerlo
    • Al ejecutar nmap contra el servidor, solo se detectaron los puertos abiertos 22/tcp ssh y 646/tcp filtered ldp

Inyección de comandos dirigida a Zyxel

  • Otra solicitud contenía comandos de shell dentro de una URL GET, y al eliminar la sustitución de shell ${IFS} quedaba una forma más fácil de leer
    • El comando depurado seguía un flujo de ir a /tmp, borrar archivos *mips*, descargar huhu.mips, darle permisos de ejecución y ejecutarlo con el argumento zyxel.selfrep
  • Este ataque parecía apuntar al exploit de zhttpd en dispositivos Zyxel
  • Este binario no estaba empaquetado, así que las cadenas podían verse directamente en Ghidra
    • Entre las cadenas aparecían M-SEARCH * HTTP/1.1, el encabezado ST relacionado con DIAL, skyljne.arm, skyljne.arm5, skyljne.arm6, skyljne.arm7, skyljne.mips, skyljne.mpsl, skyljne.x86_64, skyljne.sh4
    • También incluía un payload XML dirigido a dispositivos Huawei para descargar huhu.mips y ejecutarlo como selfrep.huawei
  • Otra cadena contenía un comando para enviar un POST a /goform/set_LimitClient_cfg
    • Junto con el encabezado Cookie: user=admin, intentaba insertar comandos en el parámetro mac para descargar y ejecutar huhu.mpsl
    • Según un artículo de Akamai, esta vulnerabilidad afecta a routers y puede explotarse sin autenticación previa porque no tiene verificaciones especiales de autenticación ni autorización
  • Se considera muy probable que este binario sea un agente de la botnet Mirai
    • Algunas fuentes también mencionan una posible relación con Linux Medusa

Respuesta desde la operación

  • Los registros revisados son solo una parte del total, y cada día se intentan muchos otros exploits
  • Es importante mantener los equipos, especialmente los dispositivos IoT, al día
  • Siempre que sea posible, los dispositivos IoT no deberían exponerse directamente a Internet pública
  • Si es imprescindible exponerlos, conviene aislarlos en una VLAN separada siempre que sea posible

1 comentarios

 
GN⁺ 2024-01-29
Opiniones de Hacker News
  • Curiosamente, algunos atacantes parecen monitorear los logs de Certificate Transparency para encontrar certificados recién emitidos.
    Varias veces me pasó que, al dejar un servidor nuevo en una IP nueva durante más de una semana, en los logs de acceso solo aparecían algunos escaneos aleatorios, pero alrededor de una hora después de obtener un certificado de Let’s Encrypt llegaban cientos de solicitudes como las del artículo.
    La conclusión es que los servicios nuevos deben estar seguros lo antes posible; idealmente, antes de exponerlos a Internet.

    • Da la sensación de que, desde el primer momento de exposición pública, al menos debería haber algo como autenticación básica al frente.
      O también se puede usar una autoridad certificadora propia y, hasta hacer el cambio, usar un certificado autofirmado y mTLS.
      Por ejemplo, si cierto software expone tal cual una pantalla de instalación inicial para crear la cuenta de administrador, conectar la DB, etc., resulta más riesgoso que definirlo desde el inicio mediante variables de entorno, archivos de configuración o una herramienta dedicada de gestión de secretos.
    • Hace poco estuve revisando logs de Certificate Transparency y me pregunto si hay herramientas o métodos cómodos para consultar logs CT.
      Por ejemplo, buscar dominios dentro de un periodo específico.
      Merkle Town[0] de Cloudflare es útil para ver un panorama general, pero todavía no encontré una forma sencilla de consultar logs CT, y ct-woodpecker[1] también parece prometedor.
      [0] https://ct.cloudflare.com/
      [1] https://github.com/letsencrypt/ct-woodpecker
    • Usar más certificados wildcard también ayuda. Hace más difícil deducir, solo a partir de los logs CT, subdominios específicos para atacar.
    • En muchos casos no son atacantes, sino servicios como urlscan.io que monitorean logs CT y rastrean la web para encontrar malware.
    • Autoalojo varios servicios, pero ya renuncié por completo a exponerlos directamente a Internet.
      Las VPN hoy son tan buenas que dan tranquilidad, y cosas como hosting de fotos o backups en particular no quiero exponerlas públicamente.
  • Cuando empecé a administrar un sitio autoalojado, también revisaba los logs de acceso y, durante un tiempo, usé un sistema de detección de intrusiones que recopilaba datos y mostraba los intentos de ataque entrantes.
    Al final dejé tanto de revisar los logs proactivamente como de pagar por el sistema de detección de intrusiones; era una pérdida de tiempo y una distracción.
    Es fácil encontrar materiales que resumen bien las vulnerabilidades y ataques comunes, así que se pueden usar como criterio para administrar servidores. Hay muchas guías de buenas prácticas para cada tecnología común de servidor web, y con solo aplicarlas al 100% ya quedas muy por delante de casi todos los atacantes.
    Después de eso, la mejor forma de usar tiempo y recursos es priorizar un ciclo de parchado lo más rápido posible. La mayoría de los ataques apuntan a vulnerabilidades públicas.
    Los logs son especialmente útiles para diagnosticar después de que ocurre un problema. El software de análisis de logs me ayudó 2 o 3 veces a almacenar y buscar información para encontrar la causa raíz de ataques exitosos, y cada vez la causa fue una vulnerabilidad conocida que se había parchado demasiado tarde.

    • Si en todos los casos fue una vulnerabilidad conocida parchada tarde, entonces un enfoque que depende solo de los parches inevitablemente va a fallar algún día. Puede ser una vulnerabilidad de día cero, o el atacante puede ser más rápido.
      La solución es la defensa en capas y, al autoalojar servicios personales, la mayoría se puede aplicar con bastante facilidad.
      Pon un firewall al frente o escóndelo detrás de una VPN/Tailscale; si ocultas phpMyAdmin en una subcarpeta como /mawer/phpmyadmin/ en vez de /phpmyadmin/, que es lo que buscan los ataques automatizados, el 99.9% no lo encontrará. A eso se le llama seguridad por oscuridad y no hay que confiar solo en eso, pero como capa adicional es muy útil.
      Hay que poner las apps en sandboxes y aislar los servidores para que, aunque haya una intrusión, sea difícil moverse a otros lugares; además, dejar logs para poder verificar si hubo ataque y si tuvo éxito.
      La clave es no depender de un solo mecanismo de defensa, ya sea parches o firewall. Al final, alguno va a fallar.
    • Me da curiosidad la parte de priorizar el ciclo de parchado más rápido posible. Quisiera saber si usas alguna herramienta para decidir cuándo parchar, o si te basas en intervalos de tiempo.
      Ahora intento actualizar paquetes cada trimestre[0], pero sería bueno tener una herramienta que avise sobre vulnerabilidades conocidas para poder responder de inmediato.
      [0] Aquí, “intento” significa que si hay rupturas de compatibilidad difíciles de adaptar a la versión más reciente, o si se trata de una versión X.0.0 en la que todavía no confío, no puedo actualizar de inmediato.
  • Como el autor dijo que no es experto en seguridad, corrigiendo un detalle menor: los ejemplos del principio son búsqueda de credenciales y configuración, no directory traversal.
    Entiendo que directory traversal es el término usado para técnicas en las que el atacante “escapa” de la raíz web o engaña al servidor para que entregue archivos fuera del directorio normal.

    • Si es una forma de incluir archivos que originalmente no deberían estar alojados, técnicamente puede ser ambas cosas. Por ejemplo, algo como "/../../passwd/etc".
  • Al menos según mi experiencia, el punto clave es que una parte considerable de estos ataques viene de actores estatales hostiles.
    Puede ser controversial, pero bloquear rangos completos de IP de países problemáticos con los que no tienes ninguna razón para tratar puede ser útil. Con eso llegué a bloquear el 100% de los intentos de escaneo que entraban a un servicio nuevo.

    • No es el problema principal; simplemente mucha gente no quiere bloquear también a los usuarios legítimos de esa región.
    • Ojalá los actores estatales no tuvieran ninguna forma de comprar servidores en otros países y ejecutar ataques desde ahí.
    • Hace más de 15 años, al revisar logs de servidores de pequeños negocios locales que alojábamos, concluimos que podíamos bloquear todas las direcciones IP de APNIC.
    • Me parece que el bloqueo regional al final solo bloquea tráfico legítimo y hace que los atacantes motivados usen proxies.
    • Si haces eso, tendrías que bloquear Estados Unidos y Países Bajos.
      La mayoría de los escaneos que llegan a mi servidor vienen de Estados Unidos, y muy por detrás, en segundo lugar, Países Bajos. Supongo que la mayoría viene de AWS y otros centros de datos.
  • Trabajo en seguridad de aplicaciones/productos y durante varios años administré WAF de empresas de miles de millones de dólares.
    Basta con mover el DNS a Cloudflare y poner algunas reglas de WAF en el sitio. Por ejemplo, aplicar un desafío administrado si la puntuación de bot es menor que 2, o actuar cuando la puntuación de ataque alcanza cierto valor. Probablemente cueste casi nada y resolverá muchos problemas.
    Eso sí, hay que probarlo sí o sí antes de pasarlo a producción. También conviene tener un dominio de pruebas. Un WAF no es una solución mágica, sino más bien un parche temporal; si la app en sí no está reforzada para resistir ataques, ni el WAF más avanzado ni la protección contra bots la van a salvar.

    • Para quienes no estén familiarizados, dejo esto: https://blog.cloudflare.com/waf-for-everyone/
      Parece que Free Managed Ruleset se despliega por defecto, y Cloudflare mantiene el registro de cambios aquí: https://developers.cloudflare.com/waf/change-log
    • Desde mi perspectiva de self-hosting, uso el WAF de CloudFlare y reglas de TLS mutuo para dejar pasar solo a los llamadores legítimos que conozco.
      Funciona muy bien. Como solo accede mi familia, fue fácil configurarlo, y cada uno tiene su propio certificado, que puedo revocar si hace falta.
    • Últimamente suelo administrar solo aplicaciones internas, así que la superficie de ataque es mucho menor que en servicios públicos.
      Como parece que conoces bien este campo, me da curiosidad saber si has administrado alguna solución que combine infraestructura de Azure con Cloudflare y, si es así, si hay cosas que la gente suele pasar por alto aparte de lo típico como OWASP.
    • Encaja bien con un sitio estándar de WordPress, y como capa adicional se le pueden sumar GuardGiant y el plugin de Sucuri.
    • Poner un WAF delante de una app y dar el tema por cerrado no es distinto de ponerle lápiz labial a un cerdo.
      Puede ser necesario si una empresa, por el motivo que sea, tiene que operar algo que no está actualizado, pero al final no deja de ser un parche temporal.
  • Llevo más o menos un año haciendo self-hosting de un servidor HTTP/S de 400 líneas que diseñé yo mismo, y es sorprendente la cantidad de tráfico de ataque que entra por los 3 puertos abiertos (22, 80, 443).
    Aunque no me he tomado el tiempo de analizar qué intentan hacer realmente los atacantes, este artículo llena muchos vacíos.
    Estaría bueno analizar de la misma forma las cosas raras que aparecen en /var/log/auth.log.
    Todo el código es open source y no hay estado del lado del servidor, así que me parece raro que un atacante se moleste en apuntarme a mí. Lo mejor que podría obtener sería acceso root a un VPS de 5 dólares al mes y una alteración temporal de un dominio al que no entra nadie.

    • Todo eso son bots automatizados. No es que alguien se esté tomando la molestia de prestarte atención.
      Si abres los 3 puertos más conocidos, vas a recibir conexiones; no saben qué estás ejecutando ni les importa.
    • Si acceden a tu VPN, sirve como punto de partida para atacar otras máquinas y agrega una capa más para ocultar rastros.
      También pueden alojar malware o ejecutar mineros de criptomonedas.
    • Vale la pena considerar permitir el puerto 22 solo desde tu propia IP y bloquear el resto.
      Mi ISP casi nunca cambia la IP en la práctica, y si cambia puedo iniciar sesión en el panel web de administración del hosting y actualizar la regla.
  • En cada servidor siempre ejecuto fail2ban, y también agrego jails personalizados para detectar ataques acordes al tipo de funcionalidades que expone el sitio.
    Dicho eso, hace mucho que no verifico si los otros valores predeterminados de fail2ban siguen siendo suficientes para bloquear ataques comunes. Voy a guardar este enlace para verlo después.

    • Si tu sistema expone vulnerabilidades que se pueden atacar tan fácilmente, fail2ban no te va a salvar.
  • Yo también reviso los logs de acceso de servicios que tengo en self-hosting, y hay un detalle que falta de forma notable en este análisis.
    Una buena parte de las solicitudes maliciosas proviene de personas comunes ejecutando escáneres de seguridad que se consiguen fácilmente en lugares como GitHub. Por lo general son ataques poco sofisticados: instancias de esos proyectos que golpean servidores sin siquiera mirar la respuesta ni preocuparse por si fueron rate-limited.
    Algunos ataques no apuntan directamente a una IP, sino que monitorean dominios y subdominios, y repiten periódicamente el mismo escaneo desde el mismo rango de IP.
    En un trabajo anterior recibíamos escaneos repetidos desde una única IP fija de Turquía, al punto de que el equipo empezó a llamarlo “el turco”; cuando veíamos un patrón raro de solicitudes, el primer paso de la respuesta a incidentes era revisar si esa persona estaba tocando nuestro servicio.

  • Si estás viendo logs como estos en AWS, por favor conviene poner AWS WAF delante de la VPC.
    No es caro y en situaciones así ayuda bastante a reducir dolores de cabeza. Aunque no bloquee todo lo que llega hasta el servicio, puede ser de gran ayuda.

    • Buena sugerencia, pero hay que tener cuidado con el conjunto de reglas predeterminado. Nosotros activamos AWS WAF por cumplimiento de SOC 2.
      Algunas reglas demasiado agresivas rompieron partes de la app de forma sutil.
      Había una regla de cuerpo de solicitud que bloqueaba solicitudes si el body contenía "localhost", y otra que bloqueaba solicitudes sin encabezado User-Agent. Como antes no exigíamos User-Agent en las solicitudes de API, les rompió toda la API a algunos usuarios hasta que encontramos la causa.
    • Los ataques mencionados en el artículo no deberían ser un problema para ninguna aplicación web moderna. Por eso no entiendo por qué habría que agregar un WAF.
    • Usar las reglas predeterminadas de AWS WAF no es tan fácil. En nuestra aplicación bloqueaban muchas solicitudes e IP legítimas.
      Hay que saber qué se está bloqueando y validarlo primero; si no, en algunos casos terminas perdiendo clientes.
    • En realidad, los WAF suelen hacer más daño que bien.
      Dan una falsa sensación de seguridad aunque se eludan fácilmente, tienen un costo de rendimiento alto y también una probabilidad considerable de bloquear tráfico legítimo: https://www.macchaffee.com/blog/2023/wafs/
    • Los WAF tienden a bloquear de forma amplia, y a veces por motivos ambiguos.
      Por ejemplo, los investigadores de nuestra universidad estudian datos de Twitter, y las IP de la universidad quedan bloqueadas por la mayoría de los WAF solo porque siguen enlaces desde una pequeña muestra aleatoria de tuits.
  • A veces se me ocurre que sería divertido crear un servidor Express que responda correctamente a uno de estos ataques para hacerle perder el tiempo a alguien
    Pero si hiciera eso, también estaría perdiendo mi propio tiempo