Inicio > Cursos > PHP > Seguridad Web: XSS y Validación
PHPPOO y PHP ModernoLección 12 de 15

Seguridad Web: XSS y Validación

La seguridad en aplicaciones PHP web no es opcional: es parte fundamental del trabajo. Los dos ataques más comunes son SQL Injection (insertar SQL malicioso en campos del formulario para manipular la base de datos) y XSS o Cross-Site Scripting (insertar JavaScript malicioso que se ejecuta en el navegador de otros usuarios). Ambos explotan el mismo error: confiar en datos del usuario sin validarlos ni escaparlos.

La regla de oro de seguridad PHP: nunca confíes en datos del usuario. Para prevenir SQL Injection: siempre usa prepared statements con PDO, nunca construyas consultas SQL concatenando strings del usuario. Para prevenir XSS: siempre escapa con htmlspecialchars() cuando muestres datos del usuario en HTML.

Para contraseñas: usa password_hash() para guardar y password_verify() para verificar, nunca guardes contraseñas en texto plano. Filtros como filter_var() validan emails, URLs y otros formatos comunes.

<?php
// XSS Prevention - SIEMPRE escapar datos del usuario
$nombre_usuario = "<script>alert('XSS')</script>";
echo htmlspecialchars($nombre_usuario, ENT_QUOTES, "UTF-8");
// Muestra el texto, no ejecuta el script

// Función helper corta
function e(string $str): string {
    return htmlspecialchars($str, ENT_QUOTES, "UTF-8");
}
echo e($_GET["nombre"] ?? "");

// Validación con filter_input
$email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL);
if ($email === false || $email === null) {
    echo "Email inválido";
}

$edad = filter_input(INPUT_POST, "edad", FILTER_VALIDATE_INT, [
    "options" => ["min_range" => 18, "max_range" => 120]
]);

$url = filter_var($_POST["url"] ?? "", FILTER_SANITIZE_URL);

// Hash de contraseñas - NUNCA uses MD5 o SHA1
$password = "mi_contraseña_123";
$hash = password_hash($password, PASSWORD_BCRYPT);

// Verificar contraseña
if (password_verify($password, $hash)) {
    echo "Contraseña correcta";
}

// CSRF Token
session_start();

// Generar token
if (empty($_SESSION["csrf_token"])) {
    $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
}

// En el formulario HTML
echo '<input type="hidden" name="csrf" value="' . e($_SESSION["csrf_token"]) . '">' ;

// Verificar en el servidor
if (!isset($_POST["csrf"]) || $_POST["csrf"] !== $_SESSION["csrf_token"]) {
    http_response_code(403);
    die("Token CSRF inválido");
}

// Validación robusta
function validarPassword(string $pass): array {
    $errores = [];
    if (strlen($pass) < 8) $errores[] = "Mínimo 8 caracteres";
    if (!preg_match("/[A-Z]/", $pass)) $errores[] = "Requiere mayúscula";
    if (!preg_match("/[0-9]/", $pass)) $errores[] = "Requiere número";
    return $errores;
}
Consejo🔐 Las 3 reglas de oro: 1) htmlspecialchars() al mostrar datos del usuario. 2) Prepared Statements para SQL. 3) password_hash() para contraseñas. NUNCA MD5 o SHA1.
← Bases de Datos con PDOProyecto: API REST con PHP →

Practica esta lección

Resuelve los ejercicios del curso de PHP en la app, gratis y con corrección automática.

Empezar a practicar