Módulo 6: Conceptos de Desarrollo Web

Seguridad básica en PHP

Lección 31 de 33 del Curso Roadmap Learning Laravel

Duración: 45 minutos
Nivel: Principiante (requiere conocimientos de HTML, CSS, JavaScript, PHP básico, MySQL, SQL básico, protocolo HTTP, patrón MVC, y configuración de entornos locales)
Objetivo: Comprender los fundamentos de seguridad en PHP, enfocándose en la validación de entradas y la prevención de inyección SQL, y aplicarlos para proteger aplicaciones web, como preparación para frameworks como Laravel.
Materiales necesarios:

  • Computadora con:
    • XAMPP o Laragon instalado (entorno local con Apache, PHP, MySQL, configurado en Lección 3).
    • Navegador web (Chrome, Firefox, etc.) con herramientas de desarrollo (DevTools, accesible con F12).
    • Editor de texto (recomendado: VS Code, descarga gratuita desde code.visualstudio.com).
    • Papel y lápiz para notas.
  • Acceso a internet (para referencias o la tarea).
    Contexto: La seguridad en PHP es crucial para proteger aplicaciones web contra ataques comunes, como la inyección SQL, que pueden comprometer bases de datos (Módulo 5). Esta lección se basa en los formularios PHP del Módulo 4, las solicitudes HTTP del Módulo 6, y el entorno local del Módulo 6, preparando al estudiante para desarrollar aplicaciones seguras.

Introducción a la seguridad en PHP (10 minutos)

Explicación:
La seguridad en PHP implica proteger aplicaciones web contra ataques que explotan vulnerabilidades, como datos de usuario no validados o consultas SQL inseguras. Dos prácticas fundamentales son la validación de entradas y la prevención de inyección SQL.

Conceptos clave:

  • Validación de entradas:
    • Verificar que los datos enviados por el usuario (por ejemplo, en formularios) sean válidos y seguros.
    • Ejemplo: Asegurarse de que un campo de email contenga un formato válido (como usuario@dominio.com).
    • Técnicas:
      • Usar funciones PHP como filter_var() o trim().
      • Comprobar longitud, tipo, y formato de los datos.
  • Inyección SQL:
    • Ataque donde un usuario inserta código SQL malicioso en un formulario para manipular la base de datos.
    • Ejemplo: Un formulario vulnerable podría permitir borrar datos con una entrada como '; DROP TABLE usuarios; --.
    • Prevención:
      • Usar consultas preparadas con PDO o mysqli.
      • Escapar datos con funciones como mysqli_real_escape_string().
  • Por qué es importante:
    • En Módulo 4, creaste formularios PHP que guardaban datos en MySQL (Módulo 5). Sin validación, estos son vulnerables.
    • La seguridad es esencial en aplicaciones reales, como las desarrolladas con Laravel.

Punto clave: Validar entradas y prevenir inyección SQL protege los datos y la integridad de la aplicación.

Actividad rápida (2 minutos):
Escribe en papel un ejemplo de dato que debería validarse en un formulario.

  • Ejemplo:
    • Dato: Email.
    • Validación: Comprobar formato (usuario@dominio.com).

Validación de entradas (10 minutos)

Explicación:
La validación de entradas asegura que los datos del usuario sean correctos y seguros antes de procesarlos. Esto incluye limpiar datos y verificar su formato.

Técnicas comunes:

  1. Limpiar datos:
    • Eliminar espacios innecesarios con trim().
    • Escapar caracteres especiales para HTML con htmlspecialchars() (evita ataques XSS).
    • Ejemplo:
      $nombre = trim($_POST['nombre']); 
      $nombre = htmlspecialchars($nombre);
  2. Validar formato:

    • Usar filter_var() para validar tipos específicos (por ejemplo, email, entero).
    • Ejemplo:
      if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { 
      die("Email inválido"); 
      }
      
      
  3. Comprobar longitud y valores permitidos:

    • Asegurarse de que un campo no esté vacío o sea demasiado largo.
    • Ejemplo:
      if (empty($_POST['nombre']) || strlen($_POST['nombre']) > 100) {
       die("Nombre inválido"); 
      }

Por qué es importante:

  • En Módulo 4, usaste $_POST directamente sin validación, lo que puede permitir datos maliciosos.
  • La validación evita errores y ataques, como entradas vacías o mal formadas.

Punto clave: Validar y limpiar entradas es el primer paso para una aplicación segura.

Actividad rápida (2 minutos):
Escribe en papel una función PHP que usarías para validar un email.

  • Ejemplo:
    • Función: filter_var($email, FILTER_VALIDATE_EMAIL).

