Introducción

El control de acceso roto es una de las vulnerabilidades más comunes y peligrosas en las aplicaciones web. Ocurre cuando las restricciones sobre lo que los usuarios autenticados pueden hacer no se aplican correctamente. Los atacantes pueden explotar estas fallas para acceder a funcionalidades y datos que no deberían estar disponibles para ellos.

Conceptos Clave

  1. Control de Acceso: Mecanismos que determinan qué usuarios pueden realizar qué acciones en una aplicación.
  2. Autenticación: Proceso de verificar la identidad de un usuario.
  3. Autorización: Proceso de verificar si un usuario autenticado tiene permiso para realizar una acción específica.

Ejemplos Comunes de Control de Acceso Roto

  1. Acceso Directo a URLs:

    • Los usuarios pueden acceder a URLs restringidas simplemente ingresándolas en la barra de direcciones del navegador.
    • Ejemplo: Un usuario no autorizado accede a /admin/dashboard y obtiene acceso a funcionalidades administrativas.
  2. Modificación de Parámetros:

    • Los usuarios pueden manipular parámetros en las solicitudes para obtener acceso no autorizado.
    • Ejemplo: Cambiar el parámetro user_id en una solicitud de /profile?user_id=123 a otro valor para ver el perfil de otro usuario.
  3. Falta de Validación de Roles:

    • La aplicación no valida adecuadamente los roles de usuario antes de permitir acciones específicas.
    • Ejemplo: Un usuario con rol de "cliente" puede acceder a funcionalidades reservadas para el rol de "administrador".

Ejemplo Práctico

Código Vulnerable

// Ejemplo en Java
@WebServlet("/admin/dashboard")
public class AdminDashboardServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Asume que el usuario está autenticado
        String userRole = (String) request.getSession().getAttribute("role");
        
        // No se verifica el rol del usuario
        if (userRole != null) {
            request.getRequestDispatcher("/WEB-INF/admin/dashboard.jsp").forward(request, response);
        } else {
            response.sendRedirect("/login");
        }
    }
}

Explicación del Código Vulnerable

En este ejemplo, la aplicación asume que cualquier usuario autenticado puede acceder al panel de administración. No se verifica si el usuario tiene el rol adecuado (por ejemplo, "administrador") antes de permitir el acceso.

Código Seguro

// Ejemplo en Java
@WebServlet("/admin/dashboard")
public class AdminDashboardServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Asume que el usuario está autenticado
        String userRole = (String) request.getSession().getAttribute("role");
        
        // Verifica si el usuario tiene el rol de administrador
        if ("admin".equals(userRole)) {
            request.getRequestDispatcher("/WEB-INF/admin/dashboard.jsp").forward(request, response);
        } else {
            response.sendRedirect("/access-denied");
        }
    }
}

Explicación del Código Seguro

En este ejemplo, la aplicación verifica si el usuario tiene el rol de "administrador" antes de permitir el acceso al panel de administración. Si el usuario no tiene el rol adecuado, se redirige a una página de acceso denegado.

Ejercicio Práctico

Ejercicio 1: Identificación de Control de Acceso Roto

Instrucciones:

  1. Revisa el siguiente fragmento de código y encuentra la vulnerabilidad de control de acceso roto.
  2. Propón una solución para corregir la vulnerabilidad.
# Ejemplo en Python (Flask)
@app.route('/user/<int:user_id>')
def user_profile(user_id):
    user = get_user_from_db(user_id)
    if user:
        return render_template('profile.html', user=user)
    else:
        return "User not found", 404

Solución:

  1. Identificación de la Vulnerabilidad:

    • El código permite a cualquier usuario acceder al perfil de cualquier otro usuario simplemente cambiando el user_id en la URL.
  2. Corrección de la Vulnerabilidad:

    • Verificar que el user_id en la URL coincide con el user_id del usuario autenticado.
# Ejemplo en Python (Flask)
@app.route('/user/<int:user_id>')
@login_required
def user_profile(user_id):
    current_user_id = session.get('user_id')
    if current_user_id == user_id:
        user = get_user_from_db(user_id)
        if user:
            return render_template('profile.html', user=user)
        else:
            return "User not found", 404
    else:
        return "Access denied", 403

Explicación de la Solución

  • @login_required: Asegura que solo los usuarios autenticados pueden acceder a la ruta.
  • Verificación de user_id: Compara el user_id en la URL con el user_id del usuario autenticado para asegurar que solo el propietario del perfil puede acceder a él.

Resumen

El control de acceso roto es una vulnerabilidad crítica que puede permitir a los atacantes acceder a datos y funcionalidades no autorizadas. Es esencial implementar controles de acceso robustos y verificar tanto la autenticación como la autorización de los usuarios en cada punto de entrada de la aplicación. A través de ejemplos prácticos y ejercicios, hemos visto cómo identificar y corregir estas vulnerabilidades para mejorar la seguridad de nuestras aplicaciones web.

Curso de OWASP: Directrices y Estándares para la Seguridad en Aplicaciones Web

Módulo 1: Introducción a OWASP

Módulo 2: Principales Proyectos de OWASP

Módulo 3: OWASP Top Ten

Módulo 4: OWASP ASVS (Application Security Verification Standard)

Módulo 5: OWASP SAMM (Software Assurance Maturity Model)

Módulo 6: OWASP ZAP (Zed Attack Proxy)

Módulo 7: Buenas Prácticas y Recomendaciones

Módulo 8: Ejercicios Prácticos y Casos de Estudio

Módulo 9: Evaluación y Certificación

© Copyright 2024. Todos los derechos reservados