Coordinated Disclosure Timeline
- 2023-06-30: Reported the vulnerability via private vulnerability reporting feature on GitHub.
- 2023-07-24: Sent a message in PVR asking the maintainers if they’ve had time to review the report.
- 2023-08-04: Sent an email to the address from the security policy. Received a response immediately.
- 2023-09-11: Sent a reminder about GitHub Security Lab’s disclosure dates and process.
- 2023-09-12: Received a question about the disclosure process in the PVR report and answered it.
- 2023-09-15: Asked the maintainers to publish an advisory.
- 2023-09-25: Sent a final reminder about the disclosure date and requested that the maintainers publish the advisory.
- 2023-09-29: The maintainer requests a CVE.
- 2023-10-11: Asked the maintainer to publish the advisory.
- 2023-10-16: Sent a follow up email that GitHub Security Lab will be publishing the advisory on our website and if the maintainer would like to publish at the same time.
- 2023-10-17: Advisory published by the maintainer: GHSA-3m5q-q39v-xf8f.
Summary
Nocodb contains SQL injection vulnerability, that allows an authenticated attacker with creator access to query the underlying database.
Product
nocodb/nocodb
Tested Version
Details
SQL injection in SqliteClient.ts
(GHSL-2023-141
)
By supplying a specially crafted payload to the given below parameter and endpoint, an attacker can inject arbitrary SQL queries to be executed. Since this is a blind SQL injections, an attacker may need to use time-based payloads which would include a function to delay execution for a given number of seconds. The response time indicates, whether the result of the query execution was true or false. Depending on the result, the HTTP response will be returned after a given number of seconds, indicating TRUE, or immediately, indicating FALSE. In that way, an attacker can reveal the data present in the database.
The triggerList
method creates a SQL query using the user-controlled table_name
parameter value from the tableCreate
endpoint.
async triggerList(args: any = {}) {
const _func = this.triggerList.name;
const result = new Result();
log.api(`${_func}:args:`, args);
try {
args.databaseName = this.connectionConfig.connection.database;
const response = await this.sqlClient.raw(
`select *, name as trigger_name from sqlite_master where type = 'trigger' and tbl_name='${args.tn}';`,
);
[...]
This issue was found with the CodeQL query SQL query built from user-controlled sources.
Proof of concept
This proof of concept requires creator-level access.
Use an HTTP proxy, such as Burp Suite, to be able to capture projectId
and baseId
values.
- In Nocodb, Create a new database and a table. That action triggers a POST request to
/api/v1/db/meta/projects/:projectId/:baseId/tables
. - Copy the POST request with valid cookies and
projectId
andbaseId
values to/api/v1/db/meta/projects/:projectId/:baseId/tables
. - Change the value of the
table_name
value tofoo' OR UPPER(HEX(RANDOMBLOB(100000000/2))) -- /**/
and send the request.
The payload will cause the database to wait around 30 seconds, depending on the hardware the database is running on, indicating the payload is executed.
For more information about testing applications for SQL injection see OWASP Web Security Testing Guide - Testing for SQL injection.
Impact
This issue may lead to Information Disclosure
.
CVE
- CVE-2023-43794
Credit
This issue was discovered and reported by GHSL team member @sylwia-budzynska (Sylwia Budzynska).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-141
in any communication regarding this issue.