Forum und email

Globálisan is elérhető változók (Register Globals) használata

A legvitatottabb változtatás a PHP-ben talán az, amikor register_globals direktíva alapértelmezett értéke ON-ról OFF-ra változott a PHP » 4.2.0-ban. Erre a direktívára való támaszkodás meglehetősen népszerű volt, sokan még azt sem tudták, hogy létezik és azt feltételezték, hogy ez csupán a PHP működésének tudható be. Ez az oldal azt taglalja, hogyan lehet nem biztonságos kódot írni ezzel a direktívával, de tartsd észben azt is, hogy maga a direktíva nem veszélyes, annál inkább az a helytelen használata.

Amikor a register_globals be van állítva, megmérgezi a szkriptjeidet mindenféle változóval, mint például a HTML formokból származókkal. Ehhez hozzájön az, hogy a PHP nem követeli meg a változók inicializálását, így sokkal könnyeb veszélyes kódot írni. Nehéz döntés volt, de a PHP közösség úgy döntött, hogy ez a direktíva alap állapotban ki kell legyen kapcsolva. Amikor bekapcsolt állapotban van, úgy használják a változókat, hogy valójában nem is tudják honnan származik, csak feltételezik. A szkriptben definiált változók összekeverednek a felhasználótól érkezőkkel, de a register_globals kikapcsolása ezt megváltoztatja. Itt egy példa, amely a register_globals helytelen használatát szemlélteti:

Example#1 Helytelen használat register_globals = on esetben

<?php
// $jogosult = true csak akkor ha a felhasználó sikeresen azonosítva van
if (azonositott_felhasznalo()) {
    
$jogosult true;
}

// Mivel nem inicializáltuk az $authorized változót false-ra, előfordulhat,
// hogy definiálva lett a register_globals hatására, mint például
// GET beleptet.php?jogosult=1 
// Így bárki jogosult lehet érzékeny adatok elérésére.
if ($jogosult) {
    include 
"/nagyon/erzekeny/adat.php";
}
?>

Amikor register_globals = on, a fenti logikánkon kicsit javítani kell. Amikor off, a $jogosult változó nem állítható be a felhasználótól érkező adatokból, tehát minden rendben, bár valójában a változók inicializálása rendszerint jó programozási gyakorlat. Például a fenti kódrészletben előbb egy $jogosult = false értékadást kellett volna írnunk. Ha így teszünk, a kódunk működik a register_globals on és off értékével egyaránt, azaz a felhasználók alapból jogosulatlanok lesznek.

Egy másik példa a munkamenetkezeléshez kötődik. Amikor register_globals = on, az alábbi példában használhatnánk egy $usernev változót, de gondolj bele, hogy a $usernev máshonnan is származhat, mint például GET paraméterből (URL-en keresztül).

Example#2 Példa munkamenetek használatára, register_globals on vagy off

<?php
// Nem tudhatjuk, hogy a $usernev honnan származik, de azt igen, hogy
// a $_SESSION a munkamenet adatokat hivatkozza
if (isset($_SESSION['usernev'])) {

    echo 
"Hello, <b>{$_SESSION['usernev']}</b>";

} else {

    echo 
"Hello, <b>Vendég</b><br />";
    echo 
"Szeretnél belépni?";

}
?>

Okosan használva, még azt képes lehet jelezni, ha hamisítást kíséreltek meg. Ha előre tudható, hogy mely változóknak honnan kell érkezniük, akkor azt is megvizsgálhatod, hogy vajon más módon nem próbálták-e elküldeni ezt a változót. Ez nem garantálja, hogy az adatok nem hamisíthatók, azonban megköveteli a támadótól, hogy az rátaláljon a megfelelő hamisítási módszerre. Az is lehetséges, hogy megelőző intézkedéseket tegyünk, hogy figyelmeztetést kapjunk, amikor hamisítást kíséreltek meg. Ha előre tudható, hogy mely változóknak pontosan honnan kell érkezniük, akkor azt is megvizsgálhatod, hogy vajon más módon nem próbálták-e elküldeni ezt a változót. Ez nem garantálja, hogy az adatok nem hamisíthatók, azonban megköveteli a támadótól, hogy az rátaláljon a megfelelő hamisítási módszerre. Ha nem számít, hogy a beküldött adat honnan jön, használhatod a $_REQUEST-et, mivel ez tartalmazza a GET, POST és COOKIE adatok keverékét. Lásd még a kézikönyv PHP-n kívüli változók használatáról szóló részt.

Example#3 Egyszerű "változómérgezés" feltárása

<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {

    
// A MAGIC_COOKIE cookie-ból érkezik.
    // Ne felejtsd el ellenőrizni a cookie adatot!

} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {

   
mail("[email protected]""Lehetseges betoresi probalkozas"
$_SERVER['REMOTE_ADDR']);
   echo 
"Betörési próbálkozás. Adminisztrátor értesítve.";
   exit;

} else {

   
// A MAGIC_COOKIE nincs beállítva ebben a kérésben

}
?>

A register_globals kikapcsolása természetesen nem jelenti azt, hogy a kódod biztonságos. Minden beérkező adatot valamilyen egyéb módon is ellenőrizni kell. Mindig ellenőrizd a felhasználótól érkező adatokat és inicializáld a változóidat! Az inicializálatlan változók felfedezéséhez bekapcsolhatod az error_reporting()-ot hogy kiírja az E_NOTICE szintű hibákat.

A FAQ-ban olvashatsz arról, hogyan lehet emulálni a register_globals On vagy Off értékét.

Note: A szuperglobális változók használhatóságaA 4.1.0 változattól kezdődően bevezetésre kerültek olyan szuperglobális hatókörű tömbök, mint a $_GET, $_POST, $_SERVER, stb. További infórmációk a superglobals oldalon olvashatók.