PHP - register_globals


Návody pro C4


Register globals je konfigurační direktiva PHP, může nabývat dvou hodnot - buď zapnuto nebo vypnuto. Pokud je register_globals zapnuté, znamená to, že k proměnným z odeslaných formulářů, k proměnným v URL a jiným podobným proměnným (např. z cookies) je možné přistupovat přímo přes název proměnné, např. přes $heslo. Když je register_globals vypnuté, tak je možné přistupovat jen přes superglobální pole, např. přes $_POST["heslo"], $_GET["heslo"], $_COOKIES["heslo"] nebo $_SERVER["heslo"] (pokud je zapnutá direktiva register_long_arrays, tak lze k proměnným přistupovat ještě jedním alternativním způsobem, ten je ale zastaralý).

Příklad s proměnnou v URL

Např. na webu www.c4.cz bude umístěn skript test.php. Do internetového prohlížeče zadáte adresu (URL):

http://www.c4.cz/test.php?vstup=sport

Obsah skriptu test.php může být následující:

<?php

// vypise Test1, pokud register_globals = On (zapnuto)
if($vstup == "sport") echo "Test1<br />;\n";

// vypise Test2 nezavisle na nastaveni register_globals
// pristupuje k promenne pres superglobalni pole $_GET
if($_GET["vstup"] == "sport") echo "Test2<br />;\n";

?>

Příklad s proměnnou z formuláře

Dalším typickým příkladem, kdy se projevuje nastavení register globals, je zpracování údajů z odeslaného formuláře. Nechť je součástí internetové stránky jednoduchý formulář na vyplnění jednoho textového pole:

<form method="post" action="/test.php">
<p>
Text: <input type="text" name="textove_pole" value="" /><br />
<input type="submit" value="Odeslat" />
</p>
</form>

Po odeslání webového formuláře dojde ke zpracování skriptem test.php, který může vypadat takto:

<?php

// vypise obsah promenne, pokud register_globals = On (zapnuto)
echo "Obsah: $textove_pole<br />\n";

// vypise obsah promenne nezavisle na nastaveni register_globals
// pristupuje k promenne pres superglobalni pole $_POST
echo "Obsah: $_POST[textove_pole]<br />\n";

?>

Register globals mějte vypnuté

Vypnuté register globals (tedy že proměnné budou dostupné jen přes superglobální pole $_GET, $_POST, ..) je lepší variatna z následujících důvodů:

  1. Je to bezpečnější. Weby se zapnutým register_globals jsou snázeji zneužitelné (důvody jsou uvedeny níže).
  2. V PHP 6 bude register_globals vypnuté a nebude možné ho zapnout. Když budete vytvářet skripty, které budou spoléhat na zapnuté register_globals, takové skripty určitě nepoběží na PHP 6.

Na PHP 5 serverech je register_globals vypnuté (lze na požádání přenastavit, což ale z výše uvedených důvodů nedoporučujeme). Aktuální nastavení lze jednoduše zjistit pomocí funkce ini_get().

Proč je nebezpečné mít register_globals zapnuté?

Zajisté si kladete otázku, proč je to tak nebezpečné mít zapnuté register globals. Zapnuté register_globals totiž umožňují útočníkovi přidat novou globální proměnnou s libovolnou hodnotou a pokud skript korektně neinicializuje proměnné, tak tím může ovlivnit běh skriptu. Podívejme se na jednoduchý příklad. Řekněme, že HTML kód přihlašovacího formuláře do administrační sekce vašeho webu vypadá následovně:

<form method="post" action="http://www.c4.cz/admin.php">
<p>
Jmeno: <input type="text" name="jmeno" value="" /><br />
Heslo: <input type="password" name="heslo" value="" /><br />
<input type="submit" value="Odeslat" />
</p>
</form>

PHP skript admin.php má tento obsah:

<?php

if($jmeno == "admin" && $heslo == "d83jFsTsz2") {
    $vstup_povolen = 1;
}

if(!$vstup_povolen) {
    echo "Bylo zadano chybne heslo. Vratte se zpet.\n";
    exit;
}

?>

<h1>Administracni sekce</h1>

... 

Jedná se o začátek PHP skriptu, který zpracovává hodnoty přihlašovacího formuláře. Skript spoléhá na zapnuté register_globals a zároveň není korektně inicializovaná proměnná $vstup_povolen. Útočníkovi nyní stačí, aby do internetového prohlížeče zadal adresu:

http://www.c4.cz/admin.php?vstup_povolen=1

A získá tak přístup do administrační sekce vašeho webu, aniž by znal správné přihlašovací jméno a heslo.

Problém by šlo vyřešit snadno, stačilo by do skriptu admin.php na začátek přidat:

<?php

$vstup_povolen = 0;

...

Můžete namítnout, že vám se nic takového nemůže stát, že si při psaní php skriptů dáváte pozor a proměnné vždy korektně inicializujete. U větších projektů jako je např. Joomla, které se skládají z velmi mnoha php skriptů, které jsou navíc různě inkludovány do sebe, je téměř nemožné zamezit všem chybám ohledně nedostatečné inicializace proměnných a proto je důležité, aby register_globals byly vypnuté a nehrozilo zneužití. Uvědomte si, že stačí jedna taková drobná chybka (zapomente inicializovat proměnnou) a následky zneužití mohou být velmi závažné, např. útočník může získat přístup do chráněné sekce webu, může dojít k zneužití skriptu k rozesílání spamu, útočník může získat hesla k databázím nebo může zcela ovládnout web a např. upravovat stávající skripty a nebo si nainstalovat svoje.

Jak předělat skripty, aby fungovaly pro vypnuté register globals?

Pokud máte skripty, které jsou vytvořené pro zapnuté register_globals, lze je poměrně jednoduše předělat, aby fungovaly s vypnutými register globals. Vezměme jako příklad výše uvedený skript admin.php, který zpracovává údaje (jméno a heslo) z přihlašovacího formuláře. V tomto skriptu jsou proměnné $jmeno a $heslo, které díky zapnutým register_globals obsahují data z formuláře. Stačí na začátek skriptu dát následující řádky:

<?php

$jmeno = $_POST["jmeno"];
$heslo = $_POST["heslo"];

...

Tím dosáhnete toho, že proměnné $jmeno a $heslo budou obsahovat data zadaná do formuláře i po vypnutí register_globals. Obecný postup je tedy takový, že všem proměnným, které spoléhají na inicializaci pomocí register globals, na začátku skriptu přiřadíte obsah ze superglobálních polí. Nejčastěji používaná superglobální pole jsou:

Související odkazy

Diskuzní fórum pro článek PHP - register_globals

Nové diskuzní téma můžete založit v sekci PHP, MySQL.

Změny a kontroly

K dispozici je kompletní přehled všech změn a kontrol v tomto návodu.


Diskuzní fórum
  • Webové aplikace
  • Tvorba web stránek
  • PHP, MySQL

forum.c4.cz