Top 10 vulnerabilidades de aplicaciones PHP: cómo proteger tu código
PHP sigue siendo uno de los lenguajes más populares para el desarrollo web. Sin embargo, su flexibilidad y simplicidad a menudo conducen a la aparición de vulnerabilidades críticas. Según las estadísticas de OWASP, más del 70% de las aplicaciones web tienen al menos una brecha de seguridad grave. En este artículo analizaremos las 10 vulnerabilidades más comunes en aplicaciones PHP, mostraremos ejemplos de código peligroso y daremos recomendaciones prácticas para la protección.
1. Inyección SQL (SQL Injection)
El ataque más conocido y peligroso. El atacante inyecta código SQL a través de la entrada del usuario.
Código peligroso:
<?php$id = $_GET['id'];$query = "SELECT * FROM users WHERE id = $id";$result = mysqli_query($conn, $query);?>Código seguro (usando consultas preparadas):
<?php$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");$stmt->bind_param("i", $_GET['id']);$stmt->execute();$result = $stmt->get_result();?>Recomendaciones:
- Utilice siempre expresiones preparadas (PDO o MySQLi).
- Nunca concatene datos del usuario en consultas SQL.
- Valide los tipos de datos (por ejemplo,
is_numeric()para ID).
2. XSS (Cross-Site Scripting)
Inyección de código JavaScript en la página a través de datos no validados. Robo de cookies, redirección a sitios de phishing.
Código peligroso:
<?phpecho "Hola, " . $_GET['name'];?>Código seguro:
<?phpecho "Hola, " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');?>Recomendaciones:
- Escape la salida con
htmlspecialchars(). - Configure Content-Security-Policy (CSP) en los encabezados.
- Para respuestas JSON, use
json_encode().
3. CSRF (Cross-Site Request Forgery)
El atacante obliga a un usuario autenticado a realizar una acción no deseada (por ejemplo, transferir dinero).
Ejemplo de formulario sin protección:
<form action="delete.php" method="POST"> <input type="hidden" name="id" value="123"> <input type="submit" value="Eliminar"></form>Código seguro (con token):
<?phpsession_start();if (empty($_SESSION['token'])) { $_SESSION['token'] = bin2hex(random_bytes(32));}?><form action="delete.php" method="POST"> <input type="hidden" name="token" value="<?= $_SESSION['token'] ?>"> <input type="hidden" name="id" value="123"> <input type="submit" value="Eliminar"></form>Recomendaciones:
- Genere tokens CSRF únicos para cada formulario.
- Verifique los tokens en el servidor antes de ejecutar acciones.
- Use SameSite Cookie (Lax o Strict).
4. Autenticación incorrecta y gestión de sesiones
Protección débil de sesiones, fuga de identificadores, fijación de sesión.
Código vulnerable:
<?phpsession_start();if ($_POST['password'] == 'admin123') { $_SESSION['logged'] = true;}?>Código seguro:
<?phpsession_start();session_regenerate_id(true); // Cambiar ID de sesión después del inicio de sesión
// Hash de contraseña$hash = password_hash($_POST['password'], PASSWORD_BCRYPT);if (password_verify($input_password, $hash)) { $_SESSION['logged'] = true; $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];}?>Recomendaciones:
- Use
password_hash()ypas