Jak zabezpieczyć skrypt przed register_globals

Tags:

Co zrobić w przypadku gdy serwer ma włączone register_globals, i nie umożliwia zmiany tego ustawienia - jak wyłączyć tą funkcję?

Poniżej prosty sposób, który pozwala na zabezpieczenie naszego skryptu przed skutkami włączonego register_globals. Poniższą funkcję należy zdeklarować na początku skryptu, następnie zamiast


należy użyć nowo zdeklarowanej funkcji
  1. safe_session_start();

A oto i kod naszej funkcji:

  1. function safe_session_start() {
  2.   if (ini_get('register_globals') == 1){
  3.     // zabezpieczam zdefiniowane wcześniej zmienne globalne
  4.     $local_globals = array();
  5.     $super_globals = array(
  6.       'GLOBALS',
  7.       '_SERVER',
  8.       '_GET',
  9.       '_POST',
  10.       '_FILES',
  11.       '_COOKIE',
  12.       '_SESSION',
  13.       '_REQUEST',
  14.       '_ENV',
  15.     );
  16.     foreach ($GLOBALS as $varname => $varvalue) {
  17.       // zachowuję wszystkie oprócz superglobals
  18.       // z superglobals PHP sobie radzi poprawnie ponieważ nie nadpisuje ich przy włączonym register_globals
  19.       if (!in_array($varname, $super_globals) $local_globals[$varname] = $varvalue;
  20.     }
  21.    
  22.     $return = session_start();
  23.    
  24.     // z tych zmiennych register_globals korzysta
  25.     $register_global_vars = array (
  26.       '_SERVER',
  27.       '_COOKIE',
  28.       '_REQUEST', // zawiera łącznie _GET i _POST
  29.       '_ENV',
  30.     );
  31.    
  32.     // kasuję wszystkie globalne zmienne, oprócz superglobals
  33.     // i zastępuję je dotychczasowymi zmiennymi globalnymi
  34.     foreach ($register_global_vars as $remove_me) {
  35.      
  36.       if (is_array($$remove_me)) foreach(array_keys($$remove_me) as $varname) {
  37.         if (!in_array($varname, $super_globals) {
  38.           if (isset($local_globals[$varname])) {
  39.             $GLOBALS[$varname] = $local_globals[$varname];
  40.           } else unset($GLOBALS[$varname]);
  41.          
  42.         }
  43.       }
  44.     }
  45.   } else {
  46.     $return = session_start();
  47.   }
  48.   return $return;
  49. }

Jak to działa?

Nie wystarczy zwykłe unset() wszystkich zmiennych globalnych które są podane w $_SERVER, $_REQUEST etc, jak to podają użytkownicy w komentarzach na php.net. W ten sposób możemy skasować zdefiniowane przez nas wcześniej w skrypcie zmienne globalne.

Powyższa funkcja zachowuje ich zawartość, omija także zmienne superglobalne, których PHP nie podmienia nawet jeśli są podane w np. GET lub POST.

Zalety: szybki i prosty sposób, i nie martwimy się jeśli session_start jest gdzieś w środku kodu czy w inkludowanym pliku, po zdeklarowaniu ważnych dla skryptu zmiennych globalnych.

UWAGA: należy pamiętać o zmianie we wszystkich plikach .php wywoływanych bezpośrednio przez żądanie przeglądarki (nie includowanych). Np. jeśli mamy osobny plik

  1. admin.php

i jest on wywoływany bezpośrednio a nie włączany do index.php, to również w admin.php musimy zadbać by funkcja safe_session_start(); została zdeklarowana i użyta w zamiast session_start();.

Kod nie został przetestowany, jest to jedynie przykład teoretyczny.