Translate: 
EnglishFrenchGermanItalianPolishPortugueseRussianSpanish

Jak obejść limit przestrzeni dyskowej na koncie WWW

Przy wyborze serwera hostingowego pod nową stronę WWW jednym z głównych czynników decydujących „za” lub „przeciw” jest limit dostępnej przestrzeni dyskowej.

Chociaż w dzisiejszych czasach większość firm na rynku prześciga się między sobą w ilości oferowanych gigabajtów (tak dostępnego transferu, jak i powierzchni), zademonstruję, jak te limity obejść całkowicie (lecz krótkoterminowo).

Teoria

Większość serwisów hostingowych swoje limity opiera na gotowych funkcjach udostępnianych przez system operacyjny. Rozwiązanie to upraszcza znacznie zarządzanie kontami użytkowników, nie obciążając przy tym dodatkowo samego serwera.

W tym artykule skupię się na najpopularniejszej platformie hostingowej PHP, do której zalicza się grupę systemów Linux/BSD oraz Unix. W wymienionych OS’ach za obsługę powierzchni dyskowej odpowiedzialny jest mechanizm quoty.

Ogólną cechą mechanizmu quoty jest to, że w prosty sposób można przy jej pomocy ograniczyć powierzchnię dyskową dla poszczególnych systemów plików (w olbrzymim uproszczeniu: odpowiedników windowsowych partycji).

Taka funkcjonalność pozwala administratorom hostingów na tworzenie różnorodnych, czasami niezależnych od siebie ograniczeń (np. oferty kont o pojemności 200MB na FTP, lecz tylko 50MB dla bazy MySQL), a nam… ułatwia zadanie ich obejścia.

Praktyka

Jak działa taka quota w praktyce? Przyjrzymy się temu od strony administratora hostingowego.

Naszym kontem testowym będzie login „tester”.

Po utworzeniu konta „tester” na serwerze poleceniem useradd lub jego programowym odpowiednikiem (najczęściej automatycznie przez oprogramowanie zarządzające) następuje przydzielenie limitów powierzchni w systemie.

Zakładając, że nasze konto testowe znajduje się w katalogu /home/tester na systemie plików /dev/sdc1, w celu ustawienia limitów najprostszym sposobem będzie posłużenie się interaktywnym poleceniem edquota lub nieinteraktywnym setquota, np. w ten sposób:

[root@hosting ~]# edquota tester

Po wykonaniu tego polecenia pojawia się nam ekran edycji zawierający przykładowy wynik :

Disk quotas for user tester (uid 777):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/sdc1                         7          0          0          6        0         0

W tym miejscu administrator jest w stanie edytować limity użytkownika, takie jak ilość zajętej przestrzeni przez wszystkie pliki (pierwsze dwie kolumny: „soft” oraz „hard”), a także limit ilości wszystkich plików na koncie (ostatnie dwie kolumny: „soft” oraz „hard”).
Pozostałe dwie kolumny przedstawiają ilość obecnie użytej przestrzeni oraz liczbę już zapisanych plików.

Do tego momentu wszystko jest w porządku. Użytkownik po edycji limitów na takie:

  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/sdc1                         7     400000     400000          6     2000     2000

…posiada konto o pojemności 400MB oraz limit do 2 tysięcy plików.

Tutaj jednak pojawia się pewna ciekawostka.

Szukanie dziury w całym…

Wpisanie innego systemowego polecenia: df

[root@hosting ~]# df -h

oznajmia nam, że na serwerze istnieje więcej systemów plików, niż tylko /dev/sdc1:

Filesystem            Size  Used Avail Use% Mounted on
/dev/cciss/c0d0p1      63G   41G   23G  65% /
/dev/sdc1             624G  593G   32G  95% /home

Jest to oczywiście całkiem normalny widok, często spotykany na serwerach hostingowych, gdzie z powodu wydajności oraz bezpieczeństwa system operacyjny trzymany jest na innych dyskach, niż konta użytkowników.

Czemu jednak w trybie edycji quoty nie pojawiły nam się informacje o drugim systemie plików?

Odpowiedź jest prosta, mechanizm quoty można włączać niezależnie dla każdego systemu plików, polecenie edquota pozwala zaś edytować ustawienia tylko dla tych systemów, które mają włączone zliczanie limitów.

W tym przypadku możemy mieć potencjalnie do czynienia z przeoczeniem po stronie administratora serwera, wnioskując po mapowaniu ścieżek na systemy plików wynika, że cały system operacyjny (łącznie z katalogiem plików tymczasowych /tmp) znajduje się w systemie plików, który nie obsługuje quoty.

Co by było, gdyby zapisać tam własne pliki?

