Jul 13, 2026·5 min read·24 visits
An authenticated user with low privileges can perform blind SQL injection and unauthorized administrative tasks in the DIRAC framework due to unsanitized input formatting and overly permissive default access controls.
The DIRAC PilotManager component contains combined security weaknesses: a SQL injection vulnerability (CWE-89) in the PilotAgentsDB database interaction layer, and an improper access control configuration (CWE-284) within the default authorization structure. A low-privilege authenticated attacker can bypass intended authorization checks to run administrative commands, manipulate grid job tracking records, and execute arbitrary SQL statements against the backend database.
The DIRAC (Distributed Infrastructure with Remote Agent Control) software framework manages computing jobs and infrastructure components across distributed cloud and grid systems. Within the DIRAC Workload Management System (WMS), the PilotManager component acts as a core service for handling active pilot agents, which are responsible for launching jobs on remote nodes. The execution path is vulnerable to unauthorized remote modification due to structural weaknesses in both its access control limits and query assembly interfaces.
This vulnerability consists of an authorization bypass (CWE-284) coupled with a SQL injection flaw (CWE-89). Under standard deployments, the default communication handler exposes endpoints to modify grid metadata, alter database fields, and inspect execution diagnostics. Because the system's access configurations are excessively broad by default, the attack surface of the internal administrative handlers is exposed directly to any valid user holding authenticated status.
Once an authenticated session is established, an attacker can construct specially crafted payloads within procedural remote parameters. These values feed into the SQL construction interface of the workload tracking database. The resulting chain allows standard users to compromise metadata confidentiality, disrupt active computational pipelines, and execute arbitrary command syntax within the storage backend.
The SQL injection vulnerability originates in src/DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py within the setPilotStatus method. When pilot properties require updates, variables are aggregated and structured dynamically. Rather than utilizing parameterized bindings or parameterized SQL statements, the application constructs the raw database update statements directly by formatting raw strings using dynamic Python f-string operators.
Several parameter values, such as statusReason, gridSite, and queue, are converted directly to query components via string interpolation (e.g., setList.append(f"StatusReason='{statusReason}'")). These components are then combined with the dynamic target identifier to compose the complete execution string: req = f"UPDATE PilotAgents SET {set_string} WHERE PilotJobReference='{pilotRef}'". Because the class uses raw dynamic strings and executes them through standard database update procedures without structural containment, any single quote delimiter breaks out of the expected execution context.
Simultaneously, the improper authorization boundary resides inside the global configuration registry template at src/DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg. Under the default configurations of the PilotManager daemon, the configuration block contains the parameter definition Default = authenticated. This definition permits any caller possessing a valid transport-layer security (TLS) user certificate to issue remote execution calls to endpoints exposed by PilotManagerHandler.py, bypassing the expected administrative authorization checks.
An analysis of the vulnerable version of the source code highlights the absence of parameter escaping and input parsing. Below is the vulnerable segment of the setPilotStatus routine within PilotAgentsDB.py:
# Affected File: src/DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py
def setPilotStatus(self, pilotRef, status, ...):
setList = []
setList.append(f"Status='{status}'")
# ...
if not statusReason:
statusReason = "Not given"
setList.append(f"StatusReason='{statusReason}'") # Direct dynamic interpolation
# ...
set_string = ",".join(setList)
req = f"UPDATE PilotAgents SET {set_string} WHERE PilotJobReference='{pilotRef}'"
return self._update(req, conn=conn) # Executed without parameterized argumentsThe corresponding patch addresses this by migrating from dynamic format string updates to structured binding. The updated execution logic abstracts inputs by generating a list of positional formatting markers (%s) and feeding the unsanitized parameter values separately into the database adapter:
# Patched File: src/DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py
def setPilotStatus(self, pilotRef, status, ...):
setList = []
args = []
setList.append("Status=%s")
args.append(status)
# ...
if not statusReason:
statusReason = "Not given"
setList.append("StatusReason=%s") # Placeholder replaces literal parameter interpolation
args.append(statusReason)
# ...
set_string = ",".join(setList)
req = f"UPDATE PilotAgents SET {set_string} WHERE PilotJobReference=%s"
args.append(pilotRef)
return self._update(req, args=args, conn=conn) # Safe execution via parameterized bindingIn addition to database execution changes, the configuration registry must be updated to raise default authorization barriers. The system moves from a single broad default definition to distinct, granular, role-based definitions:
# Configuration change in src/DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg
PilotManager
{
Port = 9171
Authorization
{
- Default = authenticated
+ Default = Operator
+ setPilotStatus = Operator
+ setPilotStatus += Pilot
+ setPilotStatus += GenericPilot
}
}Exploitation of the vulnerability involves a two-phase attack sequence. First, the attacker connects to the DIRAC network port (typically port 9171 or the integrated Tornado HTTPS gate) using a basic authenticated TLS grid certificate. Because the default configuration designates Default = authenticated for the PilotManager service, the request is permitted by the interface logic, and the user is granted access to the exposed API methods.
Second, the attacker triggers the SQL injection flaw by executing the RPC API routine setPilotStatus. By inputting a crafted string payload into arguments such as statusReason, the attacker alters the structured execution flow of the SQL driver.
For example, setting the statusReason argument to "Injected', BenchMark=SLEEP(10) WHERE PilotJobReference='target-job" results in the generation of a dual-conditional SQL instruction. The database engine executes the command and triggers the SLEEP(10) instruction, confirming the vulnerability through a blind, time-based side channel.
The security implications of this chained vulnerability are substantial. An authenticated attacker can disrupt grid operations by manipulating active pilot jobs. By modifying job entries in the PilotAgents database, attackers can change job tracking workflows, terminate scheduled workload processes, or misroute remote computing operations.
Furthermore, because the SQL injection is executed within the context of the underlying database instance, attackers can run arbitrary SQL commands to read or modify other database tables. This allows for the extraction of cryptographic hashes, administrative details, and grid system credentials.
While this vulnerability does not allow direct shell commands on the server host, the ability to control database tables can lead to privilege escalation within the DIRAC application framework. The lack of proper input validation and authorization checks results in a CVSS v3.1 score of 8.5.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
DIRAC DIRACGrid | >= 6, < 8.0.79 | 8.0.79 |
DIRAC DIRACGrid | >= 8.1.0a1, < 9.0.22 | 9.0.22 |
DIRAC DIRACGrid | >= 9.1.0, < 9.1.10 | 9.1.10 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-89 (SQL Injection), CWE-284 (Improper Access Control) |
| Attack Vector | Network |
| CVSS v3.1 Score | 8.5 (High) |
| Exploit Status | none |
| KEV Status | Not Listed |
The software constructs an SQL command using input from an upstream component, but fails to neutralize or incorrectly neutralizes elements that can modify the SQL command.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.