• Seguridad Web
  • Vulnerabilidades OWASP en Laravel: Explicación detallada

    Vulnerabilidades OWASP en Laravel: Explicación detallada

    Laravel es un framework diseñado con muchas protecciones de seguridad integradas, pero aun así es posible introducir riesgos graves si no aplicas buenas prácticas. Estas vulnerabilidades que sigue OWASP son las más comunes y peligrosas para cualquier aplicación web moderna.

    #Control de Acceso Roto (Broken Access Control)

    El control de acceso asegura que cada usuario solo pueda ver o modificar lo que está autorizado a hacer. Cuando esto falla, un usuario puede acceder a recursos o funciones que no debería.

    ¿Por qué pasa?

    • No se aplican políticas o gates en Laravel
    • Revisiones de autorización solo en el front, no en el backend
    • Confusión entre autenticación y autorización

    Cómo evitarlo:
    Laravel provee mecanismos como Policies y Gates para definir roles y permisos. Siempre autoriza en el backend incluso si la UI muestra u oculta botones.

    #Código inseguro

     1public function show($id)
     2{
     3    return User::findOrFail($id);
     4}
    

    #Código seguro

     1public function show(User $user)
     2{
     3    $this->authorize('view', $user);
     4    return $user;
     5}
    

    #Fallos Criptográficos (Cryptographic Failures)

    Esta categoría incluye cualquier uso incorrecto de criptografía que exponga datos sensibles, como contraseñas, tokens o cualquier información que deba permanecer cifrada.

    Ejemplos de problemas comunes:

    • Guardar contraseñas o información sin encriptar
    • Cifrar con algoritmos débiles o propios
    • Olvidar cifrar datos en tránsito o reposo

    Por qué es crítico:
    Si los datos importantes no están cifrados de forma segura, un atacante que obtenga acceso podría leer y reutilizar esa información sin dificultad.

    Cómo mitigarlo:
    Laravel ofrece funciones como Hash::make() y Crypt::encryptString() que implementan algoritmos robustos sin que tengas que diseñar tu propia criptografía.

    #Código inseguro

     1$user->password = $request->password;
     2$user->save();
    

    #Código seguro

     1$user->password = Hash::make($request->password);
     2$user->save();
    

    #Inyección de Código (Injection)

    Una inyección ocurre cuando datos no confiables del usuario se incluyen directamente en comandos (como SQL). Un atacante puede manipular esos datos para alterar la intención original de la consulta.

    Ejemplo típico:
    Componer una consulta SQL directamente con datos del usuario sin sanitizar.

    Por qué es peligroso:
    Esto puede permitir a un atacante ver, modificar o borrar datos de la base sin autorización. Incluso ejecutar comandos peligrosos en el sistema.

    Cómo prevenirlo en Laravel:
    Usa siempre query bindings o Eloquent en lugar de SQL crudo con interpolación de variables. Esto asegura que los valores del usuario se gestionen de forma segura.

    #Código inseguro

     1$email = $request->email;
     2$users = DB::select("SELECT * FROM users WHERE email = '$email'");
    

    #Código seguro

     1$users = User::where('email', $request->email)->get();
    

    #Diseño Inseguro (Insecure Design)

    No se refiere a un “bug” en código, sino a una falla en la arquitectura o diseño de la aplicación que deja espacio para que se exploten vulnerabilidades.

    Ejemplos:

    • APIs sin lógica de límites o protección
    • Falta de análisis de amenazas antes de construir funciones
    • Flujo de autorización débil desde el diseño

    Por qué esto es grave:
    Incluso si el código está bien, si el diseño no considera escenarios de abuso o falla en la prevención de riesgos estructurales, la seguridad se rompe fácilmente.

    Cómo mitigarlo:
    Piensa en seguridad desde la fase de diseño: modela amenazas, define límites de confianza y aplica patrones de diseño seguro desde el inicio.

    #Código inseguro

     1$request->file('file')->move(public_path('uploads'));
    

    #Código seguro

     1$request->validate([
     2    'file' => 'required|image|mimes:jpg,png,jpeg|max:2048'
     3]);
     4
     5$request->file('file')->store('uploads');
    

    #Configuración de Seguridad Incorrecta (Security Misconfiguration)

    Este fallo ocurre cuando hay ajustes inseguro en servidores, frameworks o librerías que permiten ataques fáciles.

    Ejemplos habituales:

    • APP_DEBUG=true en producción
    • Sin HTTPS forzado
    • Cookies sin atributos de seguridad

    Por qué ocurre:
    A menudo se ignoran detalles de configuración cuando se despliega la app, dejando exposiciones obvias a atacantes.

    Cómo evitarlo:
    Siempre revisa la configuración antes del despliegue, fuerza HTTPS, desactiva debug y configura cookies con atributos seguros.

    #Ejemplo de configuración insegura

     1APP_DEBUG=true
    

    #Ejemplo de configuración segura

     1APP_DEBUG=false
     2APP_ENV=production
     3SESSION_SECURE_COOKIE=true
    

    #Componentes Vulnerables y Desactualizados

    Se refiere a que tu aplicación depende de librerías, frameworks o software con vulnerabilidades conocidas o sin parches recientes.

    Por qué es importante:
    A veces no es tu propio código el problema, sino una dependencia externa que alguien más creó. Si esa librería está desactualizada o tiene fallos, tu app es vulnerable.

    Cómo mitigarlo:
    Ejecuta auditorías de dependencias regularmente y mantén Laravel y todos los paquetes de Composer actualizados.

    #Ejemplo de mala práctica

     1composer install
    

    #Ejemplo de buena práctica

     1composer audit
     2composer update
    

    #Fallos de Identificación y Autenticación

    Este tipo de fallo sucede cuando la aplicación no gestiona bien quién es el usuario o cómo se autentica, como contraseñas muy débiles o falta de límites de intentos.

    Ejemplos:

    • Sin protección contra fuerza bruta
    • Validación insuficiente de credenciales
    • Uso de lógica casera de autenticación sin seguridad probada

    Por qué es crítico:
    Autenticación débil facilita que atacantes accedan a cuentas legítimas.

    Cómo mitigarlo:
    Usa el sistema de autenticación seguro que Laravel ofrece, activa el rate limiting en logins y define reglas fuertes de contraseñas.

    #Código inseguro

     1Auth::attempt($credentials);
    

    #Código seguro

     1Route::post('/login', [LoginController::class, 'login'])
     2    ->middleware('throttle:5,1');
    

    #Fallos de Integridad de Software y Datos (Software & Data Integrity)

    Se da cuando tu aplicación confía en datos entrantes o en componentes externos sin validar su autenticidad o integridad.

    Ejemplo típico:
    Aceptar datos o binarios sin validar quién los generó o si han sido alterados.

    Por qué importa:
    Un atacante puede inyectar datos maliciosos o corromper componentes que tu sistema asume son confiables.

    Cómo mitigarlo:
    Valida todo dato externo, sigue principios de verificación de firma o hashes, y no confíes ciegamente en la entrada del cliente.

    #Código inseguro

     1$user->email = $request->email;
     2$user->save();
    

    #Código seguro

     1$request->validate([
     2    'email' => 'required|email'
     3]);
     4
     5$validated = $request->validated();
     6
     7$user->email = $validated['email'];
     8$user->save();
    

    #Fallos de Registro y Monitoreo de Seguridad

    No registrar eventos importantes o no monitorear actividad anómala permite que un ataque pase desapercibido.

    Ejemplos:

    • No registrar intentos fallidos de login
    • No alertar sobre patrones extraños
    • Falta de logging de operaciones sensibles

    Por qué falla esto:
    Sin registros ni monitoreo, no sabes qué está sucediendo en tu app hasta que es demasiado tarde.

    Cómo mitigarlo:
    Implementa logging exhaustivo, define alertas para eventos sospechosos y revisa logs con regularidad.

    #Código inseguro

     1// No se registra nada
    

    #Código seguro

     1Log::warning('Intento de login fallido', [
     2    'ip' => request()->ip(),
     3    'email' => $request->email,
     4]);
    

    #SSRF – Server-Side Request Forgery

    SSRF ocurre cuando tu servidor realiza peticiones a URLs controladas por el usuario, y eso puede permitir acceder a recursos internos o sensibles.

    Por qué es posible:
    El servidor, confiando en la entrada del usuario, hace solicitudes HTTP a cualquier dirección, sin validar si es segura.

    Cómo mitigarlo:
    Implementa listas blancas de dominios permitidos, bloquea rangos IP internos y valida estrictamente URLs entrantes.

    #Código inseguro

     1$response = Http::get($request->url);
    

    #Código seguro

     1$allowedDomains = ['example.com', 'api.example.com'];
     2
     3$host = parse_url($request->url, PHP_URL_HOST);
     4
     5abort_unless(in_array($host, $allowedDomains), 403);
     6
     7$response = Http::get($request->url);
    

    #Conclusión

    El OWASP Top 10 no es solo una lista teórica, es una guía práctica de los riesgos que más vemos en aplicaciones reales y debe incorporarse desde el diseño hasta el despliegue de tu app.

    Laravel tiene muchas herramientas para ayudarte a mitigar cada uno de estos riesgos; tu responsabilidad como desarrollador es conocerlos y aplicarlos correctamente.

    profile image of Fran Diez

    Fran Diez

    4 años de experiencia. Técnico en desarrollo de aplicaciones web y en administración de sistemas. León, España 🇪🇸. Especializado en el desarrollo de aplicaciones web únicas.

    Mas posts de Fran Diez