Ssrf in Flask with Cockroachdb
Ssrf in Flask with Cockroachdb — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in a Flask application that uses CockroachDB can occur when user-controlled input is used to form network requests or database connection parameters without adequate validation. In this stack, an attacker may exploit dynamic configuration or introspection features to coerce the server into making arbitrary outbound HTTP requests or to manipulate internal service discovery that ultimately reaches CockroachDB.
Consider a Flask route that accepts a database node hostname or proxy URL from a query parameter to construct a CockroachDB connection string:
from flask import Flask, request
import psycopg2
app = Flask(__name__)
@app.route('/query')
def query_db():
host = request.args.get('host', 'localhost')
port = request.args.get('port', '26257')
dbname = request.args.get('db', 'mydb')
conn_str = f'postgresql://root@{host}:{port}/{dbname}'
conn = psycopg2.connect(conn_str)
cur = conn.cursor()
cur.execute('SELECT 1')
return str(cur.fetchone())
If the host parameter is not strictly validated, an attacker can supply an internal service endpoint (e.g., the metadata service at 169.254.169.254 on cloud providers) or an external domain, causing the Flask backend to perform SSRF on behalf of the attacker. Even when CockroachDB is the target, an SSRF vector can allow an attacker to probe internal network segments where CockroachDB nodes are running, bypassing firewall rules that would otherwise restrict direct access.
Moreover, if the application exposes an administrative endpoint that fetches schema or table information dynamically using user-supplied identifiers, an attacker can leverage SSRF to induce the backend to make requests to unauthenticated LLM endpoints or to internal CockroachDB SQL shell interfaces, if such services are reachable from the application host. Because middleBrick tests include SSRF among its 12 parallel security checks, it can identify whether a Flask endpoint can be tricked into making unintended network calls that involve CockroachDB listeners or configuration endpoints.
Cockroachdb-Specific Remediation in Flask — concrete code fixes
Remediation focuses on strict input validation, network segregation, and avoiding dynamic connection string assembly based on user input. When you must allow configuration via HTTP parameters, use allowlists and avoid forwarding user input directly to network destinations.
1) Use a fixed set of allowed hosts and ports for CockroachDB connections. Do not concatenate user input into connection strings.
from flask import Flask, request, abort
import psycopg2
ALLOWED_HOSTS = {'cockroach-node-internal.example.com'}
ALLOWED_PORTS = {26257}
app = Flask(__name__)
def get_safe_connection():
host = request.args.get('host')
port = request.args.get('port', 26257, type=int)
if host not in ALLOWED_HOSTS:
abort(400, 'Host not allowed')
if port not in ALLOWED_PORTS:
abort(400, 'Port not allowed')
conn_str = 'postgresql://[email protected]:26257/mydb'
return psycopg2.connect(conn_str)
@app.route('/query')
def query_db():
conn = get_safe_connection()
cur = conn.cursor()
cur.execute('SELECT 1')
return str(cur.fetchone())
2) Use environment variables or configuration files for connection parameters and keep them out of the request path. This prevents runtime manipulation of network targets.
import os
import psycopg2
from flask import Flask
app = Flask(__name__)
DATABASE_URI = os.getenv('COCKROACH_DATABASE_URI', 'postgresql://root@cockroach-internal:26257/mydb')
@app.route('/query')
def query_db():
conn = psycopg2.connect(DATABASE_URI)
cur = conn.cursor()
cur.execute('SELECT 1')
return str(cur.fetchone())
3) If the application must perform outbound HTTP requests on behalf of the client (e.g., calling a third-party API), isolate the functionality and enforce strict URL allowlists and timeouts. Do not allow arbitrary URLs derived from user input.
import requests
from flask import Flask, request, abort
app = Flask(__name__)
ALLOWED_URLS = {'https://api.example.com/metadata'}
@app.route('/fetch')
def fetch_metadata():
url = request.args.get('url')
if url not in ALLOWED_URLS:
abort(400, 'URL not permitted')
resp = requests.get(url, timeout=5)
resp.raise_for_status()
return resp.text
These practices reduce the attack surface for SSRF and help ensure that CockroachDB connections remain within controlled network boundaries. middleBrick’s dashboard can track your security scores over time, and the CLI allows you to integrate scans into scripts to validate that such mitigations are effective.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |