11-01-2019 / Od 0 do pentestera

PHAR Injection

Dzisiaj o funkcji sprawdzającej czy plik o podanej nazwie istnieje na dysku.

Czy ta prosta funkcjonalność może wyrządzić nam jakieś szkody?

Popatrzmy na przykładową aplikację:

<?php
class aplikacja {
	function __construct($name) {
		$this->name = './pliki/'.$name;
		if (strpos($this->name, "..") !== false) {
			die('HACKER');
		}
		if (file_exists($name)) {
			echo 'USUNIETO';
		} else {
			echo 'PLIK NIE ISTNIEJE';
		}
	}
	function __destruct() {
		echo 'EXPLOIT'.$this->name;
	}
}
new aplikacja($_GET['p']);

Sprawdzamy w niej, czy podany przez użytkownika plik znajduje się na dysku w katalogu pliki.

Korzystamy przy tym z pomocy funkcji file_exists.

Oczywiście jesteśmy świadomi ataku path traversal, w którym użytkownik mógłby użyć ciągu znaków z kropką i slashem w celu sprawdzenia istnienia plików poza katalogiem pliki.

Dlatego też sprawdzamy, czy w podanym przez użytkownika ciągu nie istnieją dwie kropki.

Jeżeli plik istnieje - wyświetlamy odpowiedni komunikat.

Korzystamy też z magicznej funkcji __destruct, która usuwa plik o który prosił użytkownik.

W naszym wypadku symulujemy to usunięcie funkcją echo - tak aby zobaczyć co tak naprawdę dzieje się w tym przykładzie.

Jest to więc prosta funkcjonalność usuwania plików z serwera - na przykład zdjęć użytkownika z danego katalogu.

Jeszcze do niedawna można by było założyć, że używany tutaj kod jest bezpieczny.

Bronimy się przecież przed atakiem path traversal i usuwamy pliki jedynie z jednego katalogu.

Branża bezpieczeństwa to jednak dynamiczny rynek - gdzie wszystko jest możliwe.

Jakiś czas temu przedstawiono nowy atak na aplikacje stworzone w języku PHP.

Do jego przeprowadzenia korzysta się z plików phar. Co to za pliki?

Jest to format podobny do javowych plików jar.

Zatem przy pomocy tego formatu możemy spakować całą naszą wielo-plikową aplikację do jednego, przenośnego pliku będącego swego rodzaju archiwum.

Dlaczego to takie istotne z punktu widzenia bezpieczeństwa?

Niektóre funkcje związane z odczytywaniem plików z dysku oprócz standardowych parametrów obsługują również tak zwane wrappery1.

To właśnie dzięki nim funkcje te mogą obsługiwać dodatkowe formaty.

Takim wrapperem jest protokół http:// czy też ftp://.

Jest nim także phar.

Co dalej? Badacze odkryli, że jeżeli skorzystamy z funkcji obsługującej wrappery - czyli na przykład file_exists i jako parametr przekażemy do niej wrapper phar - to funkcja ta oprócz sprawdzenia, czy plik rzeczywiście istnieje - otworzy także jego zawartość.

Co rozumiem przez słowo "otworzy"?

Archiwum phar oprócz treści plików przechowuje także metadane na temat całej paczki.

A jak możemy wyczytać w dokumentacji2 - są one przechowywane w zserializowanej formie.

W PHP oznacza to, że do ich zapisania używa się funkcji serialize, a do ich odczytania funkcji unserialize.

Funkcja file_exists wykonuje zatem funkcję unserialize na metadanych paczki przekazanej do niej jako parametr.

Jest to więc klasyczny atak object injection - kiedy to dane od atakującego są przekazywane do funkcji unserialize.

Wystarczy zatem stworzyć przykładowy plik phar i w jego treści zawrzeć obiekt, który chcemy przekazać do atakowanej przez nas aplikacji.

Zobaczmy na nasz przykład jeszcze raz.

Naszym celem jest usunięcie pliku poza katalogiem "pliki".

Tworzymy więc paczkę phar a w niej przykładowy obiekt klasy aplikacja.

Tam ustawiamy parametr name na interesującą nas wartość.

Teraz wystarczy już tylko wysłać ten plik na serwer, a następnie wywołać funkcję file_exists używając wrappera phar.

Jak widzisz - został tutaj usunięty pliki spoza katalogu pliki.

Stało się tak, ponieważ treść metadanych została odczytana przez funkcję file_exists.

Nasz test przeciwko atakom nie zadziałał - parametr od użytkownika bowiem nie zawierał podwójnej kropki.

Jaki morał płynie z tego ataku?

W przeszłości wystarczyło sprawdzać, czy nie posiadamy funkcji unserialize w kodzie źródłowym naszej aplikacji.

Teraz należy dodatkowo sprawdzać, czy parametr przekazywany przez użytkownika nie zawiera słowa kluczowego phar.

Icon made by Freepik, Smashicons, Maxim Basinski Premium from www.flaticon.com