D DIGITOMENORES
DIGITO Systems · Tecnología con alma
11 módulos · 62 lecciones
Inicio / Módulo 09
MÓDULO 09 · Proteger lo que se construye

Seguridad Web

SQL Injection, XSS, validación de datos, contraseñas seguras y password_hash(): la base de una web responsable.

0 / 5 lecciones completadas (0%)

Lección 1

SQL Injection

📘 Explicación

Ya se vio en el Módulo 2: la inyección SQL ocurre cuando datos escritos por el usuario se mezclan sin protección dentro de una consulta SQL, permitiendo que alguien manipule esa consulta. La defensa siempre son las consultas preparadas.

PHP
// Vulnerable:
$sql = "SELECT * FROM usuarios WHERE usuario = '$usuario' AND clave = '$clave'";
// Un atacante podria escribir: ' OR '1'='1  y saltarse el login

// Protegido:
$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE usuario = ? AND clave = ?");
$stmt->execute([$usuario, $clave]);
🧠 Ejercicio interactivo

¿Qué intenta conseguir un atacante con una inyección SQL en un formulario de login?

📎 Recursos oficiales
Lección 2

XSS

📘 Explicación

XSS (Cross-Site Scripting) ocurre cuando una web muestra sin filtrar texto escrito por un usuario, y ese texto contiene código JavaScript. Ese código se ejecuta en el navegador de otras personas que visiten la página, pudiendo robar información o suplantar sesiones.

PHP
// Vulnerable: se muestra el comentario tal cual
echo "<p>" . $_POST["comentario"] . "</p>";
// Un atacante podria escribir: <script>alert('hackeado')</script>

// Protegido: se escapan los caracteres especiales antes de mostrarlos
echo "<p>" . htmlspecialchars($_POST["comentario"], ENT_QUOTES) . "</p>";
🧠 Ejercicio interactivo

¿Qué hace htmlspecialchars() para prevenir XSS?

Lección 3

Validación

📘 Explicación

Validar significa comprobar que un dato cumple lo esperado antes de usarlo: que un email tenga formato de email, que una edad sea un número positivo, que un campo obligatorio no esté vacío. Es la primera línea de defensa contra datos incorrectos o maliciosos.

PHP
function validarEdad($edad) {
    if (!is_numeric($edad)) return "La edad debe ser un numero.";
    if ($edad < 0 || $edad > 120) return "La edad no parece valida.";
    return true;
}

$resultado = validarEdad($_POST["edad"] ?? "");
if ($resultado !== true) {
    echo $resultado;
}
🧠 Ejercicio interactivo

¿Cuál de estas es una buena práctica de validación de datos?

Lección 4

Contraseñas seguras

📘 Explicación

Una contraseña segura es larga, no se reutiliza en varios sitios y combina letras, números y símbolos. Como desarrolladores, además, nunca se debe guardar la contraseña de un usuario tal cual (en texto plano) en la base de datos.

Estructura / Referencia
Contrasena debil:   123456, nombre1234, qwerty
Contrasena fuerte:  frase-larga-Y-dificil-de-adivinar-2026!

Regla de oro para desarrolladores:
NUNCA guardar la contrasena real en la base de datos.
Se guarda un "hash": una huella irreversible de la contrasena.
🧠 Ejercicio interactivo

¿Por qué no se debe guardar la contraseña de un usuario tal cual en la base de datos?

Lección 5

password_hash()

📘 Explicación

PHP incluye la función password_hash() para convertir una contraseña en un hash seguro de forma automática, y password_verify() para comprobar si una contraseña introducida coincide con ese hash, sin necesidad de «deshacer» el hash nunca.

PHP
// Al registrar un usuario:
$hash = password_hash($_POST["clave"], PASSWORD_DEFAULT);
// Se guarda $hash en la base de datos, nunca la contrasena original

// Al iniciar sesion:
$hashGuardado = "..."; // obtenido de la base de datos
if (password_verify($_POST["clave"], $hashGuardado)) {
    echo "Contrasena correcta, acceso permitido.";
} else {
    echo "Contrasena incorrecta.";
}
🧠 Ejercicio interactivo

¿Qué hace password_verify() en el ejemplo anterior?