PHP Security #1 Filter Input

Bezpieczeństwo powinno zawsze być tematem numer jeden gdy dysputujemy o dobrym kodzie. Niestety starsze wersje PHP miały skłaniały do pisania słabego kodu pod względem bezpieczeństwa. Ta seria postów będzie poświęcona bezpieczeństwu aplikacji pisanych w PHP 5.x. Zacznę od podstaw czyli zasady: Filter Input, Escape Output.
Wszystkie dane pochodzące z zewnątrz powinny być uznawane za niebezpieczne. Chodzi tutaj tylko o dane pochodzące z formularzy, czyli z zapytań HTTP metodą POST czy GET, ale także dane z baz danych czy API powinny być traktowane jako groźne dla aplikacji. Dane tego typu należy filtrować.
Z drugiej strony dane które mają zostać wyświetlone użytkownikowi najpierw powinny być przekazane do funkcji escapującej. Oto kod który nie spełnia tych zaleceń:
<?php $id = $_GET['id']; $include_dir = 'inc/'; include($include_dir . $id . '.php');
Kod pochodzi z czasów PHP 3, gdy relacyjne bazy danych nie były szeroko dostępne. Informacje przechowywano w plikach tekstowych i w zależności od potrzeby je dodawano do wyniku aplikacji. URL do strony mógł wyglądać następująco:
domain.com/index.php?id=1
Niestety kod ten jest niezabezpieczony. Źli użytkownicy mogą zamiast powyższego adresu wpisać w przeglądarkę następujący.
domain.com/index.php?id=../../../etc/passwd
Teraz użytkownik ma dostęp do haseł na serwerze, bardzo niedobrze :(
By naprawić ten błąd można sprawdzić czy zmienna id jest typu liczbowego.
$id = $_GET['id'];
$include_dir = 'inc/';
if(is_int($id))
{
include($include_dir . $id . '.php');
}
Oczywiście lepszym rozwiązaniem jest wykorzystanie instrukcji sterującej switch:
$id = $_GET['id'];
$include_dir = 'inc/';
if(is_int($id))
{
switch($id)
{
case 0:
include 'inc/about.php';
break;
case 1:
include 'inc/contact.php';
break;
default:
include 'inc/home.php';
break;
}
}