Prevención de inyección SQL (10 minutos)

Explicación:
La inyección SQL ocurre cuando un atacante inserta código SQL en un formulario para manipular la base de datos. La mejor defensa es usar consultas preparadas.

Cómo ocurre la inyección SQL:

  • Ejemplo vulnerable (Módulo 4):
    $email = $_POST['email']; 
    $query = "SELECT * FROM usuarios WHERE email = '$email'"; 
    // Si $email es: ' OR '1'='1 
    // Resultado: SELECT * FROM usuarios WHERE email = '' OR '1'='1' 
    // Esto devuelve todos los usuarios (vulnerabilidad).

Prevención:

  1. Consultas preparadas:
    • Usar PDO o mysqli para parametrizar consultas, evitando que los datos del usuario se interpreten como código SQL.
    • Ejemplo con PDO:
      $pdo = new PDO("mysql:host=localhost;dbname=app_usuarios", "root", "");
      $stmt = $pdo->prepare("SELECT * FROM usuarios WHERE email = ?");
      $stmt->execute([$_POST['email']]);
      $usuario = $stmt->fetch();
    • Ejemplo con mysqli:
      $conexion = new mysqli("localhost", "root", "", "app_usuarios");
      $stmt = $conexion->prepare("SELECT * FROM usuarios WHERE email = ?");
      $stmt->bind_param("s", $_POST['email']);
      $stmt->execute();
      $resultado = $stmt->get_result();
  2. Escapar datos (si no usas consultas preparadas):
    • Usar mysqli_real_escape_string() para escapar caracteres especiales.
    • Ejemplo:
      $email = $conexion->real_escape_string($_POST['email']);
      $query = "SELECT * FROM usuarios WHERE email = '$email'";
    • Nota: Las consultas preparadas son preferibles, ya que son más seguras.

Por qué es importante:

  • En Módulo 5, usaste consultas SQL para gestionar datos. Sin protección, son vulnerables.
  • Las consultas preparadas son estándar en Laravel (Eloquent ORM).

Punto clave: Las consultas preparadas previenen la inyección SQL al separar datos y código.

Actividad rápida (2 minutos):
Escribe en papel una ventaja de usar consultas preparadas.

  • Ejemplo:
    • Ventaja: Evita que datos del usuario se interpreten como código SQL.

Ejemplo práctico: Escapa datos de un formulario antes de guardarlos (10 minutos)

Explicación:
Crearemos un formulario PHP que guarda un usuario (nombre y email) en una base de datos, aplicando validación de entradas y consultas preparadas para prevenir inyección SQL.

Escenario:

  • Base de datos: app_usuarios con una tabla usuarios (creada en Módulo 5).
    CREATE TABLE usuarios (
        id INT AUTO_INCREMENT PRIMARY KEY,
        nombre VARCHAR(100) NOT NULL,
        email VARCHAR(100) NOT NULL UNIQUE
    );
  • Formulario: Permite registrar un usuario.
  • Seguridad: Validar entradas y usar consultas preparadas.

Código del ejemplo:

  1. Formulario HTML (formulario.html):
    <!DOCTYPE html>
    <html lang="es">
    <head>
        <meta charset="UTF-8">
        <title>Registrar Usuario</title>
    </head>
    <body>
        <h2>Registro de Usuario</h2>
        <form action="procesar.php" method="POST">
            <label>Nombre: <input type="text" name="nombre"></label><br>
            <label>Email: <input type="email" name="email"></label><br>
            <button type="submit">Registrar</button>
        </form>
    </body>
    </html>
  2. Procesamiento PHP (procesar.php):
    <?php
    // Validación de entradas
    $nombre = trim($_POST['nombre'] ?? '');
    $email = trim($_POST['email'] ?? '');
    
    if (empty($nombre) || strlen($nombre) > 100) {
        die("Error: El nombre es obligatorio y debe tener menos de 100 caracteres.");
    }
    
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        die("Error: El email no es válido.");
    }
    
    // Conexión a la base de datos
    $conexion = new mysqli("localhost", "root", "", "app_usuarios");
    if ($conexion->connect_error) {
        die("Error de conexión: " . $conexion->connect_error);
    }
    
    // Consulta preparada para prevenir inyección SQL
    $stmt = $conexion->prepare("INSERT INTO usuarios (nombre, email) VALUES (?, ?)");
    $stmt->bind_param("ss", $nombre, $email);
    
    // Ejecutar y verificar
    if ($stmt->execute()) {
        echo "Usuario registrado: $nombre ($email)";
    } else {
        echo "Error al registrar: " . $conexion->error;
    }
    
    // Cerrar recursos
    $stmt->close();
    $conexion->close();
    ?>

