<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
Jeśli w PHP używane jest `==`, mogą wystąpić przypadki, w których porównanie nie zachowuje się oczekiwanie. Dzieje się tak, ponieważ "==" porównuje tylko wartości przekształcone do tego samego typu, jeśli chcesz również porównać, czy typ porównywanych danych jest taki sam, musisz użyć `===`.
*`"0xAAAA" == "43690" -> True` Ciągi złożone z liczb w formacie dziesiętnym lub szesnastkowym można porównać z innymi liczbami/ciągami, uzyskując wynik True, jeśli liczby były takie same (liczby w ciągu są interpretowane jako liczby)
*`"0e3264578" == 0 --> True` Ciąg rozpoczynający się od "0e" i zawierający cokolwiek będzie równy 0
*`"0X3264578" == 0X --> True` Ciąg rozpoczynający się od "0" i zawierający dowolną literę (X może być dowolną literą) oraz cokolwiek będzie równy 0
*`"0e12334" == "0" --> True` Jest to bardzo interesujące, ponieważ w niektórych przypadkach można kontrolować wejściowy ciąg znaków "0" oraz pewną zawartość, która jest haszowana i porównywana do niego. Dlatego jeśli można podać wartość, która spowoduje utworzenie hasza zaczynającego się od "0e" i bez żadnej litery, można ominąć porównanie. Można znaleźć **już zahaszowane ciągi** w tym formacie tutaj: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
*`"X" == 0 --> True` Dowolna litera w ciągu jest równa liczbie całkowitej 0
Więcej informacji na stronie [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
Jeśli ta funkcja jest używana do **jakiejkolwiek weryfikacji uwierzytelniania** (takiej jak sprawdzanie hasła) i użytkownik kontroluje jedną stronę porównania, może wysłać pusty tablicę zamiast ciągu znaków jako wartość hasła (`https://example.com/login.php/?username=admin&password[]=`) i ominąć tę weryfikację:
Nawet jeśli jest używany `===`, mogą wystąpić błędy, które sprawiają, że porównanie jest podatne na surowe rzucanie typów. Na przykład, jeśli porównanie konwertuje dane na inny typ obiektu przed porównaniem:
**`preg_match()`** może być używane do **sprawdzania poprawności danych wprowadzanych przez użytkownika** (sprawdza, czy jakiekolwiek **słowo/wyrażenie regularne** z **czarnej listy** jest **obecne** w **danych wprowadzanych przez użytkownika**, a jeśli nie, kod może kontynuować swoje wykonanie).
Jednakże, gdy ograniczamy początek wyrażenia regularnego, `preg_match()`**sprawdza tylko pierwszą linię danych wprowadzonych przez użytkownika**, więc jeśli w jakiś sposób można **przesłać** dane wejściowe w **kilku liniach**, można ominięć tę kontrolę. Przykład:
Aby ominąć tę kontrolę, możesz **wysłać wartość z zakodowanymi znakami nowej linii** (`%0A`) lub jeśli możesz wysłać **dane JSON**, wyślij je w **kilku liniach**:
Jeśli możesz przesłać do `preg_match()`**bardzo dużą poprawną wartość wejściową**, nie będzie w stanie jej przetworzyć, co pozwoli Ci **obejść** sprawdzenie. Na przykład, jeśli jest na czarnej liście JSON, możesz przesłać:
Sztuczka z: [https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223](https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223) i [https://mizu.re/post/pong](https://mizu.re/post/pong)
W skrócie problem występuje, ponieważ funkcje `preg_*` w PHP bazują na [bibliotece PCRE](http://www.pcre.org/). W PCRE pewne wyrażenia regularne są dopasowywane poprzez dużą liczbę wywołań rekurencyjnych, co zużywa dużo miejsca na stosie. Możliwe jest ustawienie limitu na ilość dozwolonych rekursji, ale w PHP ten limit [domyślnie wynosi 100 000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), co jest więcej niż mieści się na stosie.
[Wątek na Stackoverflow](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) został również podlinkowany w poście, gdzie bardziej szczegółowo omówiono ten problem. Naszym zadaniem było teraz jasne:\
**Wysłać dane wejściowe, które sprawią, że wyrażenie regularne wykona ponad 100 000 rekursji, powodując SIGSEGV, sprawiając, że funkcja `preg_match()` zwróci `false`, co sprawi, że aplikacja uzna, iż nasze dane wejściowe nie są złośliwe, rzucając niespodziankę na końcu ładunku w postaci czegoś w stylu `{system(<bardzozłepolecenie>)}` aby uzyskać SSTI --> RCE --> flaga :)**.
Cóż, w terminach wyrażeń regularnych, faktycznie nie wykonujemy 100 tys. "rekursji", ale zamiast tego liczymy "kroki wstecz", które, jak podaje [dokumentacja PHP](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), domyślnie wynoszą 1 000 000 (1M) w zmiennej `pcre.backtrack_limit`.\
Jeśli PHP przekierowuje do innej strony, ale nie jest wywoływana funkcja **`die`** lub **`exit`** po ustawieniu nagłówka `Location`, PHP kontynuuje wykonywanie i dołącza dane do ciała strony:
* **register\_globals**: W **PHP < 4.1.1.1** lub gdy jest błędnie skonfigurowany, **register\_globals** może być aktywny (lub ich zachowanie jest imitowane). Oznacza to, że w zmiennych globalnych jak $\_GET, jeśli mają wartość np. $\_GET\["param"]="1234", można uzyskać do niej dostęp za pomocą **$param**. Dlatego wysyłając parametry HTTP, można nadpisać zmienne używane w kodzie.
* **Ciasteczka PHPSESSION z tej samej domeny są przechowywane w tym samym miejscu**, dlatego jeśli w obrębie domeny **używane są różne ciasteczka w różnych ścieżkach**, można spowodować, że ścieżka **uzyskuje dostęp do ciasteczka z innej ścieżki**, ustawiając wartość ciasteczka z innej ścieżki.
W ten sposób, jeśli **obie ścieżki uzyskują dostęp do zmiennej o tej samej nazwie**, można sprawić, że **wartość tej zmiennej w ścieżce 1 będzie stosowana do ścieżki 2**. Następnie ścieżka 2 uzna zmienne ścieżki 1 za ważne (nadając ciasteczku nazwę odpowiadającą jej w ścieżce 2).
Te funkcje są zazwyczaj używane w PHP do **generowania hashy z haseł** i do **sprawdzania**, czy hasło jest poprawne w porównaniu z haszem.\
Obsługiwane algorytmy to: `PASSWORD_DEFAULT` i `PASSWORD_BCRYPT` (zaczyna się od `$2y$`). Zauważ, że **PASSWORD\_DEFAULT jest często takie samo jak PASSWORD\_BCRYPT.** Obecnie **PASSWORD\_BCRYPT** ma **ograniczenie rozmiaru wejścia do 72 bajtów**. Dlatego, gdy próbujesz zahaszować coś większego niż 72 bajty tym algorytmem, użyte zostaną tylko pierwsze 72B:
Z [**tego wątku na Twitterze**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A\&s=19) można zobaczyć, że wysłanie więcej niż 1000 parametrów GET lub 1000 parametrów POST lub 20 plików spowoduje, że PHP nie będzie ustawiał nagłówków w odpowiedzi.
Pozwalając na obejście na przykład ustawiania nagłówków CSP w kodach takich jak:
#### Wypełnianie treści przed ustawieniem nagłówków
Jeśli **strona w PHP drukuje błędy i echo z powrotem pewne dane wprowadzone przez użytkownika**, użytkownik może sprawić, że serwer PHP wydrukuje pewne **treści wystarczająco długie**, aby kiedy spróbuje **dodać nagłówki** do odpowiedzi, serwer zwróci błąd.\
W następującym scenariuszu **atakujący sprawił, że serwer zwrócił kilka dużych błędów**, i jak widać na ekranie, kiedy PHP spróbowało **zmodyfikować informacje nagłówka, nie mogło** (więc na przykład nagłówek CSP nie został wysłany do użytkownika):
Ta funkcja w php pozwala ci **wykonać kod napisany w postaci ciągu znaków**, aby **zwrócić true lub false** (i w zależności od tego zmienić wykonanie). Zazwyczaj zmienna użytkownika zostanie wstawiona w środku ciągu znaków. Na przykład:\
Będziesz musiał **przerwać** składnię kodu, **dodać** swój **payload**, a następnie ponownie ją **naprawić**. Możesz użyć operacji logicznych takich jak "**and" lub "%26%26" lub "|"**. Należy zauważyć, że "or" lub "||" nie działają, ponieważ jeśli pierwszy warunek jest prawdziwy, nasz payload nie zostanie wykonany. Podobnie nie działa ";" ponieważ nasz payload nie zostanie wykonany.
Jeśli możesz **załadować** plik **.htaccess**, to możesz **skonfigurować** kilka rzeczy i nawet wykonać kod (konfigurując pliki z rozszerzeniem .htaccess, aby mogły być **wykonywane**).
Jeśli znajdziesz podatność, która pozwala Ci **modyfikować zmienne środowiskowe w PHP** (i inną do wgrywania plików, chociaż po dokładniejszym zbadaniu może to być obejścione), możesz wykorzystać to zachowanie do uzyskania **RCE**.
* [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/#ld\_preload-and-ld\_library\_path): Ta zmienna środowiskowa pozwala na ładowanie dowolnych bibliotek podczas wykonywania innych binariów (choć w tym przypadku może nie działać).
* **`PHPRC`** : Wskazuje PHP, **gdzie znajduje się plik konfiguracyjny**, zwykle nazywany `php.ini`. Jeśli możesz wgrać swój własny plik konfiguracyjny, użyj `PHPRC` aby wskazać PHP na niego. Dodaj wpis **`auto_prepend_file`** określający drugi wgrany plik. Ten drugi plik zawiera normalny **kod PHP, który jest następnie wykonywany** przez środowisko PHP przed jakimkolwiek innym kodem.
2. Wgraj drugi plik zawierający dyrektywę **`auto_prepend_file`** instruującą preprocesor PHP do wykonania pliku, który wgraliśmy w kroku 1
3. Ustaw zmienną `PHPRC` na plik, który wgraliśmy w kroku 2.
* Uzyskaj więcej informacji na temat wykonania tego łańcucha [**z oryginalnego raportu**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/).
* **PHPRC** - kolejna opcja
* Jeśli **nie możesz wgrywać plików**, możesz użyć w FreeBSD pliku "file" `/dev/fd/0`, który zawiera **`stdin`**, będący **treścią** żądania wysłanego do `stdin`:
Owińce i protokoły PHP mogą pozwolić Ci **obejść zabezpieczenia zapisu i odczytu** w systemie i go skompromitować. Aby uzyskać [**więcej informacji, sprawdź tę stronę**](../../../pentesting-web/file-inclusion/#lfi-rfi-using-php-wrappers-and-protocols).
Jeśli zauważysz, że **Xdebug** jest **włączony** w wyniku `phpconfig()`, powinieneś spróbować uzyskać RCE za pomocą [https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit)
XOR (exclusive OR) to operacja logiczna, która zwraca prawdę tylko wtedy, gdy oba argumenty są różne. W kontekście hakowania XOR jest często wykorzystywany do szyfrowania danych lub do manipulacji wartościami bitowymi.
Więc jeśli możesz **wykonać dowolny kod PHP bez użycia cyfr i liter**, możesz wysłać żądanie, wykorzystując poniższy payload do wykonania arbitralnego kodu PHP:
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF** sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.