Usando Register Globals
AdvertenciaEsta característica ha sido declarada
OBSOLETA desde PHP 5.3.0 y ELIMINADA
a partir de PHP 5.4.0.
Quizás el cambio más controversial en PHP fue cuando el valor predeterminado
para la directiva de PHP
register_globals pasó de ON a OFF en PHP
» 4.2.0. La dependencia sobre esta
directiva era bastante común y muchas personas ni siquiera sabía que existía
y asumían sólo que ese era el modo como PHP funcionaba. Esta página explicará cómo se puede
escribir código inseguro con esta directiva, pero tenga en cuenta que la
directiva en si misma no es insegura sino el uso inapropiado de ella.
Cuando está activada, register_globals inyectará los scripts con todo
tipo de variables, como las de peticiones provenientes de formularios HTML. Esto,
unido al hecho de que PHP no requiere la inicialización de variables,
significa que es muy fácil escribir código inseguro. Fue una decisión
difícil, pero la comunidad de PHP decidió desactivar esta directiva por
defecto. Cuando está activada, las personas usan variables que en realidad no se sabe a ciencia cierta
de dónde provienen y solo queda asumir. Las variables internas que son
definidas en el script mismo son mezcladas con los datos requeridos enviados por
los usuarios y al deshabilitar register_globals se cambia esto. Vamos a demostrar
con un ejemplo del uso incorrecto de register_globals:
Ejemplo #1 Ejemplo de uso incorrecto con register_globals = on
<?php
// $authorized = true Se define sólo si el usuario está autenticado
if (authenticated_user()) {
$authorized = true;
}
// Debido a que no se inicializa $authorized como false, esta podría ser
// definida a través de register_globals, como desde GET auth.php?authorized=1
// ¡Por lo tanto, cualquier persona puede verse como autenticada!
if ($authorized) {
include "/highly/sensitive/data.php";
}
?>
Cuando está register_globals = on, la lógica anterior podría verse comprometida. Cuando
está deshabilitada, $authorized no puede definirse a través de peticiones, así que
estará bien, aunque realmente en general es una buena práctica de programación
inicializar las variables primero. Por ejemplo, en el ejemplo anterior se puede
haber realizado primero algo como $authorized = false. Hacer esto
primero significa que el código anterior podría funcionar con register_globals activado o desactivado ya
que los usuarios de forma predeterminada no serían autorizados.
Otro ejemplo es aquel de las sesiones.
Cuando está register_globals = on, se puede usar también
$username en el siguiente ejemplo, pero nuevamente se debe
notar que $username también puede provenir de otros
medios, tal como GET (a través de la URL).
Ejemplo #2 Ejemplo de uso de sesiones con register_globals on u off
<?php
// No se sabría por dónde proviene $username, pero se sabe que $_SESSION es
// para datos de sesión.
if (isset($_SESSION['username'])) {
echo "Hello <b>{$_SESSION['username']}</b>";
} else {
echo "Hello <b>Guest</b><br />";
echo "Would you like to login?";
}
?>
Incluso es posible tomar medidas preventivas para advertir cuando se
haga un intento de falsificación. Si se sabe previamente con exactitud el lugar de donde una variable
debería provenir, se puede verificar si los datos enviados
provienen de una clase inapropiada de sumisión. Si bien no
garantiza que los datos no han sido falsificados, esto requiere que un atacante
adivine el medio apropiado para falsificar. Si no importa de donde provienen los datos
requeridos, se puede usar $_REQUEST ya que contiene
una mezcla de datos GET, POST y COOKIE. Ver también la sección del manual sobre
el uso de variables desde fuentes externas
sources.
Ejemplo #3 Detección de envenenamiento simple de variables
<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {
// MAGIC_COOKIE viene de una cookie.
// ¡Asegúrese de validar la información de la cookie!
} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {
mail("admin@example.com", "Posible intento de ataque", $_SERVER['REMOTE_ADDR']);
echo "Violación de seguridad, el administrador ha sido alertado.";
exit;
} else {
// MAGIC_COOKIE no se establece a través de este REQUEST
}
?>
Por supuesto, simplemente deshabilitar register_globals no quiere decir que su código
es seguro. Cada pieza de datos que es remitida, también debe ser
verificada de otras formas. ¡Siempre valide los datos de los usuarios e inicialice
sus variables! Para chequear por variables no inicializadas, se puede usar
error_reporting() para mostrar
errores de nivel E_NOTICE
.
Para obtener información sobre la emulación de register_globals activado o desactivado, consulte este FAQ.