RCE w kontenerze Dockera

0

Cześć, na wstępie zaznaczę, że mało wiem o konteneryzacji, znam jedynie podstawy. Mam aplikację napisana w całości w Javie która odpalana jest z docker compose i zawiera 5 kontenerów które sie ze sobą komunikują. W jednym z tych kontenerów udało mi się odkryć RCE (remote code executon), które jest możliwe do wykonania z poziomu strony internetowej. Odpowiednio modyfikując żądanie http jestem w stanie wykonać kod na tym kontenerze. Tutaj pojawia sie pytanie jak dużo bałaganu mogę zrobić z poziomu takiego kontenera? Tworzenie plikow czy usuwanie plikow działa, jednak komendy takie jak shutdown, reboot już nie. Czy jestem jakoś w stanie wpłynąć na dzialanie innych kontenerow lub dostać sie do maszyny na której uruchomiony jest docker? Jak dużo szkód mogę zrobić? Z góry dzięki za pomoc!

1

Czy to twoja aplikacja na pewno? ;)

Ogólnie, o ile kontener nie posiada czegoś jawnie łączącego go z hostem (typu podmontowany katalog "/" albo docker socket) to dostać się na host raczej się nie da (a przynajmniej nie powinno się dać). Można próbować typowe ataki DoS typu zapełnić dysk albo pamięć (o ile limitu nie ma ustawionego), ale to chyba jasne. Do innych kontenerów można się dostać tak samo, jak aplikacja się do nich dostaje, w końcu odpalasz ten kodzik jako user aplikacji.

0
infantylny napisał(a):

Tutaj pojawia sie pytanie jak dużo bałaganu mogę zrobić z poziomu takiego kontenera? Tworzenie plikow czy usuwanie plikow działa, jednak komendy takie jak shutdown, reboot już nie. Czy jestem jakoś w stanie wpłynąć na dzialanie innych kontenerow lub dostać sie do maszyny na której uruchomiony jest docker? Jak dużo szkód mogę zrobić? Z góry dzięki za pomoc!

Ja nie wiem nic o RCE, ale ogólnie uruchamianie poleceń OS z poziomu strony internetowej to idea stara jak świat.

Jeżeli chodzi o szkody wyrządzone w systemie operacyjnym to pewnie kwestia poustawiania uprawnień i użytkownika na uprawnieniach którego uruchamia się całe to RCE.

Wyrządzanie szkód wewnątrz samej aplikacji to kolejna sprawa - różnego rodzaju ataki modyfikujące dane aplikacji to powszechne zjawisko w Wordpress (tam się to nazywa XML RPC - remote procedure call i jest chyba używane np. do manipulacji plikami/załącznikami do artykułów). Oczywiście Twoja aplikacja nie będzie powszechnie używanym open sourcowym CMS-em i pewnie nikt z zewnątrz nie będzie jej atakował z góry wiedząc gdzie jest dziura w zabezpieczeniach, ale jakieś tam ryzyko pozostaje.

Jeżeli już musisz czegoś takiego używać to musisz zrobić jakąś listę dozwolonych poleceń i zabronić wszystkich pozostałych, mocno dopracować walidację parametrów, poprosić kilka doświadczonych osób o przejrzenie tego itp.

0

@Kamil A: dokladnie o to chodzi, o wykonanie polecenia OS z poziomu strony internetowej. Tylko te polecenie nie sa wykonywane z poziomu OS na ktorej hostowana jest strona a jest dodatkowy poziom zagnieżdżenia w postaci konteneru dockera i tutaj pojawia się moje pytanie czy sa jakies metody ucieczki z takiego kontenera do głównego systemu opercyjnego albo inne metody "napsucia" z poziomu kontenera, typu usunięcie wszystkich danych z kontenera, dostanie sie do innych kontenerow z ktorymi rozmawia dany kontener na którym mozliwe jest RCE albo zawieszenie calego serwera na którym odpalony jest ten kontener.

0

A więc ja robię to na przykład tak:

Mam jakiś katalog ze skryptami możliwymi do uruchomienia CLI_SCRIPTS_DIR (stała konfiguracyjna aplikacji).

Moje skrypty zawsze zwracają Double, bo to rejestrator danych. Do bardziej uniwersalnych zastosowań pewnie byłby lepszy String.

Funkcja która wykonuje polecenia na serwerze wygląda tak:

       public static Double executeScriptAndGetResult(String scriptName, String scriptParameters) throws IOException {

        String command = CLI_SCRIPTS_DIR + "/" + scriptName + ".sh " + scriptParameters;
        StringBuilder result = new StringBuilder();

        // tu można by jeszcze nałożyć restrykcje na scriptName
        // żeby nie było znaków umożliwiających przejście do innego katalogu, pipe, && i takie tam, 
        // najlepiej by było wyciąć wszystko ze spacją włącznie, poza literami
        // u mnie nie było to konieczne, bo to aplikacja używana wewnątrz firmy, zabunkrowana VPN-em i odcięta firewallem od świata

        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String s;

        while ((s = reader.readLine()) != null) {
            result.append(s).append("\n");
        }

        if (result.toString().startsWith("Error:")) {
            // tu mam obsługę błędów skryptu
            // wszystkie mają obsługę błędu wewnątrz, 
            // w bashu i jeżeli coś jest nie tak to wypisują na stdout "Error: Jakiś tam błąd"
            // jeżeli potrzebuję uruchomić np. df -h to muszę napisać skrypt .sh który to polecenie wykonuje.
            // włożyć go do `CLI_SCRIPTS`, nazwać np. df-h.sh, nadać uprawnienia +x, dopiero wtedy można go odpalić po API
        }

        Double retVal;

        try {
            retVal = Double.parseDouble(result.toString()); // throws NumberFormatException
        } catch (NumberFormatException e) {
            // tu mam obsługę błędów
        }

        return retVal;
    }
    

Pewnie dało by się ten kod przyczepić do jakiegoś Springa, u mnie to działa na autorskim API napisanym w Javie, nafaszerowanym mechanizmami reflection.

Serwer aplikacji (czyli to całe API w Javie) uruchamiany jest przez odpowiednio przygotowanego użytkownika systemu Linux, dzięki czemu mam pewność że "nic nie wylezie" poza uprawnienia zwykłego usera.

0

czy sa jakies metody ucieczki z takiego kontenera do głównego systemu opercyjnego

Raczej nie, ale pewnie są lub pojawią się kiedyś jakieś bugi.
Z założenia oprogramowanie do konteneryzacji / wirtualizacji nigdy nie powinno umożliwiać "wyjście na zewnątrz z konterera" .

Pogooglałem "docker breakout" i znalazłem np. to:
https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation

albo inne metody "napsucia" z poziomu kontenera, typu usunięcie wszystkich danych z kontenera

Tego nie rozumiem.

dostanie sie do innych kontenerow z ktorymi rozmawia dany kontener na którym mozliwe jest RCE albo zawieszenie calego serwera na którym odpalony jest ten kontener.

Raczej nie, ale pewnie są lub pojawią się kiedyś jakieś bugi.

2

Tutaj pojawia sie pytanie jak dużo bałaganu mogę zrobić z poziomu takiego kontenera

Nie ma ogólnej odpowiedzi. Wszystko zalezy od tego jak jest skonfigurowana strona. Będę pisał co może zrobić hipotetyczny atakujący, nie zajmując się tym co to za strona i czy to na pewno zamówione pentesty :P. Z głowy parę scenariuszy w miarę od prostszych do trudniejszych ataków.

  • Atakujący może uruchomić swoja koparkę kryptowalut na tym serwerze
  • Atakujący może wyciągnąć konfigurację bazy danych, sekrety aplikacji, etc.
  • W szczególności to znaczy, że atakujący może ukraść całą bazę danych i hasła użytkowników etc (wszystko do czego aplikacja webowa ma dostęp).
  • Znowu analogicznie, atakujący może wykorzystać zaufanie użytkowników do strony webowej i podmienić np. pobierane pliki na takie z malware, albo dorzucić złośliwy javascript.
  • W przypadku kubernetesa, AWS i podobnych chmurowych rozwiązań, atakujący może próbować ukraść token dający mu uprawnienia na całym klastrze. Uda się to tylko w razie miskonfiguracji czegoś, no ale zdarza się że jest dostępny z kontenera.
  • Atakujący może spróbować dokonać eskalacji na inne kontenery z którymi rozmawia. Metoda nie jest generyczna, ale np. źle skonfigurowane bazy danych pozwalają na zrobienie RCE na kontenerze z bazą i dostanie się tam.
  • Atakujący może wykonać atak DoS na serwerze, np robiąc starą dobrą forkbombę.
  • Atakujący może uszkodzić pliki działającego obecnie kontenera, ale wrócą one po restarcie kontenera. Natomiast wszystkie podmontowane dane (docker volumes) nie wrócą, więc potencjalnie może je usunąć na stałe (albo ofc ukraść/zaszyfrować)
  • Atakujacy może przeprowadzić stary, dobry ARP spoofing i przechwycić ruch TCP z innych kontenerów (AFAIR w domyślnej konfiguracji dockera domyślnie możliwe, ale tylko wewnątrz jednej sieci dockerowej).
  • Warto też pamiętać, że atakujący może inicjować ruch z serwera (skoro tam wykonuje kod). Czyli jeśli gdzieś jest przeprowadzana kontrola na podstawie IP wejściowego, atakujący przejdzie taki check. Przydatne w różnych cloudach gdzie często są magiczne URLe do których serwer może zagadać i dostać coś ciekawego (np. http://1.2.3.4/latest/meta-data/)
  • Jeśli kontener jest --priviliged, atakujący może dość łatwo wyeskalować się do hosta i przejąć serwer
  • Jeśli kontener ma przypisane jakieś dodatkowe capabilities (np. CAP_SYS_ADMIN), może być możliwa eskalacja do hosta
  • Atakujący może znaleźć jakąś podatność w kontenerze na którym może wykonywać kod i wykorzystać ją do eskalacji na hosta (klasyk tutaj to podmontowany docker.sock, ale to raczej mało prawdopodobne)
  • Atakujący może dysponować 0dayem na dockera albo linux namespaces, który pozwoli mu wyeskalować się do hosta nawet bez błedu konfiguracji (np. https://lwn.net/Articles/781013/)
  • Atakujący może dysponować 0dayem na linuxa, który pozwoli mu wyeskalować się do hosta nawet bez błedu konfiguracji (np. https://en.wikipedia.org/wiki/Dirty_COW)
  • Taki 0day prędzej czy później zostanie opublikowany, a admin kontenera może zapomnieć/nie zdążyć go zaktualizować (dlatego poprawna strategia to poleganie na defence in depth, czyli mamy wiele warstw obrony)

1 użytkowników online, w tym zalogowanych: 0, gości: 1