Z artykułu tego dowiesz się jak zwracać uwagę na bezpieczeństwo w aplikacjach PHP.
Dane od użytkownika
Najważniejszą zasadą jest walidacja wszystkiego,
co pochodzi od użytkownika. Niedopuszczalne jest
zapisywanie w bazie (lub pliku) danych bez ich
sprawdzenia. Gdy użytkownik wprowadza dane –
na przykład w formularzu rejestracyjnym – należy
sprawdzić, co wprowadza. Na przykład imię i nazwisko
może zawierać jedynie litery, a ich maksymalną
długość możemy ustalić na 30 znaków. Oto
kod sprawdzający poprawności imienia i nazwiska.
Formularz do wprowadzania danych:
Kod sprawdzający poprawność:
function sprawdz($dana) {
if (eregi(\'^[a-ząćęłńóśżźĄĆĘŁŃÓŚŻŹ\\']+$\', $dana) && strlen($dana) <= 30) {
return true;
} else {
return false;
}
}
if (isset($_POST[\'imie\']) && isset($_POST[\'nazwisko\'])) {
if (sprawdz($_POST[\'imie\']) && sprawdz($_POST[\'nazwisko\'])) {
header(\'Location: index.php? wynik=1\');
exit;
} else {
header(\'Location: index.php? wynik=2\');
exit;
}
}
Za sprawdzanie poprawności imienia i nazwiska
odpowiada funkcja {stala}sprawdz{/stala}. Wykorzystuje
ona funkcję {stala}eregi{/stala}, która opiera się na wyrażeniach
regularnych. Jej zapis:
eregi (\'^[a-ząćęłńóśżźĄĆĘŁŃÓŚŻŹ \\']+$\', $dana)
oznacza sprawdzanie czy zmienna $dana jest
zgodna z podanym wzorcem. Tutaj wzorzec
sprawdza czy znaki w zmiennej są z zakresu a-z
(oraz A-Z - eregi nie zwraca uwagi na wielkość
znaków), po czym dodatkowo wymienione są
polskie litery ze znakami diakrytycznymi (niestety
eregi nie rozpoznaje ich jako litery, musimy więc
wymienić je ręcznie).
Pozwalamy także użyć w imieniu i nazwisku znaku spacji oraz apostrofu
(\'), tak aby osoby o obco brzmiących nazwiskach
mogły je bez problemu wprowadzić. Po sprawdzeniu
czy znaki w danej zmiennej są poprawne,
funkcja {stala}sprawdz{/stala} analizuje długość napisu. Gdy
oba testy przebiegną pomyślnie, zwraca logiczną
wartość true, w przeciwnym razie false.
To tylko przykład walidacji. Wiek można skonwertować
do liczby za pomocą funkcji {stala}intval{/stala}
(którą już poznaliśmy). Jeśli użytkownik wprowadza
jakąś cyfrę zmiennoprzecinkową, może się
okazać, że będzie ją wprowadzał w postaci 1,5
lub 1.5. Dla PHP poprawna jest tylko ta druga
postać. Dlatego skuteczną konwersją takiej wartości
jest użycie następującej konstrukcji:
$flt = floatval (str_replace(\',\', \'.\', $od_uzytkownika));
Czyli najpierw zamieniamy przecinek na kropkę,
a następnie konwertujemy napis do zmiennej
zmiennoprzecinkowej.
Pamiętajmy, że dane pochodzące od użytkownika
to nie tylko dane z formularza. Jeśli w pasku adresu przekazujemy np. identyfikator, musimy
zawsze sprawdzać jego poprawność, a jeśli jest
on cyfrą, wymuszać jego konwersję do cyfry za
pomocą funkcji {stala}intval{/stala}.
include i require
Często popełnianym błędem jest wykonywanie
instrukcji {stala}include{/stala} lub {stala}require{/stala} (oraz {stala}include_once{/stala}
i {stala}require_once{/stala}), przekazując do nich dane od
użytkownika bez wcześniejszego ich sprawdzenia.
Jest to tym bardziej niebezpieczne, jeśli
udostępniamy użytkownikowi formularz pozwalający
na umieszczanie plików na serwerze. Jeśli
musimy użyć w instrukcji {stala}require{/stala} danych od
użytkownika, zawsze sprawdzajmy co dołączamy
do skryptu. Np. jeśli chcemy użyć konstrukcji
podobnej do tej:
include(\'moduły/\' . $_GET[\'id\'] . \'/index.php);
musimy sprawdzić dokładnie id, a najlepiej wymusić,
aby była to zmienna z dozwolonego zakresu.
Można to zrobić tak:
$strModule = \'main\';
if (isset($_GET[\'id\']) {
switch ($_GET[\'id]\') {
case 2:
$strModule = \'news\';
break;
case 3:
$strModule = \'art\';
break;
case 1:
default:
$strModule = \'main\';
break;
}
}
include(\'moduły/\' . $strModule . \'/index.php);
Dzięki temu cyfra pochodząca od użytkownika
zamieniana jest na napis, dodatkowo mamy kontrolę
zakresu - wszystko, co nie zostało wymienione
w switch, zamieniane jest na main.
Oczywiście można to robić inaczej i przechowywać
odpowiednią konfigurację w tabeli, pliku
XML, bazie danych czy w jakikolwiek inny sposób
(przykład wyżej jest jednym z najprostszych
sposobów zabezpieczenia się). Wszystko jednak
opiera się na zasadzie minimum zaufania do
użytkownika.
PHP to raczej prosty język programowania
i można się go szybko nauczyć. Sama znajomość
języka to jednak nie wszystko. Aby dobrze się
nim posługiwać, trzeba znać jego bibliotekę
standardową (poznaliśmy niektóre z jej elementów),
a także popularne biblioteki dodatkowe.
Proponuję zainteresować się również algorytmami
i wzorcami projektowymi oraz zapoznać się
dokładniej z językiem SQL.