Quizás el cambio más controversial en la historia de
PHP se ha dado cuando la directiva register_globals pasó
de tener como valor por defecto ON al valor OFF en PHP 4.2.0. La dependencia sobre
esta directiva era bastante común y muchas personas
nisiquiera estaban enteradas de que existía y
asumían que ese era el modo en que PHP trabajaba. Esta
página explicará cómo puede llegar a
escribirse código inseguro con esta directiva pero tenga en
mente que no es la directiva misma la que es insegura sino el uso
inapropiado de ella.
Cuando se encuentra activa, la directiva register_globals
inyectará (o envenenará) sus scripts con todo tipo
de variables, como variables de peticiones provenientes de
formularios HTML. Esto junto con el 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ó desahibilar esta directiva por defecto. Cuando
está habilitada, las personas usan variables sin saber con
seguridad de dónde provienen y solo queda asumir. Las
variables internas que son definidas en el script mismo son
mezcladas con los datos enviados por los usuarios y al
deshabilitar register_globals se modifica este
comportamiento. Demostremos este caso con un ejemplo del uso
incorrecto de register_globals:
Ejemplo 16-14. Ejemplo del uso inapropiado de register_globals =
on
<?php // definir $autorizado = true solo si el usuario ha sido autenticado
if (usuario_autenticado()) { $autorizado = true; }
// Ya que no inicializamos $autorizado como false, esta podria estar // definida a traves de register_globals, como en el caso de GET // auth.php?autorizado=1
// De modo que cualquier persona podria verse como autenticada!
if ($autorizado) { include "/datos/muy/importantes.php"; } ?>
|
|
Cuando register_globals = on, nuestra lógica anterior
podría verse comprometida. Cuando la directiva está
deshabilitada, $autorizado no puede definirse a
través de peticiones, así que no habrá
ningún problema, aunque es cierto que siempre es una buena
práctica de programación inicializar las variables
primero. Por ejemplo, en nuestro ejemplo anterior pudimos haber
realizado primero algo como $authorized =
false. Hacer esto representa que el código
anterior podría funcionar con register_globals establecido
a on u off ya que los usuarios no serían autorizados por
defecto.
Otro ejemplo es aquel de las sesiones. Cuando register_globals =
on, podríamos usar
también $nombre_usuario en nuestro
siguiente ejemplo, pero nuevamente usted debe notar que
$nombre_usuario puede provenir de otros medios,
como GET (a través de la URL).
Ejemplo 16-15. Ejemplo del uso de sesiones con register_globals on u
off
<?php // No sabriamos de donde proviene $nombre_usuario, pero sabemos que // $_SESSION es para datos de sesion
if (isset($_SESSION['nombre_usuario'])) { echo "Hola <b>{$_SESSION['nombre_usuario']}</b>";
} else { echo "Hola <b>Invitado</b><br />"; echo "¿Quisiera iniciar su sesión?";
} ?>
|
|
Incluso es posible tomar medidas preventivas para advertir cuando
se intente falsificar la información. Si usted sabe
previamente con exactitud el lugar de donde debería
provenir una variable, usted puede chequear si los datos enviados
provienen de una fuente inadecuada. Aunque esto no garantiza que
la información no haya sido falsificada, esto requiere que
un atacante adivine el medio apropiado para falsificar la
información. Si no le importa de dónde proviene la
información, puede usar $_REQUEST ya que
allí se incluye una mezcla de variables que provienen de
datos GET, POST y COOKIE. Consulte también la
sección del manual sobre el uso de variables desde fuera de
PHP.
Ejemplo 16-16. Detección de envenenamiento simple de
variables
<?php if (isset($_COOKIE['COOKIE_MAGICA'])) { // COOKIE_MAGICA proviene de una cookie. // Asegurese de validar los datos de la cookie!
} elseif (isset($_GET['COOKIE_MAGICA']) || isset($_POST['COOKIE_MAGICA'])) { mail("admin@ejemplo.com", "Posible intento de intromision", $_SERVER['REMOTE_ADDR']); echo "Violación de seguridad, el administrador ha sido alertado."; exit;
} else { // COOKIE_MAGICA no fue definida en este REQUEST
} ?>
|
|
Por supuesto, deshabilitar register_globals no quiere decir que su
código vaya a ser seguro. Por cada trozo de datos que sea
enviado por el usuario, éste debe ser chequeado en otras
formas. ¡Siempre valide los datos de los usuarios e
inicialice sus variables! Para chequear por variables no
inicializadas, usted puede usar
error_reporting() para mostrar errores del
nivel
E_NOTICE.
Superglobals: Nota de
disponibilidad: Desde 4.1.0, están disponibles
algunas matrices superglobales tales como $_GET,
$_POST, y $_SERVER, etc. Para
más información puede consultar la sección
superglobals