Man In The Middle in Flask
How Man-In-The-Middle Manifests in Flask Applications
Man-In-The-Middle (MITM) attacks against Flask applications typically exploit weaknesses in transport layer security and session management. Flask's default configuration prioritizes developer convenience over strict security, creating several attack vectors.
Insecure Session Cookies: Flask uses itsdangerous to sign session cookies by default, but does not encrypt them. If SESSION_COOKIE_SECURE is not set to True, these signed cookies are transmitted over HTTP, allowing network eavesdroppers to steal session tokens. An attacker can then replay these cookies to hijack user sessions (CWE-523: Unprotected Transport of Credentials).
SSL Stripping: Without HTTP Strict Transport Security (HSTS), an attacker can downgrade HTTPS connections to HTTP. Flask applications that accept both HTTP and HTTPS traffic are vulnerable. An attacker intercepts the initial HTTP request and proxies it to the HTTPS endpoint, relaying traffic bidirectionally while the user believes they are on a secure connection.
Certificate Validation Bypass: Flask's development server (app.run()) uses a self-signed certificate when ssl_context='adhoc' is specified. Production deployments behind reverse proxies (e.g., Nginx) must ensure the proxy validates upstream certificates if communicating with internal services. Misconfigured proxies that disable certificate validation (verify=False in requests calls) create internal MITM opportunities.
Mixed Content: Flask templates serving HTTP assets (scripts, images) on HTTPS pages allow attackers to inject malicious content via MITM, leading to XSS or data exfiltration. Flask's url_for('static', ...) generates protocol-relative URLs only if SESSION_COOKIE_SECURE is enabled; otherwise, it may generate HTTP links.
Flask-Specific Detection Strategies and Scanning
Manual Detection: Inspect response headers for Set-Cookie. A secure session cookie includes: Secure; HttpOnly; SameSite=Strict. Missing Secure indicates transmission over HTTP. Check for Strict-Transport-Security header absence. Use curl -I https://api.example.com to examine headers. Test SSL/TLS configuration with openssl s_client -connect api.example.com:443 -tls1_2 to verify supported protocols and cipher strength.
Dynamic Scanning with middleBrick: middleBrick's Encryption check (one of its 12 parallel tests) automatically validates these Flask-specific exposures. Submit your Flask API endpoint to the middleBrick Dashboard or run middlebrick scan https://your-flask-api.com via the CLI. The scan will:
- Detect missing
SecureandHttpOnlyflags on session cookies - Identify absent HSTS headers or short
max-age - Flag weak TLS versions (e.g., TLS 1.0/1.1) and insecure cipher suites
- Report mixed content issues in HTML responses
The report assigns an Encryption category score (0–100) and provides prioritized findings with remediation steps. For CI/CD integration, the middleBrick GitHub Action can fail PRs if the Encryption score drops below your threshold.
Flask-Specific Remediation: Code-Level Fixes
Enforce Secure Session Cookies: Configure Flask to set cookies with Secure, HttpOnly, and strict SameSite attributes. In your application factory or main module:
from flask import Flask
app = Flask(__name__)
app.config.update(
SESSION_COOKIE_SECURE=True, # Only send over HTTPS
SESSION_COOKIE_HTTPONLY=True, # Prevent JavaScript access
SESSION_COOKIE_SAMESITE='Strict', # Block cross-site sending
SECRET_KEY=os.environ.get('SECRET_KEY', 'fallback-secret-key') # Use strong, random key
)Enable HSTS: Force browsers to use HTTPS for future connections. Set these configs before first request:
app.config['SECURE_HSTS_SECONDS'] = 31536000 # 1 year
app.config['SECURE_HSTS_INCLUDE_SUBDOMAINS'] = True
app.config['SECURE_HSTS_PRELOAD'] = True # Optional, for browser preload listsAlternatively, use the flask-talisman extension for comprehensive security headers:
from flask_talisman import Talisman
Talisman(app,
force_https=True,
session_cookie_secure=True,
strict_transport_security=True,
content_security_policy={
'default-src': ["'self'"],
'script-src': ["'self'"],
}
)Disable HTTP: In production, configure your reverse proxy (Nginx/Apache) to redirect all HTTP to HTTPS. For Flask's development server, set app.run(ssl_context='adhoc') only for local testing—never in production.
Validate Internal Calls: If your Flask app makes outbound requests to internal APIs, validate certificates:
import requests
response = requests.get('https://internal-service/api', verify='/path/to/ca-bundle.pem')After applying these fixes, rescan with middleBrick to confirm the Encryption score improves. The middleBrick CLI allows quick iteration: middlebrick scan --format json https://your-api.com to track category scores programmatically.
Frequently Asked Questions
Why are Flask's default session cookies vulnerable to MITM even if they're signed?
Secure flag, these cookies are sent over HTTP, allowing an attacker to intercept and replay them. The signature only ensures integrity, not confidentiality. Always set SESSION_COOKIE_SECURE=True to enforce HTTPS-only transmission.