Broken Object Level Authorization

Broken Object Level Authorization in Flask (CVE-2024-21644) [CVE-2024-21644]

[Updated Month Year] Updated CVE-2024-21644

Overview

Real-world impact: CVE-2024-21644 describes a vulnerability in a pyLoad Flask-based component where an unauthenticated user can access a URL that returns the Flask configuration, including SECRET_KEY. This is a serious instance of improper access control (CWE-284) and information disclosure, because an attacker can obtain secrets that control session security and cryptographic protections. Exploitation: Attackers simply browsed to a misconfigured endpoint (for example /config or /debug/config) that echoed app.config without enforcing any authentication or authorization. With SECRET_KEY exposed, an attacker could forge session cookies or tokens, compromise integrity, and pivot to other sensitive data. The vulnerability stems from exposing internal state via a public route and keeping secrets in code or easily accessible config. Flask remediation approach: In Python Flask apps, never expose app.config or SECRET_KEY via HTTP responses. Secure endpoints with authentication (Flask-Login, Flask-HTTPAuth, OAuth2), and implement strict access controls for sensitive data. Move secrets out of source code into environment variables or secret stores, load them with app.config.from_envvar or a dedicated loader, and ensure production settings disable debugging features. Add tests that verify sensitive keys are not included in API responses. Patch and validation: The vulnerability was patched in pyLoad with version 0.5.0b3.dev77. For Flask apps, apply the same principles and update dependencies to remove exposed endpoints, guard sensitive routes, and review code paths that return internal state. After applying the patch, run security tests to confirm that /config or similar routes do not reveal SECRET_KEY or other secrets.

Affected Versions

pyLoad <= 0.5.0b3.dev77 (pre-patch)

Code Fix Example

Flask API Security Remediation
VULNERABLE:
from flask import Flask, jsonify
app = Flask(__name__)
app.config['SECRET_KEY'] = 'supersecret'

@app.route('/config')
def get_config():
    # Exposes sensitive configuration including SECRET_KEY
    return jsonify({k: v for k, v in app.config.items()})

FIX:
from flask import Flask, jsonify
import os
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'fallback-secret')

auth = HTTPBasicAuth()
PASSWORDS = {'admin': os.environ.get('ADMIN_PASSWORD', 'change_me')}

@auth.verify_password
def verify_password(username, password):
    return username in PASSWORDS and PASSWORDS[username] == password

@app.route('/config')
@auth.login_required
def get_config():
    safe = {'DEBUG': app.config.get('DEBUG')}
    return jsonify(safe)

if __name__ == '__main__':
    app.run(debug=False)

CVE References

Choose which optional cookies to allow. You can change this any time.