19 października 2009 ~ 0 Komentarzy

PHP Security #1 Filter Input

PHP

filter-input-escape-output

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;
  }
}

Dodaj komentarz