PHP & Spam

Tutti, prima o poi, hanno dovuto affrontare la situazione di un sito compromesso che inizia ad essere utilizzato come veicolo di propagazione di spam. E siccome prevenire è meglio che curare, ritengo sia utile predisporre un ambiente in grado di limitare i danni in caso uno dei siti ospitati sui nostri server venga ‘bucato’. Queste sono alcune delle ricette che uso per implementare quelle che considero protezioni di base.

1. Disabilitare l’invio diretto di posta

La prima cosa che faccio è quello di disabilitare l’invio diretto di posta. Io solitamente utilizzo Postfix come MTA, e questo comportamento si implementa facilmente inserendo una linea in /etc/main.cf del tipo:

authorized_submit_users = root vmail amavis

con cui si nega agli utenti diversi da root, vmail ed amavis di inviare posta. Ove fosse necessario consentirne l’invio per determinate applicazioni, queste devono essere configurate per accedere all’MTA via smtp autenticato. In questo modo è possibile imporre tutte le regole comunemente utilizzate per le operazioni di relay.  Per l’abilitazione è necessario usare un replacement della funziona mail() come questa (il codice non è mio):

function pear_mail($to,$subject,$message,$headers="") {
    // Richiede PEAR Mail e Net_SMTP
    require_once("Mail.php");
    function split_headers( $headers )
    {
        $header_array = array();
        $lines = explode("\n",$headers);
        foreach ($lines as $line) {
            $kv = explode(":",$line,2);
            if (!empty($kv[1])) {
                $header_array[trim($kv[0])] = trim($kv[1]);
            }
        }
        return $header_array;
    }

    $mailer = Mail::factory('smtp',array('host'=>'127.0.0.1','port'=>'25'));
    $header_list = split_headers($headers);
    $header_list['Subject'] = $subject;
    return $mailer->send($to,$header_list,$message);
}

che utilizza la stessa sintassi della funzione php e quindi può essere implementata semplicemente. Configurare il server SMTP in php.ini sarebbe inutile, visto che lo scopo è quello di disabilitare la funzione mail() nativa.

2. Abilitare il logging delle chiamate alla funzione mail()

Ruotare la posta via SMTP autenticato sicuramente riduce le chance che un malware ha di inviare spam, ma è allo stesso tempo utile avere una indicazione del fatto che una condizione anomala è presente sul  nostro server: la stessa vulnerabilità potrebbe essere utilizzata per altri fini. Dato che gli script bucati continueranno a tentare di inviare la posta utilizzando la funzione built-in mail() di PHP, possiamo usare questo come una sorta di campanello d’allarme.

La prima azione da fare è quella di abilitare il logging dei messaggi inviati mediante la funzione incriminata, è sufficiente inserire in php.ini una voce

mail.log = /var/log/mail_php.log

perche l’interprete php scriva nel file indicato una voce per ogni chiamata alla funzione, contenente tutto ciò che ci serve:

mail() on [/var/www/htmp/testmail.php:2]: To: user@domain.xx -- Headers:

L’errore apparirà nel log del mailer:

postfix/sendmail[15395]: fatal: User www-data(33) is not allowed to submit mail

così come nel report giornaliero (io utilizzo pflogsumm):

Fatal Errors
------------
  sendmail (total: 7)
         7   User www-data(33) is not allowed to submit mail

La presenza dei quali indica che c’è una situazione anomala che richiede la mia attenzione.

3. Bloccare il traffico in uscita SMTP per apache

Se il malware ha un proprio server SMTP, come nel caso del CryptoPHP, i vincoli precedenti non hanno effetto, ma bisogna agire sulle regole di iptables per bloccare il traffico in uscita. In questo caso possiamo usare due approcci.

Il primo, meno restrittivo, consiste nel bloccare il traffico verso le porte SMTP generato da processi con l’uid di apache:

# blocco delle connessioni SMTP in uscita per apache
/sbin/iptables -A OUTPUT --dst 127.0.0.1 -p tcp --dport 25 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 25 -m owner --uid-owner 33 -j DROP
/sbin/iptables -A OUTPUT -p tcp --dport 465 -m owner --uid-owner 33 -j DROP
/sbin/iptables -A OUTPUT -p tcp --dport 587 -m owner --uid-owner 33 -j DROP
# log traffico generato da utenti diversi da postfix
/sbin/iptables -A OUTPUT -p tcp --dport 25 -m owner ! --uid-owner 107 -j LOG
/sbin/iptables -A OUTPUT -p tcp --dport 465 -m owner ! --uid-owner 107 -j LOG
/sbin/iptables -A OUTPUT -p tcp --dport 587 -m owner ! --uid-owner 107 -j LOG

Queste regole accettano il traffico verso il server locale, ma bloccano quello generato da apache (uid 33), inoltre loggano il traffico di utenti diversi da postfix (uid 107).
Un secondo approccio, più restrittivo, blocca il traffico per tutti gli utenti diversi da postfix:

# blocco delle connessioni SMTP
/sbin/iptables -A OUTPUT --dst 127.0.0.1 -p tcp --dport 25 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 25 -m owner ! --uid-owner 107 -j DROP
/sbin/iptables -A OUTPUT -p tcp --dport 465 -m owner ! --uid-owner 107 -j DROP
/sbin/iptables -A OUTPUT -p tcp --dport 587 -m owner ! --uid-owner 107 -j DROP

Ovviamente se il server ha sia un indirizzo ipv4 che ipv6 le regole vanno inserite in entrambe le definizioni di iptables, ricordo che localhost in ipv6 è ::1.

Per rilevare queste condizioni anomale, che implicano la presenza di vulnerabilità sul server, è utile aggiungere una istruzione per registrare il drop in syslog, tipo:

/sbin/iptables -A OUTPUT -p tcp --dport 25 -m owner ! --uid-owner 107 -j LOG

in modo che sia rilevabile nell’analisi del log ed essere utilizzato come allarme.

Non è certo la panacea di tutti i mali, ma sono aggiustamenti che svolgono efficacemente il loro lavoro.

Pubblicato in Linux, Prevenzione, Sicurezza Taggato con: , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*