Ssrf Server Side in Flask with Basic Auth
Ssrf Server Side 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 amplify risk because the server may act as an authenticated client when it forwards requests. An attacker who can influence the target URL or request parameters may cause the Flask service to issue requests to internal or external endpoints, carrying along the embedded credentials or session context. This is especially dangerous when the Flask route accepts a URL input—such as a webhook, import, or fetch feature—and uses an HTTP client without strict allowlisting or network segregation.
Consider a Flask route that retrieves a remote configuration file and includes an Authorization header derived from a hardcoded or user-supplied Basic Auth credential. If an attacker can control the target URL, they can direct the server to probe internal services that are only reachable from within the network (e.g., http://169.254.169.254/latest/meta-data/ on cloud environments, or admin dashboards on http://127.0.0.1:8080). Because the request is issued by the server with Basic Auth credentials, the backend may trust the response and return sensitive data back to the attacker, effectively turning the Flask app into a proxy for authenticated internal calls.
OpenAPI/Swagger specs that describe such endpoints can inadvertently document permissive URL parameters or omit network-level constraints, which an attacker can exploit during reconnaissance. When the spec is analyzed alongside runtime behavior, SSRF-related findings may reveal that user-controlled inputs flow directly into an HTTP client without validation or egress filtering. Even without authentication, SSRF is critical; with Basic Auth, the impact can extend to data exfiltration from internal systems that would otherwise be unreachable.
An LLM/AI Security context adds another dimension: if an endpoint exposes functionality that interacts with models or external APIs, SSRF can be chained to probe or manipulate those interfaces. For example, an attacker might attempt to reach an unauthenticated LLM endpoint hosted internally, or induce the Flask app to make requests that leak system prompts or configuration. While middleBrick’s LLM/AI Security checks do not remediate these issues, they help detect unusual patterns of access or leakage that may accompany a compromised SSRF vector.
In practice, mitigating SSRF in this scenario requires strict input validation, network egress controls, and avoiding the automatic propagation of credentials to user-influenced destinations. Tools like middleBrick can support detection by scanning the unauthenticated attack surface and, when used under the Pro plan, enabling continuous monitoring to catch regressions that reintroduce risky request behaviors.
Basic Auth-Specific Remediation in Flask — concrete code fixes
To reduce SSRF risk when using Basic Authentication in Flask, ensure that user-controlled inputs never directly determine request targets or headers. Below are concrete remediation patterns and code examples.
Problematic pattern: A route that forwards to a user-supplied URL and adds Basic Auth headers from configuration or user input.
from flask import Flask, request
import requests
app = Flask(__name__)
# Risky: user controls url, auth is applied automatically
@app.route("/fetch")
def fetch():
url = request.args.get("url")
username = "admin"
password = "secret"
resp = requests.get(url, auth=(username, password))
return resp.text
This pattern is dangerous because url is not validated, enabling SSRF. The Basic Auth credentials are sent to any destination, potentially exposing them to internal services that the attacker can reach.
Remediation 1: strict allowlisting of hosts. Only permit requests to known, internal endpoints. Do not rely on hostname checks alone; parse the URL and validate the host and port.
from urllib.parse import urlparse
from flask import Flask, request, abort
import requests
app = Flask(__name__)
ALLOWED_HOSTS = {"api.internal.example.com"}
ALLOWED_PORTS = {443}
@app.route("/fetch")
def fetch():
url = request.args.get("url")
if not url:
abort(400, "url parameter is required")
parsed = urlparse(url)
if parsed.scheme not in {"https"}:
abort(400, "only HTTPS is allowed")
if parsed.hostname not in ALLOWED_HOSTS or parsed.port not in ALLOWED_PORTS:
abort(403, "destination not allowed")
# credentials are not derived from user input
resp = requests.get(url, timeout=5)
resp.raise_for_status()
return resp.text
Remediation 2: avoid embedding user-influenced data into request headers. If you must use Basic Auth, keep credentials server-side and do not allow the client to influence the authorization target.
from flask import Flask, request, abort
import requests
from requests.auth import HTTPBasicAuth
app = Flask(__name__)
@app.route("/data")
def get_data():
# user input only controls path, not auth target
item_id = request.args.get("item_id")
if not item_id:
abort(400, "item_id is required")
# server-side credentials, no user influence
auth = HTTPBasicAuth("service_user", "server_side_secret")
resp = requests.get(
f"https://api.internal.example.com/v1/items/{item_id}",
auth=auth,
timeout=5
)
resp.raise_for_status()
return resp.json()
These changes reduce the attack surface by removing user control over the destination and ensuring credentials are not dynamically derived from untrusted sources. Defense in depth can be further improved with network policies that restrict outbound connections from the Flask service.
For ongoing assurance, you can use the CLI tool to scan from terminal with middlebrick scan <url>, or integrate the GitHub Action to add API security checks to your CI/CD pipeline. If you need continuous visibility, the Pro plan supports 100 APIs with continuous monitoring and alerts, which can help detect configurations that drift toward risky patterns.