Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book
Programisto PHP, mamy dla Ciebie niespodziankę. Wytłumaczymy na przykładzie podatności RCE w CentOS Web Panel (luka nie wymaga uwierzytelnienia)
Tutaj inspirujący odpis podatności – CVE-2021-45467: CWP (CentOS Web Panel) – preauth RCE.
Zobaczcie ten fragment kodu:
<?php
if(!empty($_GET["api"])) {
…
if (!empty($_GET["scripts"])) {
$_GET["scripts"] = GETSecurity($_GET["scripts"]);
include "../../resources/admin/scripts/" . $_GET["scripts"] . ".php";
}
…
Może dałoby się podać wartość zmiennej scripts jako ../../../ i tym samym zaincludować jakiś inny plik z serwera?
Nie da się! Bo wredny system od razu wykrywa „hacking attempt”. Wykrycie to znajduje się w funkcji GETSecurity():
function GETSecurity($variable)
{
if (stristr($variable, ".." ) {
exit("hacking attempt");
}
}
Więc jeśli gdziekolwiek w wartości będziemy mieć podwójną kropkę – amen.
No dobrze, ale może podejść do tematu inaczej – czyli w ogóle nie używać dwóch kropek, ale jednak osiągnąć cel: tj. zaincludowanie dowolnego pliku z katalogu nadrzędnego?
No właśnie okazuje się, że można użyć ciągu .%00.
Dochodzimy tym samym do sedna cytowanego badania:
Most PHP’s functions (including the require() and include() functions) seem to process /.%00./ as /../ – Similarly, while stristr() ignores the null bytes, it still counts its size so it bypasses the check.
Co dalej? Można było bez uwierzytelnienia dodać swój klucz API do systemu:
GET https://CWP/user/loader.php?api=1&scripts= .%00./.%00./api/account_new_create&acc=guadaapi&ip=192.168.1.1&keyapi=OCTAGON
A następnie już śmiało korzystać z klucza API (w przykładzie jego wartość to: OCTAGON), który daje pełny dostęp do wszystkich funkcji w systemie:
Now we have added the api key “OCTAGON” requesting from 192.168.1.1 to have access to the full API like the following:
GET https://CWP/api/?key=OCTAGON&api=add_server
Dalej poszło względnie z górki, bo wystarczyło odpowiednią funkcją API umieścić kawałek kodu w pliku na serwerze, a później wcześniejszą metodą go zaincludować.
Nota bene, twórcy CentOS Web Panel próbowali nieco panicznej obrony, przygotowując taką łatkę:
function GETSecurity($variable)
{
if (stristr($variable, "..") || stristr($variable, ".%00.")) {
exit("hacking attempt");
}
}
Ale można było ją ominąć takim payloadem:
.%00%00%00./.%00%00%00./api/account_new_create
Morał: sprawdzenie w PHP czy jakaś wartość nie zawiera ciągu .. (jako próba ochrony przed podatnością klasy path traversal) może nie być wystarczające.
~Michał Sajdak
Nie lepiej bylo uzyc regexpa do takiego filtrowania albo lepiej funkcji typu safe string? Wyglada to jakby jakies nastoletnie dzieci pisaly ten skrypt xd
Mam serwer z cwp, panel nie jest dostępny z zewnątrz tylko lokalnie (nie są otwarte porty panelu admina i userów) czy podatność też mnie dotyczy?
Podobno nulle w ścieżkach zostały dawno temu załatane:
Paths with NULL in them (foo\0bar.txt) are now considered as invalid (CVE-2006-7243).
To jest test skryptu moderującego.
Sprawdzam, czy da się podszyć pod nadawcę „sekurak” ;-)).
wpisać w „from” możesz cokolwiek ;) ale nasze komentarze odpowiednio się odróżniają od reszty (ten się nie odróżnia)
„nasze komentarze odpowiednio się odróżniają od reszty”
U mnie się nie odróżniają.
Aha, czy może macie na myśli nieznacznie inny kolor tła?
Zauważyłem to dopiero wtedy, gdy zrobiłem printscreen i zacząłem przycinać obrazek w programie graficznym.
Nie widzę różnicy dopóki nie spojrzę na wyświetlacz pod nietypowym kątem.
Wg mnie lepiej byłoby, gdyby Wasze komentarze bardziej wyraźnie się odróżniały.
czyli się wyróżnia, tylko mało wyraziście ;-)
To nie możecie zrobić, aby się wyróżniały BARDZIEJ wyraziście? Pięknie proszę…
pewnie możemy – przy następnej „większej” aktualizacji layoutu (btw ostatnio doszedł „ciemny motyw”)
Uoo panie, zmień monitor! Szkoda oczu! Albo poczytaj jak się ustawia jasność i kontrast (choćby na skali szarości). U mnie widać wyraźnie, że Sekurakowe komentarze są na białym.
„U mnie się nie odróżniają.”
Masz kiepski monitor. Albo oczy. :-)
Ponadto w prawym górnym rogu u prawdziwego sekuraka jest ikonka.
Zwiekszylem jasnosc do maksimum i nie jest lepiej.
A zadna ikonka sie nie wyswietla.
Wiec licze na spelnienie przez Sekuraka obietnicy zwiekszenia roznicy przy okazji aktualizacji layoutu.
To jak ma wyglądać funkcja GETSecurity(), żeby to naprawić?
Możliwości jest kilka – ale ogólna zasada mówi żeby nie wywalać czegoś, co może być niebezpieczne (blacklisting) – tylko akceptować jedynie to, o czym wiemy że jest bezpieczne (np. ciąg małych liter)
dziękuję za wskazówkę
Allowlista to najlepsza opcja. Alternatywnie można użyć realpath() do sprawdzenia gdzie dokładnie prowadzi ścieżka. Temat bezpieczeństwa ścieżek opisany jest w dokumentacji:
https://www.php.net/manual/en/security.filesystem.php
https://www.php.net/manual/en/security.filesystem.nullbytes.php
Ja ciągle wchodze w te pehapy, ale czy te if to skrót od gif?! I wogule gdzie są te obrazki (te gify).
*w ogóle ;)
To nie kwestia języka a tego kto pisał panel. Równie dobrze mogło to być w Javascript
Z ciekawości zanotowałem sobie CVE do sprawdzenia, bo ta podatność wydała mi się grubymi nićmi szyta. Czy to to normalna praktyka, że wpisy do CVE nie są aktualizowane przy potwierdzonych i rozwiązanych podatnościach, czy po prostu chodziło o „ferment” w mediach?