Improper handling of permissions

Improper handling of insufficient permissions or privileges

Description

Improper authorization occurs when an application does not verify a user’s permissions or reject requests that lack the required access. Unauthorized users may then reach restricted resources or operations.

Potential impact

  • Privilege escalation: Unauthorized users may gain administrative capabilities.
  • Data exposure: Sensitive data may be disclosed to users who lack access.
  • Service disruption: Unauthorized operations on system resources may interrupt the service.

Remediation

  • Check permissions for every sensitive operation and resource access.
  • Reject unauthorized requests before performing the operation and return an appropriate HTTP error status. Changing the error message alone does not enforce access control.
  • Use the authentication and authorization features available in Django, Flask or FastAPI.

Examples

These excerpts omit authentication setup, session management and user lookup. Flask-Login requires a verified user loader and login configuration; is_admin must come from trusted permission data, not client input.

Django

Before

python
# Unsafe Django code
from django.http import HttpResponse

def view_sensitive_data(request):
    if request.user.username != 'admin':
        return HttpResponse("Not authorized")
    # Process sensitive data
    return HttpResponse("Sensitive data")

After

python
# Safe Django code
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required, user_passes_test

@login_required
@user_passes_test(lambda u: u.is_superuser)
def view_sensitive_data(request):
    # Process sensitive data
    return HttpResponse("Sensitive data")

Explanation:

  • Before: The username is treated as an administrative permission. Do not assume this string comparison safely enforces user registration, renaming and authorization policies.
  • After: Django’s login_required and user_passes_test decorators restrict access to authenticated users who pass the superuser check.

Flask

Before

python
# Unsafe Flask code
from flask import Flask, request

app = Flask(__name__)

@app.route('/sensitive')
def view_sensitive_data():
    if request.args.get('user') != 'admin':
        return "Not authorized"
    # Process sensitive data
    return "Sensitive data"

After

python
# Safe Flask code
from flask import Flask, request, abort
from flask_login import login_required, current_user

app = Flask(__name__)

@app.route('/sensitive')
@login_required
def view_sensitive_data():
    if not current_user.is_admin:
        return abort(403)
    # Process sensitive data
    return "Sensitive data"

Explanation:

  • Before: The client can choose the user query parameter, so it cannot establish administrative authority.
  • After: Flask-Login supplies the authenticated current_user; the handler rejects users without the required permission.

FastAPI

Before

python
# Unsafe FastAPI code
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.get("/sensitive")
async def view_sensitive_data(request: Request):
    if request.query_params.get('user') != 'admin':
        return {"detail": "Not authorized"}
    # Process sensitive data
    return {"detail": "Sensitive data"}

After

python
# Safe FastAPI code
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

class User(BaseModel):
    username: str
    is_admin: bool

def get_current_user(token: str = Depends(oauth2_scheme)):
    # Reject access until real token verification and user lookup are implemented.
    raise HTTPException(status_code=401, detail="Token verification is not configured")

@app.get("/sensitive")
async def view_sensitive_data(current_user: User = Depends(get_current_user)):
    if not current_user.is_admin:
        raise HTTPException(status_code=403, detail="Not authorized")
    # Process sensitive data
    return {"detail": "Sensitive data"}

Explanation:

  • Before: A client-supplied username in the URL is trusted for access control.
  • After: OAuth2PasswordBearer extracts a bearer token but does not validate it. This excerpt rejects access until verification is implemented. Implement get_current_user to verify the token and retrieve permissions from a trusted user store before returning a User.

References