high

GHSA-cgfv-jrfp-2r7v

Maven · io.openremote:openremote-manager

Summary

OpenRemote has Authenticated SQL Injection via Datapoint Crosstab Export

Severity
high
CWE
CWE-89
Published
2026-07-06
Updated
2026-07-06

Advisory details

Summary

The datapoint export API builds a PostgreSQL crosstab export query by concatenating asset display names into raw SQL. An authenticated user who can create or rename an asset and then request a crosstab datapoint export can inject SQL through the asset name. The injected query output is streamed back to the caller inside the normal ZIP/CSV export response.

This creates a practical database exfiltration primitive through the application API. In a multi-tenant deployment, this can expose data outside the attacker's tenant if the application database role can read shared manager tables.

Affected Component

Security Impact

Impact is high. A remote authenticated attacker with asset read/write capabilities can:

The demonstrated impact is database data exfiltration. The proof of concept safely retrieved database execution context and an aggregate table count. A real attacker could adapt the injected SELECT to read other database tables accessible to the application database role.

This is especially sensitive in multi-tenant deployments because application tables commonly contain data for multiple realms/tenants in the same database.

Attack Preconditions

The attacker needs:

No direct database access is required. No server filesystem access is required. No token forgery is required.

Technical Details

The export implementation derives a crosstab header from the asset name and attribute name. It then embeds that header into two SQL contexts:

  1. A PostgreSQL double-quoted column identifier:
"<asset name> : <attribute name>" text
  1. A category query passed to crosstab(...), wrapped in a fixed dollar-quoted delimiter:
$cat$ SELECT header FROM (VALUES ('<asset name> : <attribute name>')) AS t(header) $cat$

The current escaping is incomplete:

As a result, an attacker-controlled asset name can break out of the intended SQL grammar boundary and append SQL to the generated COPY ... TO STDOUT query. Because the backend streams COPY output into the export response, injected query rows are returned to the attacker as CSV.

Example Exploit Flow

  1. Authenticate normally.
  2. Create or rename an asset using a name containing SQL metacharacters that closes the crosstab column definition.
  3. Ensure the asset has an exportable datapoint attribute.
  4. Write at least one datapoint value for that attribute, if necessary.
  5. Request a CSV crosstab datapoint export for the crafted asset attribute.
  6. Inspect the returned ZIP/CSV. The CSV contains both normal datapoint rows and rows produced by the injected SQL.

A safe proof query demonstrated exfiltration of:

The returned CSV contained a row equivalent to:

<timestamp>,<database_user>:<database_name>:<table_count>

Root Cause

The root cause is manual SQL string construction using user-controlled display data as SQL syntax.

The asset name is treated as presentation data in the application model, but later reused as part of executable SQL:

These contexts require different escaping rules. Applying partial string escaping is error-prone and currently misses exploitable grammar boundaries.

Recommended Fix

Avoid embedding user-controlled asset names directly into executable SQL.

Recommended options:

  1. Do not use asset names as SQL identifiers.

    • Generate deterministic internal column aliases such as c1, c2, c3.
    • Keep the user-facing asset/attribute labels outside SQL and apply them only when serializing CSV headers.
  2. If dynamic identifiers are unavoidable, quote them using a database-aware identifier quoting function.

    • For PostgreSQL identifiers, double embedded " characters.
    • Do not perform ad hoc quoting with string concatenation.
  3. Avoid fixed dollar-quote delimiters around attacker-influenced content.

    • Use prepared statements or server-side functions where possible.
    • If textual SQL must be generated, choose a delimiter that cannot appear in user input or escape/validate before use.
  4. Add a strict validation boundary for display names if the product can tolerate it.

    • This should be defense-in-depth, not the only fix.
    • Reject control characters and SQL-significant delimiter sequences in asset names if they are not required.
  5. Add regression tests for:

    • Asset names containing ".
    • Asset names containing the fixed dollar-quote delimiter.
    • Asset names containing newline/comment syntax.
    • Crosstab exports with multiple assets and attributes.
    • Confirmation that returned CSV never contains injected query output.

Suggested Safe Design

Build the crosstab with internal, non-user-controlled category keys and column names. For example:

This removes asset display names from SQL syntax entirely.

Severity

Suggested severity: High

Rationale:

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.