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):
apache <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";
}
?>
Notas: - Usa constantes para nombres de campos,
mejorando la mantenibilidad. - filter_input()
sanitiza
datos según el tipo (por ejemplo, FILTER_SANITIZE_EMAIL
). -
(string)
asegura que el dato sea tratado como cadena. -
htmlspecialchars()
protege contra ataques XSS.
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: PHP 8.3 elimina riesgos como
register_globals
. - 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.