Variables Externas y Superglobales en PHP
En un programa las variables pueden venir de tu propio código o del exterior, a través de formularios o URLs. Aqui aprenderemos de dónde vienen las
variables, cómo manejarlas con superglobales ($_GET
, $_POST
, etc.), y por qué la antigua configuración register_globals
era un riesgo.
¿De dónde vienen las variables?
Las variables en PHP tienen dos orígenes:
- Internas: Definidas por el programador, como
$contador = 0;
. - Externas, proporcionadas por usuarios o el entorno, a través de:
- GET: Cadenas en la URL (por ejemplo,
?nombre=Juan
). - POST: Datos de formularios HTML.
- Cookies: Datos almacenados en el navegador.
- Archivos: Subidas vía formularios (
$_FILES
). - Servidor: Variables de entorno o HTTP (
$_SERVER
). - Sesiones: Datos persistentes entre páginas (
$_SESSION
).
- GET: Cadenas en la URL (por ejemplo,
Las variables externas son útiles, pero pueden ser manipuladas por usuarios, lo que puede ser un riesgo de seguridad si no se manejan correctamente. Un usuario podría intentar “inyectar” valores no deseados, comprometiendo la seguridad.
Ejemplo de riesgo (histórico):
<?php
function authenticateUser(): bool {
// Simula validación de usuario
return false; // Usuario no válido
}
if (authenticateUser()) {
$userOk = true; // Solo debería ser true si el usuario es válido
}
if ($userOk) {
echo "Acceso permitido\n";
} else {
echo "Acceso denegado\n";
}
?>
Con la antigua configuración register_globals on
, un atacante podía añadir ?userOk=1
a la URL, forzando
$userOk = true
y obteniendo acceso no autorizado.
La directiva register_globals
(obsoleta)
En versiones antiguas de PHP (hasta 5.3), la directiva register_globals
en php.ini
controlaba si las
variables externas (GET, POST, Cookies, etc.) se convertían automáticamente en variables globales. Con register_globals on
un valor como ?userOk=1
creaba $userOk = 1
globalmente. Esto mezclaba variables internas y externas, facilitando ataques.
Desde PHP 4.2.0 (2002), se recomendó register_globals off
, y en PHP 5.4 (2012) fue eliminado. En PHP 8.3, todas las variables externas se acceden a través de superglobales, como $_GET['userOk']
, lo que es más seguro porque:
- Separa variables internas de externas.
- Obliga a especificar el origen (GET, POST, etc.).
- Evita inyecciones accidentales.
- Mejora la claridad del código.
Configuración: - No puedes cambiar register_globals
en PHP 8.3 (ya no existe). - En servidores
antiguos, podías usar .htaccess
(si AllowOverride
lo permitía): apache php_flag register_globals off
O en configuraciones VirtualHost
(con permisos administrativos):
<VirtualHost 127.0.0.1>
ServerName localhost
DocumentRoot /var/www/html/misitio
php_value register_globals 0
</VirtualHost>
Ejemplo:
<?php
// URL: http://www.sitio.com/index.php?mail=usuario@ejemplo.com
$mail = $_GET['mail'] ?? ''; // Seguro, accedes explícitamente
echo "Email: $mail\n"; // Imprime: Email: usuario@ejemplo.com
// Con register_globals on, $mail existiría directamente
// pero podría ser manipulada sin control
?>
Superglobales
En PHP 8.3, las variables externas se acceden a través de arrays superglobales:
$_GET
: Datos de la URL (por ejemplo,$_GET['nombre']
).$_POST
: Datos de formularios POST (por ejemplo,$_POST['mail']
).$_COOKIE
: Datos de cookies (por ejemplo,$_COOKIE['sesion']
).$_FILES
: Archivos subidos (por ejemplo,$_FILES['foto']
).$_SESSION
: Datos de sesiones (por ejemplo,$_SESSION['usuario']
).$_SERVER
: Información del servidor (por ejemplo,$_SERVER['PHP_SELF']
).$_ENV
: Variables de entorno.$_REQUEST
: Combina GET, POST, y Cookies (evítalo, es menos seguro).$_GLOBALS
: Todas las variables globales (incluye internas y externas definidas).
Ejemplo:
<?php
// URL: http://www.sitio.com/index.php?op=login
echo $_GET['op'] ?? 'No definido'; // Imprime: login
// Formulario: <input name="mail">
echo $_POST['mail'] ?? 'No enviado'; // Imprime: valor del formulario
// Servidor
echo $_SERVER['PHP_SELF']; // Imprime: /index.php
?>
Advertencia: Evita $_REQUEST
, ya que mezcla orígenes (GET, POST, Cookies), lo que puede causar confusión o
vulnerabilidades.
Procesamiento seguro de variables externas
Siempre valida y sanitiza datos externos usando funciones modernas como filter_input()
y htmlspecialchars()
:
<?php
declare(strict_types=1);
const CAMPO_MAIL = 'mail'; // Constante para nombre del campo
// Sanitiza y valida un email de POST
$mail = filter_input(INPUT_POST, CAMPO_MAIL, FILTER_SANITIZE_EMAIL) ?? '';
$mail = (string)$mail; // Forzar tipo string
if ($mail === '' || !filter_var($mail, FILTER_VALIDATE_EMAIL)) {
echo "Email inválido\n";
} else {
echo "Email válido: " . htmlspecialchars($mail) . "\n";
}
?>
Ejemplo completo
index.php:
<!DOCTYPE html>
<html>
<head>
<title>Procesar Formulario</title>
</head>
<body>
<h1>Enviar Datos</h1>
<form action="index.php" method="post">
<label>Email: <input type="email" name="mail" /></label><br>
<input type="submit" value="Enviar" />
</form>
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$mail = filter_input(INPUT_POST, 'mail', FILTER_SANITIZE_EMAIL) ?? '';
$mail = (string)$mail;
if ($mail === '' || !filter_var($mail, FILTER_VALIDATE_EMAIL)) {
echo "<p style='color: red;'>Por favor, introduce un email válido</p>";
} else {
echo "<p>Email recibido: " . htmlspecialchars($mail) . "</p>";
}
}
?>
</body>
</html>
Explicación: - Procesa un formulario POST de forma
segura. - Valida y sanitiza el email. - Muestra el resultado con
htmlspecialchars()
.
Consejos para seguridad
- Inicializa variables internas: Define
$userOk = false;
al inicio para evitar manipulaciones. - Usa superglobales específicas: Prefiere
$_POST
o$_GET
sobre$_REQUEST
. - Valida y sanitiza: Usa
filter_input()
,filter_var()
, yhtmlspecialchars()
. - Verifica orígenes: Asegúrate de que los datos vienen del método esperado (por ejemplo,
$_SERVER['REQUEST_METHOD'] === 'POST'
). - Protege cookies y archivos: Valida
$_COOKIE
y$_FILES
rigurosamente. - Usa PHP actualizado.
- Errores en producción: Configura
display_errors = Off
para no exponer información sensible. - Actualiza scripts de terceros: Mantén los scripts al día para evitar vulnerabilidades.