Added tests and modeling of database-access-result

This commit is contained in:
Napalys Klicius
2025-07-29 16:28:35 +02:00
parent 93d9ae73b7
commit 5b31350e83
7 changed files with 168 additions and 1 deletions

View File

@@ -1,4 +1,4 @@
---
category: minorAnalysis
---
* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages. This enables detection of SQL injection vulnerabilities in DynamoDB PartiQL operations, Athena queries, S3 select expressions, and RDS Data API calls.
* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages.

View File

@@ -19,3 +19,11 @@ extensions:
data:
- ["AthenaClientV3", "@aws-sdk/client-athena", "Member[AthenaClient]"]
- ["AthenaClientV2", "aws-sdk", "Member[Athena]"]
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ["AthenaClientV3", "ReturnValue.Member[send].ReturnValue.Awaited", "database-access-result"]
- ["AthenaClientV2", "ReturnValue.Member[getQueryResults].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"]
- ["AthenaClientV2", "ReturnValue.Member[getQueryResults].Argument[1].Parameter[1]", "database-access-result"]

View File

@@ -18,3 +18,11 @@ extensions:
data:
- ["S3ClientV3", "@aws-sdk/client-s3", "Member[S3Client]"]
- ["S3ClientV2", "aws-sdk", "Member[S3]"]
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ["S3ClientV3", "ReturnValue.Member[send].ReturnValue.Awaited", "database-access-result"]
- ["S3ClientV2", "ReturnValue.Member[getObject].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"]
- ["S3ClientV2", "ReturnValue.Member[getObject].Argument[1].Parameter[1]", "database-access-result"]

View File

@@ -20,3 +20,11 @@ extensions:
data:
- ["DynamoDBClientV3", "@aws-sdk/client-dynamodb", "Member[DynamoDBClient,DynamoDB]"]
- ["DynamoDBClientV2", "aws-sdk", "Member[DynamoDB]"]
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ["DynamoDBClientV3", "ReturnValue.Member[send].ReturnValue.Awaited", "database-access-result"]
- ["DynamoDBClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"]
- ["DynamoDBClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].Argument[1].Parameter[1]", "database-access-result"]

View File

@@ -21,3 +21,11 @@ extensions:
data:
- ["RDSDataClientV3", "@aws-sdk/client-rds-data", "Member[RDSDataClient]"]
- ["RDSDataClientV2", "aws-sdk", "Member[RDSDataService]"]
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ["RDSDataClientV3", "ReturnValue.Member[send].ReturnValue.Awaited", "database-access-result"]
- ["RDSDataClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].ReturnValue.Member[promise].ReturnValue.Awaited", "database-access-result"]
- ["RDSDataClientV2", "ReturnValue.Member[executeStatement,batchExecuteStatement].Argument[1].Parameter[1]", "database-access-result"]

View File

