Crlf Injection in Flask with Bearer Tokens
Crlf Injection in Flask with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when user-controlled data is reflected into HTTP headers without sanitization, allowing an attacker to inject newline characters (\r\n) that break header structure. In Flask, APIs commonly use Bearer Tokens passed via the Authorization header (e.g., Authorization: Bearer
For example, if an endpoint accepts a custom header like X-API-Key and directly includes its value in a downstream Location header for redirects, an attacker can supply a token containing \r\nSet-Cookie: injected=value. Because CRLF characters split headers, the injected line becomes a separate header, enabling session fixation, cache poisoning, or client-side redirection to malicious sites. MiddleBrick’s scan tests this vector by submitting payloads such as %0d%0aSet-Cookie: malicious=1 in header values and checking whether the response contains the injected header lines. The tool also cross-references OpenAPI/Swagger specs (2.0, 3.0, 3.1) with runtime findings to highlight mismatches between declared security schemes and actual behavior, such as Bearer-only definitions that do not account for header injection paths.
Even when Bearer tokens are validated, frameworks like Flask may expose token material through verbose error messages or logs if developers concatenate Authorization header values into insecure redirects or responses. An attacker does not need authentication to probe these paths because middleBrick scans the unauthenticated attack surface. This makes Crlf Injection in Flask with Bearer Tokens particularly dangerous: tokens may be treated as opaque strings, but their reflection in headers can compromise integrity and enable follow-on attacks like cookie injection or open redirects.
Bearer Tokens-Specific Remediation in Flask — concrete code fixes
Remediation centers on strict input validation, avoiding header reflection, and using framework-safe constructs. Never directly embed user-supplied values into headers. If you must forward or log tokens, treat them as opaque strings and ensure they are not parsed or re-emitted as header lines. Below are concrete Flask patterns that mitigate Crlf Injection when Bearer Tokens are involved.
1. Reject tokens containing newline or carriage-return characters at the edge
from flask import Flask, request, abort
import re
app = Flask(__name__)
CRLF_RE = re.compile(r'[\r\n]')
def is_safe_token(token: str) -> bool:
return CRLF_RE.search(token) is None
@app.before_request
def validate_auth_header():
auth = request.headers.get('Authorization', '')
if auth.startswith('Bearer '):
token = auth[7:].strip()
if not token or not is_safe_token(token):
abort(400, 'Invalid token')
2. Use secure redirects with predefined URLs, never concatenate Location from user input
from flask import Flask, request, redirect, url_for
app = Flask(__name__)
@app.route('/gateway')
def gateway():
# BAD: redirect(request.args['next']) # user-controlled
# Instead, map a short alias to a trusted destination
target = request.args.get('target')
allowed = {'dashboard': '/app', 'settings': '/app/settings'}
url = allowed.get(target)
if not url:
abort(400, 'Invalid target')
return redirect(url)
3. Avoid echoing Authorization headers in responses or logs in unsafe ways
import logging
logger = logging.getLogger('api')
@app.route('/data')
def get_data():
auth = request.headers.get('Authorization', '')
# Log only that auth was present, not the full header value
logger.info('Authenticated request', extra={'auth_present': bool(auth)})
# Process token safely without reflection
return {'status': 'ok'}
4. Enforce strict Content-Security-Policy and avoid Set-Cookie from untrusted input
@app.after_request
def add_security_headers(response):
response.headers['Content-Security-Policy'] = "default-src 'self'"
# Ensure no injected Set-Cookie from app logic
if 'Set-Cookie' in response.headers:
# In practice, validate or drop any Set-Cookie that you did not explicitly set
pass
return response
5. Use WSGI middleware to sanitize headers early
class CrlfSanitizer:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# Remove dangerous newlines from header-like custom headers
headers = environ.get('HTTP_X_CUSTOM_HEADERS', '')
if '\r' in headers or '\n' in headers:
start_response('400 Bad Request', [('Content-Type', 'text/plain')])
return [b'Invalid characters in headers']
return self.app(environ, start_response)
app.wsgi_app = CrlfSanitizer(app.wsgi_app)
These patterns ensure Bearer Tokens are validated and never reflected verbatim into headers where CRLF characters can split responses. Combine these checks with automated scanning—middleBrick’s CLI can be run locally with middlebrick scan <url> to verify that your endpoints reject or safely handle maliciously crafted tokens.