Deserialization
Podstawowe informacje
Serializacja to metoda polegająca na konwertowaniu obiektu do formatu, który można zachować, z zamiarem przechowywania obiektu lub przesyłania go w ramach procesu komunikacji. Ta technika jest powszechnie stosowana, aby zapewnić, że obiekt można odtworzyć w późniejszym czasie, zachowując jego strukturę i stan.
Deserializacja, z kolei, to proces przeciwny do serializacji. Polega na pobraniu danych, które zostały sformatowane w określonym formacie i odtworzeniu ich z powrotem w postać obiektu.
Deserializacja może być niebezpieczna, ponieważ potencjalnie pozwala atakującym manipulować zserializowanymi danymi w celu wykonania szkodliwego kodu lub wywołania nieoczekiwanego zachowania w aplikacji podczas procesu odtwarzania obiektu.
PHP
W PHP podczas procesów serializacji i deserializacji wykorzystuje się konkretne magiczne metody:
__sleep
: Wywoływana podczas serializacji obiektu. Ta metoda powinna zwrócić tablicę nazw wszystkich właściwości obiektu, które powinny być zserializowane. Jest powszechnie używana do zatwierdzania oczekujących danych lub wykonywania podobnych zadań czyszczenia.__wakeup
: Wywoływana podczas deserializacji obiektu. Służy do ponownego nawiązania połączeń z bazą danych, które mogły zostać utracone podczas serializacji, oraz do wykonywania innych zadań ponownej inicjalizacji.__unserialize
: Ta metoda jest wywoływana zamiast__wakeup
(jeśli istnieje) podczas deserializacji obiektu. Daje większą kontrolę nad procesem deserializacji w porównaniu do__wakeup
.__destruct
: Ta metoda jest wywoływana, gdy obiekt ma zostać zniszczony lub gdy skrypt się kończy. Zazwyczaj jest używana do zadań czyszczenia, takich jak zamykanie uchwytów plików lub połączeń z bazą danych.__toString
: Ta metoda pozwala traktować obiekt jako ciąg znaków. Może być używana do odczytu pliku lub innych zadań opartych na wywołaniach funkcji wewnątrz niej, efektywnie dostarczając tekstową reprezentację obiektu.
Jeśli spojrzysz na wyniki, zobaczysz, że funkcje __wakeup
i __destruct
są wywoływane podczas deserializacji obiektu. Zauważ, że w kilku samouczkach znajdziesz, że funkcja __toString
jest wywoływana podczas próby wydrukowania pewnego atrybutu, ale najwyraźniej to już się nie dzieje.
Metoda __unserialize(array $data)
jest wywoływana zamiast __wakeup()
jeśli jest zaimplementowana w klasie. Pozwala ona na deserializację obiektu poprzez dostarczenie danych zserializowanych jako tablicę. Możesz użyć tej metody do deserializacji właściwości i wykonania wszelkich koniecznych zadań podczas deserializacji.
Możesz przeczytać wyjaśniony przykład w PHP tutaj: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, tutaj https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf lub tutaj https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
Deserializacja PHP + Klasy Autoload
Możesz nadużyć funkcjonalności automatycznego ładowania w PHP do ładowania dowolnych plików PHP i nie tylko:
pagePHP - Deserialization + Autoload ClassesSerializacja Wartości Odniesienia
Jeśli z jakiegoś powodu chcesz zserializować wartość jako odwołanie do innej zserializowanej wartości, możesz:
PHPGGC (ysoserial dla PHP)
PHPGGC może pomóc w generowaniu ładunków, aby nadużyć deserializacji w PHP.
Zauważ, że w wielu przypadkach nie będziesz w stanie znaleźć sposobu na nadużycie deserializacji w kodzie źródłowym aplikacji, ale możesz nadużyć kod zewnętrznych rozszerzeń PHP.
Więc, jeśli możesz, sprawdź phpinfo()
serwera i szukaj w internecie (nawet w gadżetach PHPGGC) możliwych gadżetów, których możesz nadużyć.
Deserializacja metadanych phar://
Jeśli znalazłeś LFI, który tylko czyta plik i nie wykonuje w nim kodu PHP, na przykład za pomocą funkcji takich jak file_get_contents(), fopen(), file() lub file_exists(), md5_file(), filemtime() lub filesize(). Możesz spróbować nadużyć deserializacji, która występuje podczas odczytywania pliku za pomocą protokołu phar. Aby uzyskać więcej informacji, przeczytaj następujący post:
pagephar:// deserializationPython
Pickle
Gdy obiekt zostanie odblokowany, zostanie wykonana funkcja __reduce__. W przypadku wykorzystania, serwer może zwrócić błąd.
Dla dalszych informacji na temat ucieczki z więzień pickle, sprawdź:
pageBypass Python sandboxesYaml & jsonpickle
Następna strona prezentuje technikę wykorzystania nieszybkiej deserializacji w bibliotekach pythona obsługujących yamle i kończy się narzędziem, które można użyć do generowania ładunku deserializacji RCE dla Pickle, PyYAML, jsonpickle i ruamel.yaml:
pagePython Yaml DeserializationZanieczyszczenie klasy (Python Prototype Pollution)
pageClass Pollution (Python's Prototype Pollution)NodeJS
Magiczne funkcje JS
JS nie ma "magicznych" funkcji jak PHP czy Python, które zostaną wykonane tylko po utworzeniu obiektu. Ale ma kilka funkcji, które są często używane nawet bez bezpośredniego ich wywoływania, takich jak toString
, valueOf
, toJSON
.
Wykorzystując deserializację, możesz naruszyć te funkcje, aby wykonać inny kod (potencjalnie wykorzystując zanieczyszczenia prototypów), co pozwoli ci wykonać dowolny kod podczas ich wywoływania.
Innym "magicznym" sposobem wywołania funkcji bez bezpośredniego jej wywoływania jest naruszenie obiektu zwracanego przez funkcję asynchroniczną (promise). Ponieważ, jeśli przekształcisz ten obiekt zwracany w inny promise z właściwością o nazwie "then" typu funkcja, zostanie on wykonany tylko dlatego, że jest zwracany przez inny promise. Zajrzyj pod ten link dla więcej informacji.
Zanieczyszczenie __proto__
i prototype
__proto__
i prototype
Jeśli chcesz dowiedzieć się więcej o tej technice, zapoznaj się z następującym samouczkiem:
pageNodeJS - __proto__ & prototype PollutionTa biblioteka pozwala na serializację funkcji. Przykład:
Obiekt zserializowany będzie wyglądał następująco:
Możesz zobaczyć na przykładzie, że gdy funkcja jest serializowana, do obiektu serializowanego dodawana jest flaga _$$ND_FUNC$$_
.
Wewnątrz pliku node-serialize/lib/serialize.js
znajdziesz tę samą flagę i sposób, w jaki kod z niej korzysta.
Jak widać w ostatnim fragmencie kodu, jeśli flaga zostanie znaleziona, używane jest eval
do deserializacji funkcji, więc w zasadzie wejście użytkownika jest używane wewnątrz funkcji eval
.
Jednakże, tylko serializacja funkcji nie spowoduje jej wykonania, ponieważ konieczne byłoby, aby jakiś fragment kodu wywołał y.rce
w naszym przykładzie, co jest bardzo mało prawdopodobne.
W każdym razie, można zmodyfikować serializowany obiekt, dodając nawiasy w celu automatycznego wykonania zserializowanej funkcji podczas deserializacji obiektu.
W następnym fragmencie kodu zauważ ostatni nawias i sposób, w jaki funkcja unserialize
automatycznie wykona kod:
Jak wcześniej wskazano, ta biblioteka pobierze kod po _$$ND_FUNC$$_
i wykona go za pomocą eval
. Dlatego, aby automatycznie wykonać kod, można usunąć część tworzenia funkcji oraz ostatni nawias i po prostu wykonać jednolinijkowy kod JS jak w poniższym przykładzie:
Możesz znaleźć tutaj dalsze informacje na temat sposobu wykorzystania tej podatności.
Wartościowym aspektem funcstera jest niedostępność standardowych obiektów wbudowanych; wypadają one poza dostępny zakres. To ograniczenie uniemożliwia wykonanie kodu próbującego wywołać metody na obiektach wbudowanych, co prowadzi do wyjątków takich jak "ReferenceError: console is not defined"
przy użyciu poleceń takich jak console.log()
lub require(something)
.
Mimo tego ograniczenia, przywrócenie pełnego dostępu do globalnego kontekstu, w tym wszystkich standardowych obiektów wbudowanych, jest możliwe dzięki określonemu podejściu. Wykorzystując bezpośrednio globalny kontekst, można ominąć to ograniczenie. Na przykład dostęp można przywrócić za pomocą następującego fragmentu:
Aby uzyskać więcej informacji przeczytaj ten źródło.
Pakiet serialize-javascript jest przeznaczony wyłącznie do celów serializacji, nie posiada wbudowanych funkcji deserializacji. Użytkownicy są odpowiedzialni za implementację własnej metody deserializacji. Bezpośrednie użycie eval
jest sugerowane przez oficjalny przykład do deserializacji danych zserializowanych:
Jeśli ta funkcja jest używana do deserializacji obiektów, możesz to łatwo wykorzystać:
Dla więcej informacji przeczytaj ten źródło.
Biblioteka Cryo
Na następnych stronach znajdziesz informacje na temat tego, jak nadużyć tej biblioteki do wykonania arbitralnych poleceń:
Java - HTTP
W Javie wywołania zwrotne deserializacji są wykonywane podczas procesu deserializacji. To wykonanie może być wykorzystane przez atakujących, którzy tworzą złośliwe ładunki, które wyzwalają te wywołania zwrotne, prowadząc do potencjalnego wykonania szkodliwych działań.
Odciski palców
White Box
Aby zidentyfikować potencjalne podatności na serializację w kodzie, wyszukaj:
Klasy implementujące interfejs
Serializable
.Użycie funkcji
java.io.ObjectInputStream
,readObject
,readUnshare
.
Zwróć szczególną uwagę na:
XMLDecoder
używany z parametrami zdefiniowanymi przez zewnętrznych użytkowników.Metoda
fromXML
zXStream
, zwłaszcza jeśli wersja XStream jest mniejsza lub równa 1.46, ponieważ jest podatna na problemy z serializacją.ObjectInputStream
w połączeniu z metodąreadObject
.Implementacja metod takich jak
readObject
,readObjectNodData
,readResolve
lubreadExternal
.ObjectInputStream.readUnshared
.Ogólne użycie
Serializable
.
Black Box
Podczas testowania black box, poszukaj konkretnych sygnatur lub "Magicznych bajtów", które oznaczają obiekty zserializowane w Javie (pochodzące z ObjectInputStream
):
Wzorzec szesnastkowy:
AC ED 00 05
.Wzorzec Base64:
rO0
.Nagłówki odpowiedzi HTTP z ustawionym
Content-type
naapplication/x-java-serialized-object
.Wzorzec szesnastkowy wskazujący wcześniejszą kompresję:
1F 8B 08 00
.Wzorzec Base64 wskazujący wcześniejszą kompresję:
H4sIA
.Pliki internetowe z rozszerzeniem
.faces
i parametremfaces.ViewState
. Odkrycie tych wzorców w aplikacji internetowej powinno skłonić do dokładnego zbadania, jak opisano w poście dotyczącym Deserializacji Java JSF ViewState.
Sprawdź, czy jest podatny
Jeśli chcesz dowiedzieć się, jak działa eksploit deserializacji w Javie, powinieneś zajrzeć do Podstawowa deserializacja w Javie, Deserializacja DNS w Javie i Ładunek CommonsCollection1.
Test White Box
Możesz sprawdzić, czy zainstalowano jakąkolwiek aplikację znaną z podatności.
Możesz spróbować sprawdzić wszystkie biblioteki uznane za podatne, na które Ysoserial może dostarczyć exploit. Możesz także sprawdzić biblioteki wskazane na Java-Deserialization-Cheat-Sheet. Możesz również użyć gadgetinspector, aby wyszukać możliwe łańcuchy gadżetów, które można wykorzystać. Podczas uruchamiania gadgetinspector (po zbudowaniu go) nie przejmuj się ilością ostrzeżeń/błędów, przez które przechodzi, pozwól mu zakończyć. Znajdzie wszystkie wyniki w gadgetinspector/gadget-results/gadget-chains-year-month-day-godzina-minuta.txt. Proszę zauważyć, że gadgetinspector nie stworzy exploitu i może wskazywać fałszywe pozytywy.
Test Czarnej Skrzynki
Korzystając z rozszerzenia Burp gadgetprobe, możesz zidentyfikować jakie biblioteki są dostępne (nawet wersje). Dzięki tym informacjom może być łatwiej wybrać payload do wykorzystania podatności.
Przeczytaj to, aby dowiedzieć się więcej o GadgetProbe.
GadgetProbe skupia się na deserializacjach ObjectInputStream
.
Korzystając z rozszerzenia Burp Java Deserialization Scanner, możesz zidentyfikować podatne biblioteki podatne na exploitację za pomocą ysoserial i je wykorzystać.
Przeczytaj to, aby dowiedzieć się więcej o Java Deserialization Scanner.
Java Deserialization Scanner skupia się na deserializacjach ObjectInputStream
.
Możesz także użyć Freddy, aby wykryć podatności na deserializacje w Burp. To wtyczka wykryje podatności związane nie tylko z ObjectInputStream
, ale także podatności z bibliotek deserializacji Json i Yml. W trybie aktywnym spróbuje je potwierdzić, używając payloadów sleep lub DNS.
Więcej informacji o Freddy znajdziesz tutaj.
Test Serializacji
Nie chodzi tylko o sprawdzenie, czy serwer używa podatnej biblioteki. Czasami możesz zmienić dane wewnątrz zserializowanego obiektu i ominąć niektóre kontrole (może to dać ci uprawnienia administratora w aplikacji internetowej). Jeśli znajdziesz zserializowany obiekt Javy wysyłany do aplikacji internetowej, możesz użyć SerializationDumper, aby wydrukować w bardziej czytelnej formie obiekt zserializowany, który jest wysyłany. Znając dane, które wysyłasz, łatwiej będzie je zmodyfikować i ominąć niektóre kontrole.
Exploit
ysoserial
Głównym narzędziem do eksploatacji deserializacji Javy jest ysoserial (pobierz tutaj). Możesz także rozważyć użycie ysoseral-modified, co pozwoli ci używać złożonych poleceń (z rurami na przykład).
Zauważ, że to narzędzie jest skoncentrowane na eksploatacji ObjectInputStream
.
Zacząłbym od użycia ładunku "URLDNS" przed ładunkiem RCE, aby przetestować, czy wstrzyknięcie jest możliwe. W każdym razie zauważ, że może się zdarzyć, że ładunek "URLDNS" nie działa, ale inny ładunek RCE tak.
Podczas tworzenia ładunku dla java.lang.Runtime.exec() nie możesz używać znaków specjalnych takich jak ">" lub "|" do przekierowania wyniku wykonania, "$()" do wykonywania poleceń ani przekazywać argumentów do polecenia oddzielonych spacjami (możesz użyć echo -n "hello world"
, ale nie możesz użyć python2 -c 'print "Hello world"'
). Aby poprawnie zakodować ładunek, możesz skorzystać z tej strony internetowej.
Zapraszamy do skorzystania z poniższego skryptu do stworzenia wszystkich możliwych ładunków wykonania kodu dla systemów Windows i Linux, a następnie przetestowania ich na podatnej stronie internetowej:
serialkillerbypassgadgets
Możesz użyć https://github.com/pwntester/SerialKillerBypassGadgetCollection razem z ysoserial, aby tworzyć więcej exploitów. Więcej informacji o tym narzędziu znajdziesz w slajdach prezentacji, gdzie narzędzie zostało przedstawione: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec może być używany do generowania ładunków w celu wykorzystania różnych bibliotek serializacji Json i Yml w Javie.
Aby skompilować projekt, musiałem dodać te zależności do pom.xml
:
Zainstaluj maven, a następnie skompiluj projekt:
FastJSON
Dowiedz się więcej o tej bibliotece Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Laboratoria
Jeśli chcesz przetestować niektóre ładunki ysoserial, możesz uruchomić tę aplikację internetową: https://github.com/hvqzao/java-deserialize-webapp
Dlaczego
Java używa dużo serializacji do różnych celów, takich jak:
Zapytania HTTP: Serializacja jest powszechnie stosowana w zarządzaniu parametrami, ViewState, cookies, itp.
RMI (Remote Method Invocation): Protokół Java RMI, który w całości polega na serializacji, jest podstawą komunikacji zdalnej w aplikacjach Java.
RMI przez HTTP: Ta metoda jest powszechnie używana przez aplikacje internetowe oparte na Java z gruby klientem, wykorzystując serializację do komunikacji obiektów.
JMX (Java Management Extensions): JMX wykorzystuje serializację do przesyłania obiektów przez sieć.
Niestandardowe protokoły: W Javie standardową praktyką jest przesyłanie surowych obiektów Javy, co zostanie zademonstrowane w nadchodzących przykładach wykorzystania.
Zapobieganie
Obiekty przejściowe
Klasa implementująca Serializable
może oznaczyć jako transient
dowolny obiekt wewnątrz klasy, który nie powinien być serializowany. Na przykład:
Unikaj serializacji klasy, która musi implementować interfejs Serializable
W przypadkach, gdy pewne obiekty muszą implementować interfejs Serializable
ze względu na hierarchię klas, istnieje ryzyko niezamierzonej deserializacji. Aby temu zapobiec, upewnij się, że te obiekty nie mogą być deserializowane, definiując metodę final
readObject()
, która konsekwentnie zgłasza wyjątek, jak pokazano poniżej:
Poprawa bezpieczeństwa deserializacji w Javie
Dostosowywanie java.io.ObjectInputStream
jest praktycznym podejściem do zabezpieczania procesów deserializacji. Ta metoda jest odpowiednia, gdy:
Kod deserializacji jest pod kontrolą.
Klasy oczekiwane do deserializacji są znane.
Zastąp metodę resolveClass()
w celu ograniczenia deserializacji tylko do dozwolonych klas. Zapobiega to deserializacji dowolnej klasy oprócz tych, które są wyraźnie zezwolone, jak w poniższym przykładzie, który ogranicza deserializację tylko do klasy Bicycle
:
Korzystanie z agenta Java w celu zwiększenia bezpieczeństwa oferuje rozwiązanie awaryjne, gdy modyfikacja kodu nie jest możliwa. Ta metoda dotyczy głównie czarnolistowania szkodliwych klas, korzystając z parametru JVM:
Zapewnia sposób na dynamiczne zabezpieczenie deserializacji, idealny do środowisk, w których natychmiastowe zmiany w kodzie są niemożliwe.
Sprawdź przykład w rO0 autorstwa Contrast Security
Wdrażanie filtrów serializacji: Java 9 wprowadziła filtry serializacji za pośrednictwem interfejsu ObjectInputFilter
, zapewniając potężny mechanizm określania kryteriów, które muszą spełniać obiekty zserializowane przed ich deserializacją. Filtry te mogą być stosowane globalnie lub na poziomie strumienia, oferując precyzyjną kontrolę nad procesem deserializacji.
Aby skorzystać z filtrów serializacji, można ustawić filtr globalny, który będzie stosowany do wszystkich operacji deserializacji lub skonfigurować go dynamicznie dla konkretnych strumieni. Na przykład:
Wykorzystywanie Zewnętrznych Bibliotek w Celu Wzmocnienia Bezpieczeństwa: Biblioteki takie jak NotSoSerial, jdeserialize i Kryo oferują zaawansowane funkcje do kontroli i monitorowania deserializacji w Javie. Te biblioteki mogą zapewnić dodatkowe warstwy zabezpieczeń, takie jak tworzenie listy białej lub czarnej klas, analizowanie obiektów zserializowanych przed deserializacją oraz implementowanie niestandardowych strategii serializacji.
NotSoSerial przechwytuje procesy deserializacji w celu zapobiegania wykonaniu niezaufanego kodu.
jdeserialize umożliwia analizę obiektów zserializowanych w Javie bez ich deserializacji, pomagając zidentyfikować potencjalnie złośliwe treści.
Kryo to alternatywny framework serializacji, który kładzie nacisk na szybkość i wydajność, oferując konfigurowalne strategie serializacji, które mogą zwiększyć bezpieczeństwo.
Odnośniki
Prezentacja na temat deserializacji i ysoserial: http://frohoff.github.io/appseccali-marshalling-pickles/
Prezentacja na temat gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 oraz slajdy: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
Artykuł na temat Marshalsec: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
Artykuł na temat deserializacji JSON w Java i .Net: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, prezentacja: https://www.youtube.com/watch?v=oUAeWhW5b8c oraz slajdy: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
CVE dotyczące deserializacji: https://paper.seebug.org/123/
Wstrzykiwanie JNDI i log4Shell
Dowiedz się, czym jest Wstrzykiwanie JNDI, jak je nadużywać za pomocą RMI, CORBA & LDAP oraz jak wykorzystać log4shell (oraz przykład tej podatności) na następnej stronie:
pageJNDI - Java Naming and Directory Interface & Log4ShellJMS - Java Message Service
Java Message Service (JMS) API to Java API middleware do przesyłania wiadomości między dwoma lub więcej klientami. Jest to implementacja do rozwiązania problemu producenta-konsumenta. JMS jest częścią Java Platform, Enterprise Edition (Java EE) i został zdefiniowany przez specyfikację opracowaną w Sun Microsystems, ale obecnie jest kierowany przez Java Community Process. Jest to standard komunikacji, który pozwala komponentom aplikacji opartym na Java EE tworzyć, wysyłać, odbierać i czytać wiadomości. Umożliwia komunikację między różnymi komponentami rozproszonej aplikacji w sposób luźno powiązany, niezawodny i asynchroniczny. (Z Wikipedia).
Produkty
Istnieje kilka produktów wykorzystujących to oprogramowanie pośredniczące do wysyłania wiadomości:
Wykorzystanie
W zasadzie istnieje wiele usług wykorzystujących JMS w niebezpieczny sposób. Dlatego jeśli masz wystarczające uprawnienia do wysyłania wiadomości do tych usług (zazwyczaj będziesz potrzebować prawidłowych poświadczeń), możesz wysłać zserializowane obiekty złośliwe, które zostaną zdeserializowane przez odbiorcę/subskrybenta. Oznacza to, że w tym wykorzystaniu wszyscy klienci korzystający z tej wiadomości zostaną zainfekowani.
Należy pamiętać, że nawet jeśli usługa jest podatna (ponieważ niebezpiecznie deserializuje dane wejściowe użytkownika), nadal musisz znaleźć prawidłowe gadżety do wykorzystania podatności.
Narzędzie JMET zostało stworzone do połączenia i ataku na te usługi, wysyłając wiele zserializowanych obiektów złośliwych za pomocą znanych gadżetów. Te ataki zadziałają, jeśli usługa nadal jest podatna i jeśli którykolwiek z użytych gadżetów znajduje się w podatnej aplikacji.
Odnośniki
Prezentacja JMET: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
W kontekście .Net, ataki deserializacji działają podobnie jak te znalezione w Javie, gdzie gadżety są wykorzystywane do uruchamiania określonego kodu podczas deserializacji obiektu.
Odcisk palca
WhiteBox
Kod źródłowy powinien być sprawdzony pod kątem wystąpień:
TypeNameHandling
JavaScriptTypeResolver
Należy skupić się na serializatorach, które pozwalają określić typ za pomocą zmiennej kontrolowanej przez użytkownika.
BlackBox
Wyszukiwanie powinno być skierowane na zakodowany w Base64 ciąg AAEAAAD///// lub podobny wzorzec, który może zostać zdeserializowany po stronie serwera, umożliwiając kontrolę nad typem do zdeserializowania. Może to obejmować, ale nie ograniczać się do, struktur JSON lub XML zawierających TypeObject
lub $type
.
ysoserial.net
W tym przypadku można skorzystać z narzędzia ysoserial.net w celu tworzenia exploitów deserializacyjnych. Po pobraniu repozytorium git należy skompilować narzędzie przy użyciu na przykład Visual Studio.
Jeśli chcesz dowiedzieć się, jak ysoserial.net tworzy swoje exploity, możesz sprawdzić tę stronę, gdzie wyjaśniono gadżet ObjectDataProvider + ExpandedWrapper + formatujący Json.Net.
Główne opcje ysoserial.net to: --gadget
, --formatter
, --output
i --plugin
.
--gadget
służy do wskazania gadżetu do wykorzystania (wskazuje klasę/funkcję, która będzie wykorzystana podczas deserializacji do wykonania poleceń).--formatter
, służy do wskazania metody serializacji exploitu (musisz wiedzieć, która biblioteka jest używana po stronie serwera do deserializacji ładunku i użyć tej samej do jego serializacji)--output
służy do wskazania, czy chcesz exploit w formacie surowym czy zakodowanym w Base64. Zauważ, że ysoserial.net zakoduje ładunek za pomocą UTF-16LE (domyślne kodowanie w systemie Windows), więc jeśli otrzymasz surowy i po prostu zakodujesz go z konsoli systemu Linux, możesz napotkać problemy z zgodnością kodowania, które uniemożliwią poprawne działanie exploitu (w HTB JSON box ładunek działał zarówno w UTF-16LE, jak i ASCII, ale to nie oznacza, że zawsze będzie działał).--plugin
ysoserial.net obsługuje wtyczki do tworzenia exploitów dla konkretnych frameworków jak ViewState
Więcej parametrów ysoserial.net
--minify
dostarczy mniejszego ładunku (jeśli to możliwe)--raf -f Json.Net -c "anything"
To wskaże wszystkie gadżety, które można użyć z podanym formatowaniem (Json.Net
w tym przypadku)--sf xml
możesz wskazać gadżet (-g
) i ysoserial.net będzie szukał formatowników zawierających "xml" (bez uwzględniania wielkości liter)
Przykłady exploitów ysoserial do tworzenia:
ysoserial.net ma również bardzo interesujący parametr, który pomaga lepiej zrozumieć, jak działa każde wykorzystanie: --test
Jeśli wskazujesz ten parametr, ysoserial.net spróbuje wykorzystania lokalnie, dzięki czemu możesz przetestować, czy twój ładunek zadziała poprawnie.
Ten parametr jest pomocny, ponieważ po przejrzeniu kodu znajdziesz fragmenty kodu takie jak ten (z ObjectDataProviderGenerator.cs):
To oznacza, że w celu przetestowania exploitu kod wywoła serializersHelper.JsonNet_deserialize
W poprzednim kodzie jest podatny na stworzenie eksploatacji. Więc jeśli znajdziesz coś podobnego w aplikacji .Net, oznacza to prawdopodobnie, że ta aplikacja jest również podatna.
Dlatego parametr --test
pozwala nam zrozumieć, które fragmenty kodu są podatne na eksploatację deserializacji, którą może stworzyć ysoserial.net.
ViewState
Zajrzyj do tego POSTA na temat jak próbować wykorzystać parametr __ViewState w .Net do wykonywania dowolnego kodu. Jeśli już znasz sekrety używane przez maszynę ofiary, przeczytaj ten post, aby dowiedzieć się, jak wykonać kod.
Zapobieganie
Aby zmniejszyć ryzyko związane z deserializacją w .Net:
Unikaj pozwalania strumieniom danych na definiowanie typów obiektów. Korzystaj z
DataContractSerializer
lubXmlSerializer
, gdy to możliwe.Dla
JSON.Net
, ustawTypeNameHandling
naNone
: %%%TypeNameHandling = TypeNameHandling.None%%%Unikaj używania
JavaScriptSerializer
zJavaScriptTypeResolver
.Ogranicz typy, które mogą być deserializowane, rozumiejąc związane z nimi ryzyka, takie jak
System.IO.FileInfo
w .Net, który może modyfikować właściwości plików serwera, potencjalnie prowadząc do ataków typu odmowy usługi.Bądź ostrożny z typami posiadającymi ryzykowne właściwości, takimi jak
System.ComponentModel.DataAnnotations.ValidationException
z jego właściwościąValue
, która może być wykorzystana.Bezpiecznie kontroluj instancjonowanie typów, aby zapobiec wpływowi atakujących na proces deserializacji, czyniąc nawet
DataContractSerializer
lubXmlSerializer
podatnymi.Wprowadź kontrolę białej listy za pomocą niestandardowego
SerializationBinder
dlaBinaryFormatter
iJSON.Net
.Bądź na bieżąco z znanymi niebezpiecznymi gadżetami deserializacji w .Net i upewnij się, że deserializatory nie instancjonują takich typów.
Izoluj potencjalnie ryzykowny kod od kodu z dostępem do internetu, aby uniknąć ujawniania znanych gadżetów, takich jak
System.Windows.Data.ObjectDataProvider
w aplikacjach WPF, dla niezaufanych źródeł danych.
Referencje
Dokument na temat deserializacji JSON w Java i .Net: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, prezentacja: https://www.youtube.com/watch?v=oUAeWhW5b8c oraz slajdy: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
Ruby
W Ruby, serializacja jest ułatwiana przez dwie metody w bibliotece marshal. Pierwsza metoda, znana jako dump, służy do przekształcenia obiektu w strumień bajtów. Ten proces nazywa się serializacją. Z kolei druga metoda, load, służy do przywrócenia strumienia bajtów z powrotem do obiektu, proces ten nazywa się deserializacją.
Dla zabezpieczenia zserializowanych obiektów, Ruby wykorzystuje HMAC (Hash-Based Message Authentication Code), zapewniając integralność i autentyczność danych. Klucz używany w tym celu jest przechowywany w jednym z kilku możliwych miejsc:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Łańcuch gadżetów deserializacji do RCE w Ruby 2.X (więcej informacji w https://www.elttam.com/blog/ruby-deserialization/):
Inny łańcuch RCE do wykorzystania w Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Last updated