Varnost spletnih aplikacij je ena najpomembnejših tem pri razvoju v PHP. Vsak obiskovalec strani lahko pošlje poljubne podatke, zato se moramo zaščititi pred najpogostejšimi napadi. V tem članku si ogledamo osnove: validacijo vnosa, zaščito pred SQL injekcijo in XSS, upravljanje gesel ter varne seje.
$uporabnik = htmlspecialchars($_POST['ime'], ENT_QUOTES, 'UTF-8');
Nikoli ne zaupaj vnosu
Zlato pravilo spletnega razvoja: podatke od uporabnika vedno obravnavaj kot nevaren vnos. To velja za $_GET, $_POST in $_COOKIE. Pred uporabo vedno preverimo, ali je vnos tisto, kar pričakujemo.
// Preverjanje prisotnosti in dolžine
if (isset($_POST['ime']) && mb_strlen($_POST['ime']) <= 50) {
// vnos je sprejemljiv
}
// Pričakujemo e-pošto? Preverimo jo
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if ($email === false) {
// napačen vnos
}
Zaščita pred SQL injekcijo
SQL injekcija je napad, pri katerem napadalec skozi vnos vstavi svoje SQL ukaze. Zaščita je pripravljena izjava (prepared statement) z vezavo parametrov — podatki se nikoli ne združijo z ukazom kot besedilo.
// NAPAKA: vnos je neposredno v ukazu
$ukaz = "SELECT * FROM uporabniki WHERE ime = '" . $_POST['ime'] . "'";
// PRAVILNO: prepared statement
$stmt = $pdo->prepare("SELECT * FROM uporabniki WHERE ime = :ime");
$stmt->execute(['ime' => $_POST['ime']]);
$uporabnik = $stmt->fetch();
Zaščita pred XSS
XSS (Cross-Site Scripting) omogoča napadalcu, da v stran vstavi JavaScript kodo. Do tega pride, ko nepreverjen vnos izpišemo v HTML. Vsak izpis podatkov, ki so prišli od uporabnika, pretvorimo z htmlspecialchars().
// NAPAKA: izpis nepreverjenega vnosa echo $_GET['iskalni_niz']; // PRAVILNO: znaki <, > in " so pretvorjeni v entitete echo htmlspecialchars($_GET['iskalni_niz'], ENT_QUOTES, 'UTF-8');
Shranjevanje gesel
Gesel nikoli ne shranjujemo v čistopisu in jih ne šifriramo, ampak jih izračunamo z enosmerno zgoščevalno funkcijo. PHP ima za to vgrajeno funkcijo password_hash(), ki sama doda naključno sol (salt) in uporabi algoritem bcrypt.
// Registracija: izračunaj zgoščeno vrednost
$zgoscena_vrednost = password_hash($_POST['geslo'], PASSWORD_DEFAULT);
// Prijava: preveri geslo z zgoščeno vrednostjo
if (password_verify($_POST['geslo'], $zgoscena_vrednost)) {
// geslo je pravilno
}
Varne seje
Seje (session) povezujejo prijavo uporabnika med obiski strani. Napadalec lahko poskuša ukrasti identifikator seje, zato nastavimo varnejše piškotke in po prijavi spremenimo ID seje.
session_start();
// Piškotek seje naj ne bo dostopen JavaScriptu in deluje samo preko HTTPS
session_set_cookie_params([
'httponly' => true,
'secure' => true,
'samesite' => 'Strict'
]);
// Po uspešni prijavi spremeni ID seje
session_regenerate_id(true);
To so osnove, s katerimi se izogneš najpogostejšim ranljivostim. Varnost ni enkratno opravilo, ampak navada, ki jo upoštevaš pri vsakem novem delu kode.