T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/web_app.py:16
- Finding
- Authentication Bypass Through a Publicly Known Flask Session-Signing Key<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_app.py:16-18` **Vulnerability Type**: Hard-coded cryptographic secret enabling session forgery **Risk Level**: Critical ### Complete Code Snippet ```python app = Flask(__name__) app.config['JSON_AS_ASCII'] = False app.config['SECRET_KEY'] = 'your-secret-key-change-this-in-production' # 生产环境请修改 ``` The forged user identifier is resolved through the following loader: ```python @login_manager.user_loader def load_user(user_id): for username, data in USERS.items(): if data['id'] == int(user_id): return User(user_id, username, data.get('role', 'viewer')) return None ``` The administrator has user ID `1`: ```python USERS = { 'admin': { 'password': hashlib.sha256('admin123'.encode()).hexdigest(), 'id': 1, 'role': 'admin' }, ``` ### Technical Analysis Flask uses `SECRET_KEY` to authenticate session cookies. The value is a fixed string committed to the public source code and is therefore not secret. Flask-Login stores the authenticated user identifier in the Flask session and uses `load_user()` to recover the corresponding account. An attacker who knows the signing key can create a valid Flask session containing the administrator's user identifier. Because user ID `1` maps to the `admin` account, the server will accept the forged cookie as an authenticated administrator session without requiring the administrator password. The application does not rotate the key, retrieve it from a protected secret store, or reject startup when the placeholder value remains configured. ### Attack Path 1. The attacker obtains the source code or otherwise learns the fixed Flask secret. 2. The attacker confirms that the Flask service is reachable on TCP port 5000. 3. The attacker constructs a Flask-compatible signed session containing Flask-Login's user identifier for account ID `1`. 4. The attacker sends the forged session cookie to the application. 5. ...[truncated 814 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the secret from source control. 2. Generate at least 32 random bytes using a cryptographically secure generator. 3. Load the secret from a protected environment variable or secret-management service: ```python import os secret_key = os.environ.get("FLASK_SECRET_KEY") if not secret_key or secret_key == "your-secret-key-change-this-in-production": raise RuntimeError("A unique FLASK_SECRET_KEY must be configured") app.config["SECRET_KEY"] = secret_key ``` 4. Use a different secret for every deployment environment. 5. Rotate the exposed key immediately and invalidate all existing sessions. 6. Configure secure cookie properties: ```python app.config.update( SESSION_COOKIE_SECURE=True, SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE="Lax", ) ``` 7. Add automated deployment checks that reject known placeholder or low-entropy secrets. ]]>
