PHP Australia Conference 2015

register_globals Kullanımı

Uyarı

Bu özelliğin kullanımı PHP 5.3.0'dan beri ÖNERİLMEMEKTEDİR ve PHP 6.0.0'da tamamen KALDIRILMIŞTIR. Bu özelliğe kesinlikle güvenmemelisiniz.

PHP'deki belki de en tartışmalı değişiklik, register_globals PHP yönergesinin öntanımlı değerinin PHP » 4.2.0'da On iken Off yapılmasıdır. Bu yönerge üzerindeki geçmiş deneyimlere dayanmak oldukça yaygındı ve çoğu kişi yönergenin varlığını bile bilmediği gibi PHP'nin böyle çalıştığını varsayardı. Bu sayfada, bu yönerge ile yazılan kodun nasıl güvensiz olabileceği gösterilecek, fakat güvensizliğin yönergenin kendisinden ziyade nasıl yanlış kullanımından kaynaklandığı açıklanacaktır.

register_globals On iken, HTML formlarındaki istek değişkenleri gibi bir takım değişkenler betiğinize dahil edilir. PHP'nin değişken ilklendirme gerektirmeme olgusu güvensiz kod yazımını daha da kolaylaştırır. Zor bir karar olmasına rağmen PHP topluluğu bu yönergeyi öntanımlı olarak iptal etmeyi uygun gördü. Yönergenin değeri On iken, kullanıcılar, değişkenleri, aslında ne olup bittiğini bilmeden sadece varsayımla kullanırdı. Betiğin kendisi tarafından tanımlanmış dahili değişkenler kullanıcı tarafından gönderilen istek verileri ile karışırdı. register_globals Off yapılınca bu değişti. Yönergenin yanlış kullanımını bir örnekle açıklamaya çalışalım:

Örnek 1 - register_globals = on ile yanlış kullanım örneği

<?php
// Sadece kullanıcı kimliği doğrulanıyorsa $yetkili = true olmalı
if (authenticated_user()) {
    
$yetkili true;
}

// $yetkili değişkenini başta false ile ilklendirmediğimizden
// bu atama GET auth.php?yetkili=1 şeklinde register_globals
// üzerinden yapılmış olabilir. Dolayısıyla, kullanıcı kendini
// yetkiliymiş gibi gösterebilir!
if ($yetkili) {
    include 
"/gayet/hassas/veriler.php";
}
?>

register_globals = on iken yukarıda yürüttüğümüz mantık zarar görebilir. register_globals = off olduğunda, $yetkili değişkenine istek üzerinden değer atanamayacağından bir açık söz konunu olmayacaktır. Aslında değişkenleri baştan ilklendirmek iyi bir programcılık alışkanlığıdır. Yukarıdaki örnekte baştan $yetkili = false yapabilirdik. Bu ilklendirme yapılmış olsaydı, kullanıcı öntanımlı olarak yetkisiz olacağından register_globals yönergesinin değerinin ne olduğunun bir önemi olmayacaktı.

Diğer bir örnek oturumlarla ilgilidir. register_globals = on iken, aşağıdaki örnekte $kullanici değişkenini de kullanabilirdik, fakat tekrar hatırlatmakta yarar var: $kullanici, GET gibi başka bir kaynaktan da (örn, URL üzerinden) gelebilirdi.

Örnek 2 - register_globals On veya Off iken oturum örneği

<?php
// $kullanici'nin nereden geleceğini bilemezdik
// Fakat oturum verisi için $_SESSION kullanınca biliriz
if (isset($_SESSION['kullanici'])) {

    echo 
"Merhaba <b>{$_SESSION['kullanici']}</b>";

} else {

    echo 
"Merhaba <b>Ziyaretçi</b><br />";
    echo 
"Oturum açmak ister misiniz?";

}
?>

Sahtecilik yapılmaya çalışıldığında uyaracak önleyici tedbirler almak da mümkündür. Bir değişken vaktinden önce geliyorsa, gönderilen verinin ilgisiz bir teslimat çeşidinden gelip gelmediğini sınayabilirsiniz. Verinin sahte olmadığını garanti etmese de saldırganın yaptığı sahtecilik türünün tahmin edilmesi gerekir. İstek verisinin geldiği yeri önemsemiyorsanız, GET, POST ve COOKIE verilerinin bir karışımını içeren $_REQUEST dizisini kullanabilirsiniz. Ayrıca, Dış Kaynaklı Değişkenler bölümüne de bakınız.

Örnek 3 - Basit değişken sahteciliğinin saptanması

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

    
// MAGIC_COOKIE bir çerezden gelir.
    // Çerez verisini doğrulamayı unutmayın!

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

   
mail("admin@example.com""Olası kırma çabası"$_SERVER['REMOTE_ADDR']);
   echo 
"Güvenlik ihlali; yönetici uyarıldı.";
   exit;

} else {

   
// MAGIC_COOKIE bu istek (REQUEST) üzerinden atanmamış.

}
?>

Şüphesiz, tek başına register_globals = off, kodunuzun güvenli olduğu anlamına gelmez. Gönderilen her veri parçası başka yollarla da ayrıca sınanmalıdır. Kullanıcı verinizi daima doğrulayın ve değişkenlerinizi daima ilklendirin! İlklendirilmemiş değişkenleri görmek için error_reporting() işlevi ile E_NOTICE seviyesinden hataların gösterilmesini sağlamalısınız.

register_globals'in On veya Off olmasının taklit edilmesi hakkında bilgi edinmek için SSS'deki register_globals ile nasıl çalışacağım? sorusuna bakınız.

Bilginize: Süper Küreseller Kullanılabilirlik Bilgisi

$_GET, $_POST, $_SERVER, vs. gibi süper küreseller PHP 4.1.0 sürümünden beri kullanılabilmektedir. Bu konuda daha ayrıntılı bilgi edinmek için süper küreseller bölümüne bakınız.

add a note add a note

User Contributed Notes 7 notes

up
28
lester burlap
5 years ago
It would make this whole issue a lot less confusing for less-experienced PHP programmers if you just explained:

- $myVariable no longer works by default
- $_GET['myVariable'] works just fine

I'm embarrassed to say it's taken me six months since my ISP upgraded to PHP5 figure this out.  I've completely rewritten scripts to stop using GET variables altogether.

I'm dumb.
up
5
elitescripts2000 at yahoo dot com
1 year ago
<?php

/* Forces all GET and POST globals to register and be magically quoted.
* This forced register_globals and magic_quotes_gpc both act as if
* they were turned ON even if turned off in your php.ini file.
*
* Reason behind forcing register_globals and magic_quotes is for legacy
* PHP scripts that need to run with PHP 5.4 and higher.  PHP 5.4+ no longer
* support register_globals and magic_quotes, which breaks legacy PHP code.
*
* This is used as a workaround, while you upgrade your PHP code, yet still
* allows you to run in a PHP 5.4+ environment.
*
* Licenced under the GPLv2. Matt Kukowski Sept. 2013
*/

if (! isset($PXM_REG_GLOB)) {

 
$PXM_REG_GLOB = 1;

  if (!
ini_get('register_globals')) {
    foreach (
array_merge($_GET, $_POST) as $key => $val) {
      global $
$key;
      $
$key = (get_magic_quotes_gpc()) ? $val : addslashes($val);
    }
  }
  if (!
get_magic_quotes_gpc()) {
    foreach (
$_POST as $key => $val) $_POST[$key] = addslashes($val);
    foreach (
$_GET as $key => $val$_GET[$key]  = addslashes($val);
  }
}

?>
up
4
claude dot pache at gmail dot com
5 years ago
Beware that all the solutions given in the comments below for emulating register_global being off are bogus, because they can destroy predefined variables you should not unset. For example, suppose that you have

<?php $_GET['_COOKIE'] == 'foo'; ?>

Then the simplistic solutions of the previous comments let you lose all the cookies registered in the superglobal "$_COOKIE"! (Note that in this situation, even with register_global set to "on", PHP is smart enough to not mess predefined variables such as  $_COOKIE.)

A proper solution for emulating register_global being off is given in the FAQ, as stated in the documentation above.
up
2
Ruquay K Calloway
6 years ago
While we all appreciate the many helpful posts to get rid of register_globals, maybe you're one of those who just loves it.  More likely, your boss says you just have to live with it because he thinks it's a great feature.

No problem, just call (below defined):

<?php register_globals(); ?>

anywhere, as often as you want.  Or update your scripts!

<?php
/**
* function to emulate the register_globals setting in PHP
* for all of those diehard fans of possibly harmful PHP settings :-)
* @author Ruquay K Calloway
* @param string $order order in which to register the globals, e.g. 'egpcs' for default
*/
function register_globals($order = 'egpcs')
{
   
// define a subroutine
   
if(!function_exists('register_global_array'))
    {
        function
register_global_array(array $superglobal)
        {
            foreach(
$superglobal as $varname => $value)
            {
                global $
$varname;
                $
$varname = $value;
            }
        }
    }
   
   
$order = explode("\r\n", trim(chunk_split($order, 1)));
    foreach(
$order as $k)
    {
        switch(
strtolower($k))
        {
            case
'e':    register_global_array($_ENV);        break;
            case
'g':    register_global_array($_GET);        break;
            case
'p':    register_global_array($_POST);        break;
            case
'c':    register_global_array($_COOKIE);    break;
            case
's':    register_global_array($_SERVER);    break;
        }
    }
}
?>
up
1
arman_y_92 at yahoo dot com
1 month ago
To all those fans of this insecure functionality (which I'm glad is now turned off by default) , you can just use extract() to achieve a similar goal more securely (unless you overwrite local variables with $_GET or $_POST data).
up
0
moore at hs-furtwangen dot de
6 years ago
I had a look at the post from Dice, in which he suggested the function unregister_globals(). It didn't seem to work - only tested php 4.4.8 and 5.2.1 - so I made some tweaking to get it running. (I had to use $GLOBALS due to the fact that $$name won't work with superglobals).

<?php
//Undo register_globals
function unregister_globals() {
    if (
ini_get('register_globals')) {
       
$array = array('_REQUEST', '_FILES');
        foreach (
$array as $value) {
            if(isset(
$GLOBALS[$value])){
                foreach (
$GLOBALS[$value] as $key => $var) {
                    if (isset(
$GLOBALS[$key]) && $var === $GLOBALS[$key]) {
                       
//echo 'found '.$key.' = '.$var.' in $'.$value."\n";                   
                       
unset($GLOBALS[$key]);
                    }
                }
            }
        }
    }
}
?>

The echo was for debuging, thought it might come in handy.
up
-5
Dice
6 years ago
To expand on the nice bit of code Mike Willbanks wrote and Alexander tidied up, I turned the whole thing in a function that removes all the globals added by register_globals so it can be implemented in an included functions.php and doesn't litter the main pages too much.

<?php
//Undo register_globals
function unregister_globals() {
    if (
ini_get(register_globals)) {
       
$array = array('_REQUEST', '_SESSION', '_SERVER', '_ENV', '_FILES');
        foreach (
$array as $value) {
            foreach (
$GLOBALS[$value] as $key => $var) {
                if (
$var === $GLOBALS[$key]) {
                    unset(
$GLOBALS[$key]);
                }
            }
        }
    }
}
?>
To Top