Ssrf in Flask with Basic Auth
Ssrf in Flask with Basic Auth — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in a Flask application that uses HTTP Basic Authentication can expose internal services and bypass access controls that rely on authentication boundaries. When authentication is enforced only at the application layer, an attacker who can trigger SSRF may force the server to make outbound requests that carry the application’s credentials, such as the Authorization header used for Basic Auth.
Consider a Flask route that accepts a URL from an authenticated user and fetches its content. If the route does not validate or sanitize the target, an attacker can supply an internal address like http://127.0.0.1:8000/admin. Because the request originates from the server and includes the Authorization header, the backend service may trust the request and return sensitive data. middleBrick scans detect this by submitting unauthenticated probes that attempt to leverage supplied URLs to reach internal endpoints, and findings can include data exposure when internal routes inadvertently trust the originating server’s credentials.
Basic Auth transmits credentials in an encoded but easily reversible format. If a Flask app decodes and reuses the same credentials when making outbound SSRF-capable requests, an attacker can effectively pivot through internal services that expose administrative or diagnostic interfaces on localhost or internal networks. This is especially dangerous in environments where services rely on IP-based trust and assume requests from the application server are inherently safe. The combination of SSRF and Basic Auth can therefore turn a seemingly limited input vector into a path toward internal reconnaissance, credential harvesting, and lateral movement.
middleBrick’s 12 security checks run in parallel and include Data Exposure and Input Validation tests that help surface SSRR risks even when authentication headers are present. By correlating OpenAPI specifications with runtime behavior, the scanner can highlight endpoints where user-supplied URLs may bypass expected network boundaries and reach internal resources that should remain isolated.
Basic Auth-Specific Remediation in Flask — concrete code fixes
To mitigate SSRF in Flask when using Basic Auth, avoid reusing authentication credentials for outbound requests, and strictly validate and restrict target URLs. Do not forward user-controlled URLs to services that trust the originating server, and prefer allowlists for schemes and hosts.
Example: Vulnerable Flask endpoint with Basic Auth
from flask import Flask, request, Response
from urllib.request import urlopen
import base64
app = Flask(__name__)
@app.route('/fetch')
def fetch_url():
auth = request.authorization
if not auth or auth.username != 'admin' or auth.password != 'secret':
return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic'})
target = request.args.get('url')
# Dangerous: uses user-supplied URL and reuses server-side auth context
resp = urlopen(target)
return resp.read()
Remediation 1: Validate and restrict target URLs
Use an allowlist of permitted hosts and reject URLs that point to localhost, internal IPs, or sensitive paths. Do not forward authentication headers to the target.
from flask import Flask, request, Response, abort
from urllib.parse import urlparse
import requests
ALLOWED_HOSTS = {'api.example.com', 'data.example.com'}
@app.route('/fetch')
def fetch_url():
auth = request.authorization
if not auth or auth.username != 'admin' or auth.password != 'secret':
return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic'})
target = request.args.get('url')
if not target:
abort(400, 'url parameter is required')
parsed = urlparse(target)
if parsed.scheme not in ('http', 'https'):
abort(400, 'Unsupported scheme')
if parsed.hostname not in ALLOWED_HOSTS:
abort(403, 'Host not allowed')
# Do not reuse request.authorization headers; make unauthenticated call
resp = requests.get(target, timeout=5)
return resp.content
Remediation 2: Use a proxy with strict controls or an allowlisted fetch library
Instead of raw urlopen, use a controlled HTTP client with disabled redirects and no authentication inheritance. Enforce timeouts and avoid passing user headers downstream.
import requests
def safe_fetch(url: str) -> bytes:
resp = requests.get(
url,
allow_redirects=False,
timeout=5,
headers={'User-Agent': 'middleBrick-safe-fetcher'}
)
resp.raise_for_status()
return resp.content
These changes reduce the attack surface by ensuring that even if SSRF is attempted, the server cannot reach internal services or leak credentials through reused Basic Auth headers. When integrating with CI/CD, the middleBrick GitHub Action can be configured to fail builds if risky patterns are detected, and the dashboard can track how remediation reduces findings over time.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |