Bezpieczeństwo w PHP

Utworzenie nawet rozbudowanego serwisu internetowego z wykorzystaniem popularnej platformy PHP/MySQL jest znacznie prostsze niż zapewnienie jego bezpieczeństwa. W pierwszej części artykułu o bezpieczeństwie PHP pokażemy, jak skonfigurować PHP, i omówimy zasady pisania bezpiecznych skryptów.


Utworzenie nawet rozbudowanego serwisu internetowego z wykorzystaniem popularnej platformy PHP/MySQL jest znacznie prostsze niż zapewnienie jego bezpieczeństwa. W pierwszej części artykułu o bezpieczeństwie PHP pokażemy, jak skonfigurować PHP, i omówimy zasady pisania bezpiecznych skryptów.

Jedną z pierwszych czynności, które należy wykonać, budując serwis internetowy oparty na PHP i MySQL, jest zdefiniowanie podstawowych funkcji witryny oraz zidentyfikowanie potencjalnych zagrożeń. Oba zagadnienia są ze sobą ściśle związane, ponieważ z rodzaju oferowanych usług natychmiast wynikają przynajmniej podstawowe zagrożenia dla serwisu.

Tworząc np. komercyjne strony WWW, trzeba uwzględnić charakterystyczne dla nich zagrożenia, tj. działalność krakerów, awarie sprzętu komputerowego oraz sieci, błędy w oprogramowaniu, ograniczoną pojemność. Nie należy też zapominać o konkurencji. Możemy mówić o specyficznym "szpiegostwie internetowym". Stosują je firmy, aby śledzić działania konkurencji w swojej branży. Ma to służyć przede wszystkim dostosowywaniu swojej oferty do potrzeb rynku. Nie można jednak wykluczyć złych zamiarów polegających na próbie włamania w celu np. uzyskania haseł dostępu, modyfikacji lub zniszczeniu danych, blokadzie usług, a w konsekwencji uniemożliwieniu sprawnego działania serwisu.

W tym artykule skupimy uwagę na technicznych aspektach zabezpieczenia serwisu internetowego działającego na platformie PHP i wykorzystującego bazę MySQL. Ponieważ siłą rzeczy nie można podać idealnej recepty na całkowite zabezpieczenie witryny, omówimy wybrane ważniejsze zagadnienia.

Bezpieczna konfiguracja PHP

Bezpieczeństwo w PHP

Błędy w aplikacjach PHP są przeważnie spowodowane nie błędami w samym PHP, lecz niedopracowaniem skryptów. Dlatego tak ważne jest przemyślane projektowanie witryny.

Z kolejnych wersji PHP usuwane są błędy, niektóre bardzo niebezpieczne, jak np. zlikwidowana w wersjach 4.3.10 i 5.0.3 luka umożliwiająca nieautoryzowanemu użytkownikowi przejęcie zdalnej kontroli nad serwerem. Również w najnowszej aktualizacji (4.3.11 i 5.0.4) usunięto kilka błędów, z których najważniejszy wydaje się błąd obsługi nagłówków w plikach JPEG, umożliwiający zawieszenie serwera przy użyciu specjalnie przygotowanego obrazka. Dlatego należy zawsze instalować jak najnowsze, stabilnie działające wersje. Najnowsze wersje PHP (4.3.11 i 5.0.4) znajdują się na płycie dołączonej do bieżącego wydania.

Jeżeli nie mamy własnego serwera, tylko korzystamy z hostingu, to aktualizacja oprogramowania jest zadaniem administratorów. Użytkownikom pozostaje wtedy zadbać o jak najlepszą konfigurację PHP, dopasowaną do potrzeb naszej witryny. Przyjrzyjmy się zatem ważniejszym parametrom konfiguracyjnym, ustawianym w plikach php.ini, .htaccess i httpd.conf.

register_globals

Najczęściej konfigurację rozpoczyna się od parametru register_globals. Zaleca się ustawienie tej opcji na Off. W przeciwnym razie wszystkie zmienne wysyłane do skryptu tworzone będą jako globalne, co może spowodować nadpisywanie wcześniej ustalonych wartości zmiennych o takich samych nazwach. Tym samym możliwe staje się na przykład oszukiwanie mechanizmów autoryzacji. Dlatego od wersji 4.2 wartością domyślną tej opcji jest Off, co sprawia, że nie mogą być tworzone żadne dodatkowe zmienne globalne oprócz zdefiniowanych bezpośrednio w skrypcie.

