Zakład podatności na błąd PHP regex
Dziś mój kolega argumentował ze mną, że zna sposób, aby zapewnić specjalnie sformatowany ciąg, który może przekazać następującą kontrolę regex, a jednocześnie podaj nazwę pliku z rozszerzeniem .php lub
.jsp </Code> lub[code].asp
: [/code]if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $var) && preg_match('/\.(asp|jsp|php)$/i', $var) == false)
{
echo "No way you have extension .php or .jsp or .asp after this check.";
}
Bez względu na to, jak bardzo się starałem i przeszukiwałem sieć, nie mogłem znaleźć ani jednej usterki, która by to umożliwiła. Może czegoś mi brakuje? Biorąc pod uwagę, że luka w zabezpieczeniach bajtu zerowego została naprawiona, co jeszcze może być problemem?
Uwaga: w żaden sposób nie sugeruję, że ten kod jest w pełni przetestowaną metodą sprawdzania rozszerzenia pliku, może występować defekt w funkcji
preg_match ()lub zawartość pliku może być inny format, po prostu zadaję pytanie z kropki w odniesieniu do samej składni wyrażenia regularnego.
Kod edycji
:
if (isset($_FILES["image"]) && $_FILES["image"]["name"] && preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $_FILES["image"]["name"]) && preg_match('/\.(asp|jsp|php)$/i', $_FILES["image"]["name"]) == false) {
$time = time();
$imgname = $time . "_" . $_FILES["image"]["name"];
$dest = "../uploads/images/"; if (file_exists($dest) == false) {
mkdir($dest);
} copy($_FILES['image']['tmp_name'], $dest . $imgname); }else{
echo "Invalid image file";
}
Wersja PHP: 5.3.29
EDYCJA: epilog
Okazało się, że „luka” występuje tylko w systemie Windows. Jednak zrobił dokładnie to, co powiedział mi mój kolega - przeszedł test regex i zapisał plik z rozszerzeniem wykonywalnym. Poniższe elementy zostały przetestowane pod kątem
WampServer 2.2z
PHP 5.3.13:
Przekazanie następującego wiersza do sprawdzenia wyrażenia regularnego powyżej
test.php: .jpg(zwróć uwagę na dwukropek „:” na końcu żądanego rozszerzenia) spowoduje jego sprawdzenie, a
copy ()function. wydaje się pomijać wszystko po znaku dwukropka, w tym sam znak.
Ponownie dotyczy to tylko okien. W systemie Linux plik zostanie zapisany pod dokładnie taką samą nazwą, jak ta przekazana funkcji. [/code]
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
4 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
W tym przykładzie przekazujesz go do , ale wspomniałeś, że od jakiegoś czasu używasz tej metody do sprawdzania pliku ext, więc zakładam, że miałeś inne przypadki, w których ta procedura mogła być używana wraz z innymi funkcjami w różnych wersjach PHP.
Potraktuj to jako procedurę testową (używając include, require):
To zakończy się „in !!!!” a uruchamiając „test.php”, nawet jeśli jest załadowany, włączy go z folderu tmp - oczywiście w tym przypadku należysz już do atakującego, ale spójrzmy również na te opcje.
Nie jest to typowy skrypt procedury rozruchu, ale jest to koncepcja, której można użyć, łącząc kilka metod:
Przejdźmy dalej - jeśli wykonasz:
I znowu wszystko jest w porządku. Plik jest kopiowany do folderu „
uploads
"- Nie możesz uzyskać bezpośredniego dostępu do niego (ponieważ serwer WWW będzie szablon prawej strony #), ale wprowadziłeś plik, a atakujący może znaleźć sposób lub innego słabego miejsca, aby zadzwonić później.
Przykład takiego skryptu wykonawczego jest powszechny w witrynach udostępnianych i hostujących, w których pliki są obsługiwane przez skrypt PHP, który (w niektórych niezabezpieczonych przypadkach) może załadować plik, dołączając do niego niewłaściwy typ funkcji, na przykład , , , które są podatne na ataki i mogą wykonać plik. [/code]
Null Bayt.
ataki zerobajtowe były poważną słabością w php & < 5.3, ale zostały ponownie wprowadzone przez regresję w wersji 5.4+ w niektórych funkcjach, w tym we wszystkich funkcjach związanych z plikami i wielu innych w rozszerzeniach. Zostało to naprawione kilka razy, ale nadal istnieje i wiele starszych wersji jest nadal w użyciu. Jeśli pracujesz ze starszą wersją php, na pewno jesteś narażony na:
Zostanie wydrukowany „w !!!!” i skopiuje twój plik o nazwie „test.php”.
Sposób php naprawił to, sprawdzając długość ciągu przed i po przekazaniu go do głębszej procedury C, która tworzy rzeczywistą tablicę znaków, a zatem jeśli ciąg jest obcięty do bajtu zerowego (co wskazuje koniec ciągu w C ) długość nie będzie pasować.
więcej szczegółów
http://www.madirish.net/401
Co dziwne, nawet w poprawionych i nowoczesnych wydaniach PHP, nadal istnieje:
Mój wniosek:
Twoja metoda sprawdzania rozszerzeń plików mogłaby zostać znacznie ulepszona - Twój kod pozwala plikowi PHP o nazwie przejść przez niego, podczas gdy nie powinien. Skuteczne ataki są zasadniczo przeprowadzane poprzez połączenie wielu luk, nawet tych mniejszych - każdy nieoczekiwany wynik i zachowanie należy traktować jako jeden.
Uwaga
: wciąż jest wiele problemów z nazwami plików i obrazami, ponieważ są one później umieszczane wielokrotnie na stronach i jeśli nie są prawidłowo filtrowane i bezpiecznie dołączane, narażasz się na wiele innych rzeczy związanych z XSS, ale to jest poza tematem.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
http://php.net/manual/en/function.preg-match.php
zwraca 1, jeśli wzorzec pasuje do podanego tematu, 0, jeśli nie pasuje, lub FALSE, jeśli wystąpił błąd.
Więc kiedy zamierzasz przetestować swój kod, użyj .
Idealnie powinieneś użyć.
>
Anonimowy użytkownik
Potwierdzenie od:
PHP < 5.3.X
PHP pozwala na to, aby linie zawierały , ten znak jest uważany za koniec linii
Na przykład, jeśli twój ciąg zawiera:
myfile.exe\0.jpg
wtedy będzie pasować
jpg
ale inni
Funkcje PHP zatrzymają się na
myfile.exe,
np. funkcje lub