@@ -32,6 +32,34 @@ nodes
| angular-tempate-url.js:13:30:13:31 | ev | semmle.label | ev |
| angular-tempate-url.js:14:26:14:27 | ev | semmle.label | ev |
| angular-tempate-url.js:14:26:14:32 | ev.data | semmle.label | ev.data |
| aws-db.js:15:31:15:37 | results | semmle.label | results |
| aws-db.js:15:31:15:76 | results ... arValue | semmle.label | results ... arValue |
| aws-db.js:20:31:20:38 | response | semmle.label | response |
| aws-db.js:20:31:20:54 | respons ... tring() | semmle.label | respons ... tring() |
| aws-db.js:24:31:24:39 | response2 | semmle.label | response2 |
| aws-db.js:24:31:24:47 | response2.records | semmle.label | response2.records |
| aws-db.js:28:31:28:39 | response3 | semmle.label | response3 |
| aws-db.js:28:31:28:44 | response3.Item | semmle.label | response3.Item |
| aws-db.js:43:31:43:37 | results | semmle.label | results |
| aws-db.js:43:31:43:76 | results ... arValue | semmle.label | results ... arValue |
| aws-db.js:46:35:46:38 | data | semmle.label | data |
| aws-db.js:46:35:46:77 | data.Re ... arValue | semmle.label | data.Re ... arValue |
| aws-db.js:51:31:51:38 | response | semmle.label | response |
| aws-db.js:51:31:51:54 | respons ... tring() | semmle.label | respons ... tring() |
| aws-db.js:54:35:54:38 | data | semmle.label | data |
| aws-db.js:54:35:54:54 | data.Body.toString() | semmle.label | data.Body.toString() |
| aws-db.js:59:31:59:39 | response1 | semmle.label | response1 |
| aws-db.js:59:31:59:47 | response1.records | semmle.label | response1.records |
| aws-db.js:62:35:62:38 | data | semmle.label | data |
| aws-db.js:62:35:62:46 | data.records | semmle.label | data.records |
| aws-db.js:66:31:66:39 | response2 | semmle.label | response2 |
| aws-db.js:66:31:66:53 | respons ... Results | semmle.label | respons ... Results |
| aws-db.js:69:35:69:38 | data | semmle.label | data |
| aws-db.js:69:35:69:52 | data.updateResults | semmle.label | data.updateResults |
| aws-db.js:74:35:74:38 | data | semmle.label | data |
| aws-db.js:74:35:74:43 | data.Item | semmle.label | data.Item |
| aws-db.js:77:35:77:38 | data | semmle.label | data |
| aws-db.js:77:35:77:43 | data.Item | semmle.label | data.Item |
| classnames.js:7:31:7:84 | `<span ... <span>` | semmle.label | `<span ... <span>` |
| classnames.js:7:47:7:69 | classNa ... w.name) | semmle.label | classNa ... w.name) |
| classnames.js:7:58:7:68 | window.name | semmle.label | window.name |
@@ -724,6 +752,20 @@ edges
| angular-tempate-url.js:13:30:13:31 | ev | angular-tempate-url.js:14:26:14:27 | ev | provenance | |
| angular-tempate-url.js:14:26:14:27 | ev | angular-tempate-url.js:14:26:14:32 | ev.data | provenance | |
| angular-tempate-url.js:14:26:14:32 | ev.data | angular-tempate-url.js:9:26:9:45 | Cookie.get("unsafe") | provenance | |
| aws-db.js:15:31:15:37 | results | aws-db.js:15:31:15:76 | results ... arValue | provenance | |
| aws-db.js:20:31:20:38 | response | aws-db.js:20:31:20:54 | respons ... tring() | provenance | |
| aws-db.js:24:31:24:39 | response2 | aws-db.js:24:31:24:47 | response2.records | provenance | |
| aws-db.js:28:31:28:39 | response3 | aws-db.js:28:31:28:44 | response3.Item | provenance | |
| aws-db.js:43:31:43:37 | results | aws-db.js:43:31:43:76 | results ... arValue | provenance | |
| aws-db.js:46:35:46:38 | data | aws-db.js:46:35:46:77 | data.Re ... arValue | provenance | |
| aws-db.js:51:31:51:38 | response | aws-db.js:51:31:51:54 | respons ... tring() | provenance | |
| aws-db.js:54:35:54:38 | data | aws-db.js:54:35:54:54 | data.Body.toString() | provenance | |
| aws-db.js:59:31:59:39 | response1 | aws-db.js:59:31:59:47 | response1.records | provenance | |
| aws-db.js:62:35:62:38 | data | aws-db.js:62:35:62:46 | data.records | provenance | |
| aws-db.js:66:31:66:39 | response2 | aws-db.js:66:31:66:53 | respons ... Results | provenance | |
| aws-db.js:69:35:69:38 | data | aws-db.js:69:35:69:52 | data.updateResults | provenance | |
| aws-db.js:74:35:74:38 | data | aws-db.js:74:35:74:43 | data.Item | provenance | |
| aws-db.js:77:35:77:38 | data | aws-db.js:77:35:77:43 | data.Item | provenance | |
| classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | provenance | |
| classnames.js:7:58:7:68 | window.name | classnames.js:7:47:7:69 | classNa ... w.name) | provenance | |
| classnames.js:8:47:8:70 | classNa ... w.name) | classnames.js:8:31:8:85 | `<span ... <span>` | provenance | |
@@ -1319,6 +1361,20 @@ subpaths
| various-concat-obfuscations.js:21:17:21:46 | documen ... h.attrs | various-concat-obfuscations.js:17:24:17:28 | attrs | various-concat-obfuscations.js:18:10:18:105 | '<div a ... /div>') | various-concat-obfuscations.js:21:4:21:47 | indirec ... .attrs) |
| various-concat-obfuscations.js:21:17:21:46 | documen ... h.attrs | various-concat-obfuscations.js:17:24:17:28 | attrs | various-concat-obfuscations.js:18:10:18:105 | '<div a ... /div>') [ArrayElement] | various-concat-obfuscations.js:21:4:21:47 | indirec ... .attrs) |
#select
| aws-db.js:15:31:15:76 | results ... arValue | aws-db.js:15:31:15:37 | results | aws-db.js:15:31:15:76 | results ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:15:31:15:37 | results | user-provided value |
| aws-db.js:20:31:20:54 | respons ... tring() | aws-db.js:20:31:20:38 | response | aws-db.js:20:31:20:54 | respons ... tring() | Cross-site scripting vulnerability due to $@. | aws-db.js:20:31:20:38 | response | user-provided value |
| aws-db.js:24:31:24:47 | response2.records | aws-db.js:24:31:24:39 | response2 | aws-db.js:24:31:24:47 | response2.records | Cross-site scripting vulnerability due to $@. | aws-db.js:24:31:24:39 | response2 | user-provided value |
| aws-db.js:28:31:28:44 | response3.Item | aws-db.js:28:31:28:39 | response3 | aws-db.js:28:31:28:44 | response3.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:28:31:28:39 | response3 | user-provided value |
| aws-db.js:43:31:43:76 | results ... arValue | aws-db.js:43:31:43:37 | results | aws-db.js:43:31:43:76 | results ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:43:31:43:37 | results | user-provided value |
| aws-db.js:46:35:46:77 | data.Re ... arValue | aws-db.js:46:35:46:38 | data | aws-db.js:46:35:46:77 | data.Re ... arValue | Cross-site scripting vulnerability due to $@. | aws-db.js:46:35:46:38 | data | user-provided value |
| aws-db.js:51:31:51:54 | respons ... tring() | aws-db.js:51:31:51:38 | response | aws-db.js:51:31:51:54 | respons ... tring() | Cross-site scripting vulnerability due to $@. | aws-db.js:51:31:51:38 | response | user-provided value |
| aws-db.js:54:35:54:54 | data.Body.toString() | aws-db.js:54:35:54:38 | data | aws-db.js:54:35:54:54 | data.Body.toString() | Cross-site scripting vulnerability due to $@. | aws-db.js:54:35:54:38 | data | user-provided value |
| aws-db.js:59:31:59:47 | response1.records | aws-db.js:59:31:59:39 | response1 | aws-db.js:59:31:59:47 | response1.records | Cross-site scripting vulnerability due to $@. | aws-db.js:59:31:59:39 | response1 | user-provided value |
| aws-db.js:62:35:62:46 | data.records | aws-db.js:62:35:62:38 | data | aws-db.js:62:35:62:46 | data.records | Cross-site scripting vulnerability due to $@. | aws-db.js:62:35:62:38 | data | user-provided value |
| aws-db.js:66:31:66:53 | respons ... Results | aws-db.js:66:31:66:39 | response2 | aws-db.js:66:31:66:53 | respons ... Results | Cross-site scripting vulnerability due to $@. | aws-db.js:66:31:66:39 | response2 | user-provided value |
| aws-db.js:69:35:69:52 | data.updateResults | aws-db.js:69:35:69:38 | data | aws-db.js:69:35:69:52 | data.updateResults | Cross-site scripting vulnerability due to $@. | aws-db.js:69:35:69:38 | data | user-provided value |
| aws-db.js:74:35:74:43 | data.Item | aws-db.js:74:35:74:38 | data | aws-db.js:74:35:74:43 | data.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:74:35:74:38 | data | user-provided value |
| aws-db.js:77:35:77:43 | data.Item | aws-db.js:77:35:77:38 | data | aws-db.js:77:35:77:43 | data.Item | Cross-site scripting vulnerability due to $@. | aws-db.js:77:35:77:38 | data | user-provided value |
| hana.js:11:37:11:51 | rows[0].comment | hana.js:11:37:11:40 | rows | hana.js:11:37:11:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:11:37:11:40 | rows | user-provided value |
| hana.js:16:37:16:51 | rows[0].comment | hana.js:16:37:16:40 | rows | hana.js:16:37:16:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:16:37:16:40 | rows | user-provided value |
| hana.js:19:37:19:51 | rows[0].comment | hana.js:19:37:19:40 | rows | hana.js:19:37:19:51 | rows[0].comment | Cross-site scripting vulnerability due to $@. | hana.js:19:37:19:40 | rows | user-provided value |