Przy wyłączonej opcji register_globals do przekazywanej zmiennej należy się odwoływać za pomocą specjalnych tablic: $HTTP_POST_VARS['zmienna'] i $HTTP_GET_VARS['zmienna'] lub w skróconej formie: $_POST['zmienna'] i $_GET['zmienna'].

Opcję register_globals można wyłączyć dla całej domeny albo dla wybranych katalogów. W wypadku domeny należy w pliku konfiguracyjnym serwera httpd.conf umieścić następujący wiersz:

php_admin_value register_globals 0

Aby wyłączyć opcję register_globals dla konkretnego katalogu, korzystamy z pliku .htaccess, umieszczając w nim wiersz:

php_flag register_globals 0

Zastosowanie pliku .htaccess stanowi wyjście z trudnej sytuacji, gdy mamy konto na nieswoim serwerze, którego globalny plik konfiguracyjny ustawia parametr register_globals na On.

Aby lepiej zrozumieć problem, jaki stwarza pozostawienie włączonej opcji register_globals, warto przeanalizować poniższy skrypt przyklad.php:

<?php

if ($haslo == 'haslo')

$autoryzacja = 1;

else

echo 'nie jesteś uprawniony';

if ($autoryzacja == 1)

echo 'POUFNA INFORMACJA';

?>

Po ustawieniu opcji register_globals wystarczy wywołać skrypt przyklad.php z parametrem $autoryzacja=1 (wpisując w pole adresu przeglądarki ciąg znaków przyklad.php?autoryzacja=1), aby nie znając hasła, uzyskać poufną informację. Jeżeli z jakichś względów musimy jednak pozostawić tę opcję włączoną, to przynajmniej w powyższym przykładzie konieczne jest dodanie na początku instrukcji zerującej wartość zmiennej $autoryzacja.

safe_mode, disable_functions, safe_mode_exec_dir

Włączenie opcji safe_mode steruje dostępem do plików, udzielając go jedynie właścicielom. Uniemożliwia więc odczyt bądź modyfikację pliku innego właściciela niż autor wykonywanego skryptu. Inaczej mówiąc, wykonywany skrypt ma dostęp do innych plików, ale tylko tego samego właściciela.

Drugą ważną funkcją safe_mode jest ograniczenie możliwości uruchamiania poleceń systemowych z poziomu aplikacji PHP oraz ograniczenie dostępu do zmiennych środowiskowych. Opcji safe_mode nie da się jednak ustawić w pliku .htaccess, tak jak było to możliwe w wypadku register_globals.

Jeżeli chcemy wyłączyć dostęp tylko do wybranych funkcji, możemy użyć opcji disable_functions. W ten sposób zablokujemy np. wykonywanie poleceń systemowych. Postępując zgodnie z zasadą udostępniania tylko tych funkcji, które są potrzebne do działania skryptu, należałoby do pliku konfiguracyjnego dodać następującą instrukcję, w której zablokowane funkcje wymienione są po przecinku:

disable_functions shell_exec, mail, exec, system

Polecenia systemowe są domyślnie wyłączone w trybie safe_mode. Czasami jednak potrzebujemy jednego z poleceń systemowych, ale nie chcemy rezygnować z safe_mode. Rozwiązaniem jest utworzenie specjalnego katalogu poleceń dostępnych w safe_mode, skopiowanie do niego odpowiednich plików oraz dopisanie do php.ini następującego wiersza:

safe_mode_exec_dir=/bin/php

gdzie /bin/php jest przykładową ścieżką do tego katalogu.

open_basedir

Opcja ta ogranicza dostęp do plików. Jako parametr podajemy katalog, powyżej którego nie będzie możliwy dostęp do plików. Tak więc ustawiając w pliku php.ini przykładowo:

open_basedir=/home/user/public_html

blokujemy dostęp m.in. do pliku /home/etc/passwd. Opcję open_basedir można ustawić też w pliku konfiguracyjnym serwera Apache httpd.conf, np:

<Directory /home/user/public_html>

php_admin_value

open_basedir /home/user/public_html

</Directory>

Należy przy tym pamiętać, że wprowadzając zmiany w konfiguracji serwera oraz PHP, często trzeba ponownie uruchomić Apache.


Nie przegap

Zapisz się na newsletter i nie przegap najnowszych artykułów, testów, porad i rankingów: