Jeden odpowiednio wykorzystany przez hakera błąd w naszym skrypcie może pozwolić na odczytanie haseł użytkowników bazy danych czy zniszczenie całej struktury plików na serwerze. Jeśli nie chcemy, aby tak się stało i nasz serwis został zaatakowany po dwóch miesiącach żmudnego programowania, stosujmy się do poniższych rad.
Najbardziej niebezpieczne są funkcje include() oraz require(), gdy są użyte w nieodpowiedni sposób. W skrypcie najczęściej zawarty jest taki oto kod:
| <? include($_GET['podstrona']); ?> |
Teraz wystarczy, że (przy ustawieniu safe_mode na off – zazwyczaj tak właśnie jest) wywołamy adres index.php?file=/etc/passwd i… nazwa plików mówi sama za siebie – na serwerze unikowym wyświetli się plik z hasłami użytkowników. Aby zachować podstawowy poziom bezpieczeństwa, należy zrobić coś takiego:
| <? include(“includes/”.$_GET['nazwa'].”.php”); ?> |
Wtedy rozszerzenie będzie na pewno .php i plik będzie „includowany” z foldera ze skryptem. Nie jest to jednak rozwiązanie najlepsze, więc dobrze jest w takim wypadku korzystać ze switch. Dla przykładu:
| <? switch($_GET['nazwa']) { case “index”: include(“index.php”);break; case “o_mnie”: include(“omnie.php”);break; case “download”: include(“download.php”);break; default: echo “Błąd – taki plik nie istnieje”; } ?> |
W poprzedniej części wspomnieliśmy o trybie safe_mode. Jest to specjalna dyrektywa ustawiana w pliku php.ini (konfiguracja środowiska PHP na serwerze), która określa, czy PHP ma być uruchamiane w trybie bezpiecznym czy nie. Jeśli tylko mamy dostęp do tego pliku, warto ustawić tryb safe_mode na on. Jeśli safe_mode jest włączony, to użytkownik nie ma dostępu do plików, których nie jest właścicielem (tak więc problem tego nieszczęsnego /etc/passwd jest rozwiązany – nikt nie odczyta haseł z serwera). Druga dyrektywa to open_basedir – określa ona folder, powyżej którego w drzewie folderów nie mamy dostępu. Jeżeli więc ustawione jest np. /var/www/users, to skrypt nie będzie miał dostępu np do /var/www. Najlepiej jest mieć te dwie dyrektywy ustawione (włączone), a jeśli nie jest to możliwe, to należy włączyć safe_mode.
Najbardziej zagrożonymi na ataki są te fragmenty skryptów, które operują na danych wprowadzonych przez użytkownika w formularzach lub przekazywanych metodą $_GET. Niezbędnym minimum jest w takim wypadku sprawdzenie, czy typ danych jest zgodny z tym, którego oczekujemy. Jeśli czekamy na liczbę całkowitą, aby wykorzystać ją np. do wygenerowania zapytania do bazy danych, ważne jest, aby była to właśnie liczba, a nie ciąg tekstu, który może nam poważnie namieszać w bazie danych (atak SQL Injection). W tym wypadku należy daną – pobraną z formularza lub przesłaną za pomocą GET – rzutować do oczekiwanego typu zmiennej. Dla przykładu:
<?
$doBazy = (int) $_GET['zFormularza'];
?>