View File

@@ -0,0 +1,79 @@
const { AthenaClient, GetQueryResultsCommand } = require('@aws-sdk/client-athena');
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const { RDSDataClient, ExecuteStatementCommand } = require("@aws-sdk/client-rds-data");
const { DynamoDBClient, GetItemCommand } = require("@aws-sdk/client-dynamodb");
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/v3/all', async (req, res) => {
const client = new AthenaClient({ region: "us-east-1" });
const results = await client.send(new GetQueryResultsCommand({ QueryExecutionId }));
document.body.innerHTML = results.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test]
const s3 = new S3Client({ region: "us-east-1" });
const command = new GetObjectCommand({ Bucket: bucket, Key: key });
const response = await s3.send(command);
document.body.innerHTML = response.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test]
const clientRDS = new RDSDataClient({ region: "us-east-1" });
const response2 = await clientRDS.send(new ExecuteStatementCommand(command));
document.body.innerHTML = response2.records; // $ Alert[js/xss-additional-sources-dom-test]
const clientDyamo = new DynamoDBClient({ region: "us-east-1" });
const response3 = await clientDyamo.send(new GetItemCommand(command));
document.body.innerHTML = response3.Item; // $ Alert[js/xss-additional-sources-dom-test]
});
app.post('/v2/all', async (req, res) => {
const AWS = require('aws-sdk');
const athena = new AWS.Athena();
const params = {
QueryString: 'SELECT * FROM my_table',
ResultConfiguration: { OutputLocation: 's3://bucket/prefix/' }
};
const { QueryExecutionId } = await athena.startQueryExecution(params).promise();
const results = await athena.getQueryResults({ QueryExecutionId }).promise();
document.body.innerHTML = results.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test]
athena.getQueryResults({ QueryExecutionId }, (err, data) => {
document.body.innerHTML = data.ResultSet.Rows[0].Data[0].VarCharValue; // $ Alert[js/xss-additional-sources-dom-test]
});
const s3 = new AWS.S3({ region: "us-east-1" });
const response = await s3.getObject({ Bucket: "bucket", Key: "key" }).promise();
document.body.innerHTML = response.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test]
s3.getObject({ Bucket: "bucket", Key: "key" }, (err, data) => {
document.body.innerHTML = data.Body.toString(); // $ Alert[js/xss-additional-sources-dom-test]
});
const rdsData = new AWS.RDSDataService({ region: "us-east-1" });
const response1 = await rdsData.executeStatement(params).promise();
document.body.innerHTML = response1.records; // $ Alert[js/xss-additional-sources-dom-test]
rdsData.executeStatement(params, function(err, data) {
document.body.innerHTML = data.records; // $ Alert[js/xss-additional-sources-dom-test]
});
const response2 = await rdsData.batchExecuteStatement(params).promise();
document.body.innerHTML = response2.updateResults; // $ Alert[js/xss-additional-sources-dom-test]
rdsData.batchExecuteStatement(params, function(err, data) {
document.body.innerHTML = data.updateResults; // $ Alert[js/xss-additional-sources-dom-test]
});
const dynamodb = new AWS.DynamoDB({ region: "us-east-1" });
dynamodb.executeStatement(params, (err, data) => {
document.body.innerHTML = data.Item; // $ Alert[js/xss-additional-sources-dom-test]
});
dynamodb.executeStatement(params).promise().then(data => {
document.body.innerHTML = data.Item; // $ Alert[js/xss-additional-sources-dom-test]
});
});