Skip to content

RCE via SQL Injection in Excel Upload Endpoint

High
xuwei-fit2cloud published GHSA-7hww-8rj5-7rmm Mar 19, 2026

Package

No package listed

Affected versions

<1.7.0

Patched versions

1.7.0

Description

Impact

- Description
SQLBot contains a critical SQL Injection vulnerability in the /api/v1/datasource/uploadExcel endpoint's Excel file processing logic. An attacker can upload a specially crafted Excel file with a malicious Sheet name to inject arbitrary SQL fragments, ultimately achieving Remote Code Execution (RCE) on the server.

The core weakness lies in two pieces of code in the backend:

Flaw 1: Table name directly concatenates Sheet name (no sanitization)
backend/apps/datasource/api/datasource.py#L351:

image

This line directly concatenates the Excel Sheet name (sheet_name) with an underscore _ and a 10-character random hash to form the PostgreSQL table name, without any special character filtering on the Sheet name. For example, when an attacker sets the Sheet name to a malicious SQL fragment like chat"FROM PROGRAM'id>/tmp/x'--, the generated tableName becomes:

chat"FROM PROGRAM'id>/tmp/x'--_e1049707f4

Flaw 2: Table name embedded directly into COPY SQL statement (SQL Injection)
backend/apps/datasource/api/datasource.py#L385-L388:

image

This code uses a Python f-string to embed the above tableName directly into the COPY SQL statement's double-quoted identifier, without using parameterized queries.
Since a double quote " in the Sheet name can close the SQL identifier quoting, an attacker can inject a TO PROGRAM 'command' clause into the Sheet name, causing PostgreSQL to pipe query results into an operating system shell for execution.

Although the Excel specification limits Sheet names to a maximum of 31 characters, an attacker can bypass this limitation through a two-stage injection technique to achieve arbitrary-length command execution:

  1. Stage 1 (Payload Staging): Upload a normal Excel file with Sheet name s. Its data rows contain complete shell script commands. The backend, following the logic at line 351, constructs the table name as s_<10-char-random-hash> (e.g., s_0425a81fc8) and stores the Excel data into that table. The full table name is returned in the HTTP response.
  2. Stage 2 (Trigger): Upload an XML-tampered Excel file (bypassing the Excel library's Sheet name character validation) with the Sheet name set to s_0425a81fc8"TO PROGRAM'sh'-- (only 29 characters). After backend concatenation, the resulting SQL is:
    COPY "s_0425a81fc8"TO PROGRAM'sh'--_<new_hash>" FROM STDIN WITH CSV DELIMITER E'\t'
    -- PostgreSQL actually parses this as:
    COPY "s_0425a81fc8" TO PROGRAM 'sh'   (everything after -- is a comment, ignored)
    When PostgreSQL executes this statement, it pipes every row of the s_0425a81fc8 table data line-by-line into the sh process for execution, achieving arbitrary-length command execution.

- Impact
This vulnerability allows any authenticated user (including the lowest-privileged regular user) to directly take over the SQLBot backend server. Confirmed material impacts include:

  1. Remote Code Execution (RCE): Execute arbitrary system commands with postgres (uid=999) user privileges, including reverse shells.
  2. Sensitive File Exfiltration: Read /etc/passwd, /etc/shadow, application configuration files, and other sensitive data from the server.
  3. Complete Database Takeover: Since the exploit runs under the postgres user, the attacker gains full control over the entire PostgreSQL database.

POC

- Prerequisites

  1. The target server hosts an accessible SQLBot network service.
  2. A valid regular user account (administrator privileges are NOT required). Many internet-facing targets use default public credentials: admin/SQLBot@123456 , resulting in a very large attack surface.

- Steps to Reproduce

  1. Execute the Exploit Script

Launch the attack against the target using the PoC script:

python3 poc.py http://target:port/ -u test -p SQLBot@123456 "id > /tmp/pwned"
image

Verify command execution results:

image
  1. Demonstrate Reverse Shell
image

Affected versions
<= v1.6.0

Patches

The vulnerability has been fixed in v1.7.0.

Workarounds

It is recommended to upgrade the version to v1.7.0.

References

If you have any questions or comments about this advisory:

Open an issue in https://github.com/dataease/sqlbot
Email us at wei@fit2cloud.com

Severity

High

CVE ID

CVE-2026-32950

Weaknesses

No CWEs

Credits