Cómo probarlo:

  1. Asegúrate de que XAMPP o Laragon esté corriendo (Apache y MySQL).
  2. Crea la base de datos app_usuarios y la tabla usuarios en phpMyAdmin (http://localhost/phpmyadmin).
  3. Guarda formulario.html y procesar.php en C:\xampp\htdocs\seguridad (XAMPP) o C:\laragon\www\seguridad (Laragon).
  4. Abre http://localhost/seguridad/formulario.html (XAMPP) o http://seguridad.test/formulario.html (Laragon).
  5. Prueba el formulario:
    • Válido: Nombre: “Ana”, Email: “ana@correo.com” → Mensaje: “Usuario registrado: Ana (ana@correo.com)”.
    • Inválido: Nombre: vacío, Email: “no_es_email” → Mensaje de error.
  6. Usa DevTools (F12, pestaña “Red”):
    • Verifica la solicitud POST a procesar.php.
    • Código de estado: 200 OK (si es exitoso).
  7. Prueba una inyección SQL (por ejemplo, Email: '; DROP TABLE usuarios; --):
    • La consulta preparada la neutraliza, evitando el ataque.

Por qué es importante:

  • Este ejemplo mejora los formularios del Módulo 4 al añadir validación y seguridad.
  • Prepara para Laravel, donde usarás validación (Validator) y Eloquent para consultas seguras.

Punto clave: Validar y escapar datos de un formulario protege contra ataques y errores.

Actividad rápida (3 minutos):
Escribe en papel una línea de código para validar un email en el ejemplo.

  • Ejemplo:
    • Línea: if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { die("Email inválido"); }.

5. Resumen y preparación para la tarea (5 minutos)

Resumen:

  • Seguridad en PHP: Proteger aplicaciones contra ataques comunes.
  • Validación de entradas: Limpiar y verificar datos con trim(), filter_var(), etc.
  • Inyección SQL: Prevenirla con consultas preparadas (PDO o mysqli).
  • Ejemplo: Formulario seguro que valida y guarda datos en la base de datos.

Preparación para la tarea:
La tarea pide añadir validación a un formulario PHP.

  • Estrategia:
    • Crea un formulario similar al del Módulo 4 (por ejemplo, registro de tareas).
    • Valida entradas (por ejemplo, no vacías, formato correcto).
    • Usa consultas preparadas para guardar datos en MySQL.
  • Lógica básica:
    • HTML: Formulario con campos (por ejemplo, título, descripción).
    • PHP: Validar con filter_var(), trim(); usar mysqli_prepare().
    • Prueba en XAMPP/Laragon.

Punto clave: La validación y las consultas preparadas son esenciales para aplicaciones PHP seguras.


Tarea práctica: Añade validación a un formulario PHP

Instrucciones:

  1. Crea un formulario PHP que guarde datos en una base de datos, basado en los proyectos del Módulo 4 o 5.
    • Tema sugerido: Registro de tareas (título, descripción), pero puedes elegir otro (por ejemplo, registro de productos).
    • Funcionalidad mínima: Recibir datos de un formulario, validarlos, y guardarlos en MySQL.
  2. Requisitos de seguridad:
    • Validación de entradas:
      • Asegurarse de que los campos no estén vacíos.
      • Validar formatos (por ejemplo, longitud máxima, tipo de dato).
      • Usar al menos trim() y htmlspecialchars().
    • Prevención de inyección SQL:
      • Usar consultas preparadas con mysqli o PDO.
  3. Estructura:
    • Base de datos: Crea una tabla (por ejemplo, tareas).
    • Formulario HTML: Campos para los datos (por ejemplo, título, descripción).
    • Script PHP: Valida y guarda los datos.
  4. Entregable:
    • Un archivo de texto o documento (tarea_seguridad.txt o .docx) con:
      • Descripción del formulario (qué hace).
      • SQL para la base de datos (por ejemplo, CREATE TABLE).
      • Código HTML del formulario.
      • Código PHP con validación y consulta preparada.
      • Resultado de la prueba (por ejemplo, “Guardé una tarea correctamente”).
    • Opcional: Captura de pantalla del formulario o resultado.
  5. Ejemplo de guía:
    Tarea: Formulario seguro para registrar tareas
    
    Descripción: Un formulario PHP que guarda tareas (título, descripción) en una base de datos.
    
    Base de datos:
    CREATE DATABASE app_tareas;
    CREATE TABLE tareas (
        id INT AUTO_INCREMENT PRIMARY KEY,
        titulo VARCHAR(200) NOT NULL,
        descripcion TEXT
    );
    
    Formulario HTML (formulario.html):
    <form action="procesar.php" method="POST">
        <label>Título: <input type="text" name="titulo"></label><br>
        <label>Descripción: <textarea name="descripcion"></textarea></label><br>
        <button type="submit">Guardar</button>
    </form>
    
    Script PHP (procesar.php):
    <?php
    $titulo = trim($_POST['titulo'] ?? '');
    $descripcion = trim($_POST['descripcion'] ?? '');
    
    if (empty($titulo) || strlen($titulo) > 200) {
        die("Error: Título obligatorio, máximo 200 caracteres.");
    }
    
    $conexion = new mysqli("localhost", "root", "", "app_tareas");
    if ($conexion->connect_error) {
        die("Error de conexión: " . $conexion->connect_error);
    }
    
    $stmt = $conexion->prepare("INSERT INTO tareas (titulo, descripcion) VALUES (?, ?)");
    $stmt->bind_param("ss", $titulo, $descripcion);
    
    if ($stmt->execute()) {
        echo "Tarea registrada: $titulo";
    } else {
        echo "Error: " . $conexion->error;
    }
    
    $stmt->close();
    $conexion->close();
    ?>
    
    Resultado: Probé el formulario en Laragon (http://seguridad.test). Guardé una tarea con título “Estudiar PHP” y descripción “Capítulo 4”. Mensaje: “Tarea registrada: Estudiar PHP”.
  6. Pasos para completar:
    • Paso 1: Diseña el formulario y la base de datos (usa phpMyAdmin).
    • Paso 2: Crea el archivo HTML (formulario.html).
    • Paso 3: Escribe el script PHP (procesar.php) con validación y consulta preparada.
    • Paso 4: Prueba en XAMPP (http://localhost/seguridad) o Laragon (http://seguridad.test).
    • Paso 5: Documenta el proceso en un archivo de texto o documento.
    • Paso 6: Opcional: Incluye una captura de pantalla.

Ejemplo de solución esperada:

  • Archivo (tarea_seguridad.txt):
    Tarea: Formulario seguro para registrar tareas
    
    Descripción: Un formulario PHP que guarda tareas en una base de datos con validación y consultas preparadas.
    
    Base de datos:
    CREATE DATABASE app_tareas;
    CREATE TABLE tareas (
        id INT AUTO_INCREMENT PRIMARY KEY,
        titulo VARCHAR(200) NOT NULL,
        descripcion TEXT
    );
    
    Formulario HTML (formulario.html):
    <form action="procesar.php" method="POST">
        <label>Título: <input type="text" name="titulo"></label><br>
        <label>Descripción: <textarea name="descripcion"></textarea></label><br>
        <button type="submit">Guardar</button>
    </form>
    
    Script PHP (procesar.php):
    <?php
    $titulo = trim($_POST['titulo'] ?? '');
    $descripcion = trim($_POST['descripcion'] ?? '');
    
    if (empty($titulo) || strlen($titulo) > 200) {
        die("Error: Título obligatorio, máximo 200 caracteres.");
    }
    
    $conexion = new mysqli("localhost", "root", "", "app_tareas");
    if ($conexion->connect_error) {
        die("Error de conexión: " . $conexion->connect_error);
    }
    
    $stmt = $conexion->prepare("INSERT INTO tareas (titulo, descripcion) VALUES (?, ?)");
    $stmt->bind_param("ss", $titulo, $descripcion);
    
    if ($stmt->execute()) {
        echo "Tarea registrada: $titulo";
    } else {
        echo "Error: " . $conexion->error;
    }
    
    $stmt->close();
    $conexion->close();
    ?>
    
    Resultado: Probé en XAMPP (http://localhost/seguridad). Guardé una tarea: Título “Leer Módulo 6”, Descripción “Seguridad”. Mensaje: “Tarea registrada: Leer Módulo 6”.

Tiempo estimado: 45-60 minutos (puedes hacerlo después de la lección).
Entregable:

  • Archivo de texto o documento con descripción, SQL, códigos HTML/PHP, y resultado.
  • Opcional: Captura de pantalla.

Consejo:

  • Usa el ejemplo como referencia para estructurar el formulario y el script.
  • Prueba entradas inválidas (por ejemplo, título vacío, email mal formado) para verificar la validación.
  • Revisa los logs de XAMPP/Laragon si encuentras errores (C:\xampp\apache\logs o C:\laragon\logs).

© Copyright Cursos Laravel :: 2025 Términos y condiciones