W końcu dodatkowe 23GB powierzchni piechotą nie chodzi… Niestety najprawdopodobniej próba zapisania w tym miejscu czegokolwiek z poziomu skryptu PHP zakończy się błędem.

Zależnie od konfiguracji serwera, dostęp do katalogów nie należących do użytkownika „tester” będzie ograniczony podstawowymi uprawnieniami systemowymi, bądź też ustawieniami trybu SAFE_MODE i/lub zmiennej konfiguracyjnej open_basedir w pliku php.ini.

Przy odrobinie szczęścia zabezpieczenia te jednak nie będą nam zbytnio przeszkadzać, ponieważ najczęstszym niedopatrzeniem po stronie administratorów jest brak kontroli nad katalogiem plików tymczasowych /tmp i udostępnienie go, jako domyślnego katalogu tymczasowego wykorzystywanego przez skrypty PHP.

Sposób wykorzystania luki

Niewiele osób pamięta o tym, jak w PHP wygląda proces obsługi takich rzeczy, jak pliki tymczasowe, sesje, upload plików, a tym bardziej obsługa cache’owania plików WSDL w kliencie SOAP. Wszystkie wspomniane przeze mnie mechanizmy w domyślnej konfiguracji korzystają z katalogu plików tymczasowych, zapisując w nim dane, które można samemu wygenerować!

Przekraczamy limity

Oto przykładowy skrypt generujący plik tymczasowy:

<?php
session_start();
$_SESSION['test'] = str_repeat("-=", 20000);
echo "Done";

Po odpaleniu tego skryptu, w katalogu tymczasowym pojawia się dodatkowy plik:

[root@hosting tmp]# ls -al
total 43
drwxr-xr-x  2 tester users   104 Mar 24 14:39 .
drwxr-xr-x 23 tester users  2760 Mar 24 14:35 ..
-rw-------  1 tester users 40016 Mar 24 14:40 sess_k6ups5hcepb5beb5bq4j03qcjl2lnssv

Plik ten należy do użytkownika „tester” ale nie jest liczony do limitów pojemności/ilości plików na dysku. Jedynym ograniczeniem w tym przypadku jest limit pamięci w PHP (memory_limit), który nie pozwala nam na zapisanie w zmiennej $_SESSION większej ilości danych, to jednak też można obejść dzieląc dane na wiele mniejszych plików (np. o wielkości 32MB każdy).

Aby dostać się do danych takiego pliku wystarczy posłużyć się identyfikatorem sesji PHP uzyskanym funkcją session_id(). W tym przypadku ID ma wartość k6ups5hcepb5beb5bq4j03qcjl2lnssv (co zresztą można było wywnioskować z nazwy pliku).

Tutaj powstaje pierwsze pytanie: kolejne odpalenie skryptu w przeglądarce zapisuje nowe dane ponownie do tego samego pliku. Co zrobić by zapisać dane do następnego? Wystarczy oczywiście zmienić ID sesji PHP na inny…

Przykład praktyczny luki

Tym razem nie będę przedstawiał gotowego skryptu do wykorzystania, podam jednak wskazówki jak taki program wykonać.

Aplikacja powinna składać się z dwóch składników:

  • Pierwszy składnik odpowiedzialny jest za zapisywanie kilkunastu megabajtowych kawałków danych do sesji oraz ich odczyt zależnie od parametrów zapytania POST poprzez HTTP. Do tego celu można posłużyć się zwykłymi funkcjami session_start() oraz echo()
  • Drugi skrypt operuje na globalnym zestawie danych pobierając je i wysyłając kawałkami przy pomocy pierwszego skrypu (np. po localhoście). Do tego celu przydatny jest biblioteka cURL, lub też zestaw funkcji file_get_contents(), oraz file_put_contents(). W celu ułatwienia sobie operacji na takim zbiorze danych można pokusić się o napisanie własnego wrappera plików

Wady tego rozwiązania

Wady są dwie, po pierwsze katalog tymczasowy może być regularnie czyszczony przez administratora (przykładowo raz na dobę), co wiąże się utratą zgromadzonych tam danych. Przedstawione przeze mnie rozwiązanie może jednak w najbardziej ekstremalnych przypadkach pozwalać na zapis do katalogów, które nie są traktowane jako tymczasowe (w takim razie wystarczyłby nawet zwykły fopen)

Drugim problemem jest oczywiście to, że w końcu ktoś z administracji te pliki może zauważyć.

Jak się zabezpieczyć przed tą luką?

Najlepiej ustawiać w PHP katalog tymczasowy na podkatalog znajdujący się na koncie klienta (np. poprzez odpowiednie wpisy do pliku php.ini), oraz zabrać klientowi możliwość zapisu danych na innych systemach plików.

Tagi: ,

Dodaj odpowiedź