Added modeling of athena v2 and v3 for sql injections

This commit is contained in:
Napalys Klicius
2025-07-29 13:45:11 +02:00
parent af97b0edc2
commit 0e6bac73a7
3 changed files with 99 additions and 39 deletions

View File

@@ -0,0 +1,21 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: sinkModel
data:
- ["AthenaClientV3", "ReturnValue.Member[send].Argument[0]", "sql-injection"]
- ["AthenaClientV2", "ReturnValue.Member[startQueryExecution,createNamedQuery,updateNamedQuery].Argument[0].Member[QueryString]", "sql-injection"]
- addsTo:
pack: codeql/javascript-all
extensible: summaryModel
data:
- ["@aws-sdk/client-athena", "Member[StartQueryExecutionCommand,CreateNamedQueryCommand,UpdateNamedQueryCommand]", "Argument[0].Member[QueryString]", "ReturnValue", "taint"]
- addsTo:
pack: codeql/javascript-all
extensible: typeModel
data:
- ["AthenaClientV3", "@aws-sdk/client-athena", "Member[AthenaClient]"]
- ["AthenaClientV2", "aws-sdk", "Member[Athena]"]

View File

@@ -1,4 +1,10 @@
#select
| athena.js:19:23:19:23 | p | athena.js:9:23:9:30 | req.body | athena.js:19:23:19:23 | p | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value |
| athena.js:27:23:27:58 | new Cre ... arams2) | athena.js:9:23:9:30 | req.body | athena.js:27:23:27:58 | new Cre ... arams2) | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value |
| athena.js:36:23:36:58 | new Upd ... arams3) | athena.js:9:23:9:30 | req.body | athena.js:36:23:36:58 | new Upd ... arams3) | This query string depends on a $@. | athena.js:9:23:9:30 | req.body | user-provided value |
| athena.js:48:22:48:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:48:22:48:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value |
| athena.js:57:22:57:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:57:22:57:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value |
| athena.js:66:22:66:30 | userQuery | athena.js:43:23:43:30 | req.body | athena.js:66:22:66:30 | userQuery | This query string depends on a $@. | athena.js:43:23:43:30 | req.body | user-provided value |
| clients3.js:18:23:18:60 | new Sel ... params) | clients3.js:10:26:10:33 | req.body | clients3.js:18:23:18:60 | new Sel ... params) | This query string depends on a $@. | clients3.js:10:26:10:33 | req.body | user-provided value |
| clients3.js:29:21:29:68 | "SELECT ... usInput | clients3.js:23:26:23:33 | req.body | clients3.js:29:21:29:68 | "SELECT ... usInput | This query string depends on a $@. | clients3.js:23:26:23:33 | req.body | user-provided value |
| clients3.js:38:21:38:68 | "SELECT ... usInput | clients3.js:23:26:23:33 | req.body | clients3.js:38:21:38:68 | "SELECT ... usInput | This query string depends on a $@. | clients3.js:23:26:23:33 | req.body | user-provided value |
@@ -146,7 +152,41 @@
| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query string depends on a $@. | tst4.js:8:46:8:60 | $routeParams.id | user-provided value |
| tst.js:10:10:10:64 | 'SELECT ... d + '"' | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query string depends on a $@. | tst.js:10:46:10:58 | req.params.id | user-provided value |
edges
<<<<<<< HEAD
| athena.js:9:11:9:19 | userQuery | athena.js:14:30:14:38 | userQuery | provenance | |
| athena.js:9:11:9:19 | userQuery | athena.js:24:22:24:30 | userQuery | provenance | |
| athena.js:9:11:9:19 | userQuery | athena.js:33:22:33:30 | userQuery | provenance | |
| athena.js:9:23:9:30 | req.body | athena.js:9:11:9:19 | userQuery | provenance | |
| athena.js:13:11:13:17 | params1 [QueryString] | athena.js:18:46:18:52 | params1 [QueryString] | provenance | |
| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | athena.js:13:11:13:17 | params1 [QueryString] | provenance | |
| athena.js:14:22:14:38 | "SQL" + userQuery | athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | provenance | |
| athena.js:14:30:14:38 | userQuery | athena.js:14:22:14:38 | "SQL" + userQuery | provenance | |
| athena.js:18:11:18:11 | p | athena.js:19:23:19:23 | p | provenance | |
| athena.js:18:15:18:53 | new Sta ... arams1) | athena.js:18:11:18:11 | p | provenance | |
| athena.js:18:46:18:52 | params1 [QueryString] | athena.js:18:15:18:53 | new Sta ... arams1) | provenance | |
| athena.js:21:11:21:17 | params2 [QueryString] | athena.js:27:51:27:57 | params2 [QueryString] | provenance | |
| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | athena.js:21:11:21:17 | params2 [QueryString] | provenance | |
| athena.js:24:22:24:30 | userQuery | athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | provenance | |
| athena.js:27:51:27:57 | params2 [QueryString] | athena.js:27:23:27:58 | new Cre ... arams2) | provenance | |
| athena.js:29:11:29:17 | params3 [QueryString] | athena.js:36:51:36:57 | params3 [QueryString] | provenance | |
| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | athena.js:29:11:29:17 | params3 [QueryString] | provenance | |
| athena.js:33:22:33:30 | userQuery | athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | provenance | |
| athena.js:36:51:36:57 | params3 [QueryString] | athena.js:36:23:36:58 | new Upd ... arams3) | provenance | |
| athena.js:43:11:43:19 | userQuery | athena.js:48:22:48:30 | userQuery | provenance | |
| athena.js:43:11:43:19 | userQuery | athena.js:57:22:57:30 | userQuery | provenance | |
| athena.js:43:11:43:19 | userQuery | athena.js:66:22:66:30 | userQuery | provenance | |
| athena.js:43:23:43:30 | req.body | athena.js:43:11:43:19 | userQuery | provenance | |
| clients3.js:10:9:10:22 | maliciousInput | clients3.js:16:55:16:68 | maliciousInput | provenance | |
| clients3.js:10:26:10:33 | req.body | clients3.js:10:9:10:22 | maliciousInput | provenance | |
| clients3.js:12:11:12:16 | params [Expression] | clients3.js:18:54:18:59 | params [Expression] | provenance | |
| clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | clients3.js:12:11:12:16 | params [Expression] | provenance | |
| clients3.js:16:21:16:68 | "SELECT ... usInput | clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | provenance | |
| clients3.js:16:55:16:68 | maliciousInput | clients3.js:16:21:16:68 | "SELECT ... usInput | provenance | |
| clients3.js:18:54:18:59 | params [Expression] | clients3.js:18:23:18:60 | new Sel ... params) | provenance | |
| clients3.js:23:9:23:22 | maliciousInput | clients3.js:29:55:29:68 | maliciousInput | provenance | |
| clients3.js:23:9:23:22 | maliciousInput | clients3.js:38:55:38:68 | maliciousInput | provenance | |
| clients3.js:23:26:23:33 | req.body | clients3.js:23:9:23:22 | maliciousInput | provenance | |
| clients3.js:29:55:29:68 | maliciousInput | clients3.js:29:21:29:68 | "SELECT ... usInput | provenance | |
| clients3.js:38:55:38:68 | maliciousInput | clients3.js:38:21:38:68 | "SELECT ... usInput | provenance | |
| dynamodb.js:9:9:9:22 | maliciousInput | dynamodb.js:11:64:11:77 | maliciousInput | provenance | |
| dynamodb.js:9:9:9:22 | maliciousInput | dynamodb.js:17:80:17:93 | maliciousInput | provenance | |
| dynamodb.js:9:26:9:33 | req.body | dynamodb.js:9:9:9:22 | maliciousInput | provenance | |
@@ -155,28 +195,6 @@ edges
| dynamodb.js:12:11:12:17 | command | dynamodb.js:15:23:15:29 | command | provenance | |
| dynamodb.js:12:11:12:17 | command | dynamodb.js:47:24:47:30 | command | provenance | |
| dynamodb.js:12:21:14:6 | new Exe ... \\n }) | dynamodb.js:12:11:12:17 | command | provenance | |
=======
| clients3.js:10:9:10:40 | maliciousInput | clients3.js:16:55:16:68 | maliciousInput | provenance | |
| clients3.js:10:26:10:33 | req.body | clients3.js:10:9:10:40 | maliciousInput | provenance | |
| clients3.js:12:11:17:5 | params [Expression] | clients3.js:18:54:18:59 | params [Expression] | provenance | |
| clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | clients3.js:12:11:17:5 | params [Expression] | provenance | |
| clients3.js:16:21:16:68 | "SELECT ... usInput | clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | provenance | |
| clients3.js:16:55:16:68 | maliciousInput | clients3.js:16:21:16:68 | "SELECT ... usInput | provenance | |
| clients3.js:18:54:18:59 | params [Expression] | clients3.js:18:23:18:60 | new Sel ... params) | provenance | |
| clients3.js:23:9:23:40 | maliciousInput | clients3.js:29:55:29:68 | maliciousInput | provenance | |
| clients3.js:23:9:23:40 | maliciousInput | clients3.js:38:55:38:68 | maliciousInput | provenance | |
| clients3.js:23:26:23:33 | req.body | clients3.js:23:9:23:40 | maliciousInput | provenance | |
| clients3.js:29:55:29:68 | maliciousInput | clients3.js:29:21:29:68 | "SELECT ... usInput | provenance | |
| clients3.js:38:55:38:68 | maliciousInput | clients3.js:38:21:38:68 | "SELECT ... usInput | provenance | |
| dynamodb.js:9:9:9:38 | maliciousInput | dynamodb.js:11:64:11:77 | maliciousInput | provenance | |
| dynamodb.js:9:9:9:38 | maliciousInput | dynamodb.js:17:80:17:93 | maliciousInput | provenance | |
| dynamodb.js:9:26:9:33 | req.body | dynamodb.js:9:9:9:38 | maliciousInput | provenance | |
| dynamodb.js:11:11:11:80 | statement | dynamodb.js:13:20:13:28 | statement | provenance | |
| dynamodb.js:11:64:11:77 | maliciousInput | dynamodb.js:11:11:11:80 | statement | provenance | |
| dynamodb.js:12:11:14:6 | command | dynamodb.js:15:23:15:29 | command | provenance | |
| dynamodb.js:12:11:14:6 | command | dynamodb.js:47:24:47:30 | command | provenance | |
| dynamodb.js:12:21:14:6 | new Exe ... \\n }) | dynamodb.js:12:11:14:6 | command | provenance | |
>>>>>>> 1af289cd7d4 (Added modeling of client-s3 v2 and v3)
| dynamodb.js:12:49:14:5 | {\\n ... t\\n } [Statement] | dynamodb.js:12:21:14:6 | new Exe ... \\n }) | provenance | |
| dynamodb.js:13:20:13:28 | statement | dynamodb.js:12:49:14:5 | {\\n ... t\\n } [Statement] | provenance | |
| dynamodb.js:17:11:17:25 | updateStatement | dynamodb.js:19:20:19:34 | updateStatement | provenance | |
@@ -573,25 +591,46 @@ edges
| tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | provenance | |
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | provenance | |
nodes
<<<<<<< HEAD
| dynamodb.js:9:9:9:22 | maliciousInput | semmle.label | maliciousInput |
=======
| clients3.js:10:9:10:40 | maliciousInput | semmle.label | maliciousInput |
| athena.js:9:11:9:19 | userQuery | semmle.label | userQuery |
| athena.js:9:23:9:30 | req.body | semmle.label | req.body |
| athena.js:13:11:13:17 | params1 [QueryString] | semmle.label | params1 [QueryString] |
| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | semmle.label | {\\n ... }\\n } [QueryString] |
| athena.js:14:22:14:38 | "SQL" + userQuery | semmle.label | "SQL" + userQuery |
| athena.js:14:30:14:38 | userQuery | semmle.label | userQuery |
| athena.js:18:11:18:11 | p | semmle.label | p |
| athena.js:18:15:18:53 | new Sta ... arams1) | semmle.label | new Sta ... arams1) |
| athena.js:18:46:18:52 | params1 [QueryString] | semmle.label | params1 [QueryString] |
| athena.js:19:23:19:23 | p | semmle.label | p |
| athena.js:21:11:21:17 | params2 [QueryString] | semmle.label | params2 [QueryString] |
| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] |
| athena.js:24:22:24:30 | userQuery | semmle.label | userQuery |
| athena.js:27:23:27:58 | new Cre ... arams2) | semmle.label | new Cre ... arams2) |
| athena.js:27:51:27:57 | params2 [QueryString] | semmle.label | params2 [QueryString] |
| athena.js:29:11:29:17 | params3 [QueryString] | semmle.label | params3 [QueryString] |
| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] |
| athena.js:33:22:33:30 | userQuery | semmle.label | userQuery |
| athena.js:36:23:36:58 | new Upd ... arams3) | semmle.label | new Upd ... arams3) |
| athena.js:36:51:36:57 | params3 [QueryString] | semmle.label | params3 [QueryString] |
| athena.js:43:11:43:19 | userQuery | semmle.label | userQuery |
| athena.js:43:23:43:30 | req.body | semmle.label | req.body |
| athena.js:48:22:48:30 | userQuery | semmle.label | userQuery |
| athena.js:57:22:57:30 | userQuery | semmle.label | userQuery |
| athena.js:66:22:66:30 | userQuery | semmle.label | userQuery |
| clients3.js:10:9:10:22 | maliciousInput | semmle.label | maliciousInput |
| clients3.js:10:26:10:33 | req.body | semmle.label | req.body |
| clients3.js:12:11:17:5 | params [Expression] | semmle.label | params [Expression] |
| clients3.js:12:11:12:16 | params [Expression] | semmle.label | params [Expression] |
| clients3.js:12:20:17:5 | {\\n ... ,\\n } [Expression] | semmle.label | {\\n ... ,\\n } [Expression] |
| clients3.js:16:21:16:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput |
| clients3.js:16:55:16:68 | maliciousInput | semmle.label | maliciousInput |
| clients3.js:18:23:18:60 | new Sel ... params) | semmle.label | new Sel ... params) |
| clients3.js:18:54:18:59 | params [Expression] | semmle.label | params [Expression] |
| clients3.js:23:9:23:40 | maliciousInput | semmle.label | maliciousInput |
| clients3.js:23:9:23:22 | maliciousInput | semmle.label | maliciousInput |
| clients3.js:23:26:23:33 | req.body | semmle.label | req.body |
| clients3.js:29:21:29:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput |
| clients3.js:29:55:29:68 | maliciousInput | semmle.label | maliciousInput |
| clients3.js:38:21:38:68 | "SELECT ... usInput | semmle.label | "SELECT ... usInput |
| clients3.js:38:55:38:68 | maliciousInput | semmle.label | maliciousInput |
| dynamodb.js:9:9:9:38 | maliciousInput | semmle.label | maliciousInput |
>>>>>>> 1af289cd7d4 (Added modeling of client-s3 v2 and v3)
| dynamodb.js:9:9:9:22 | maliciousInput | semmle.label | maliciousInput |
| dynamodb.js:9:26:9:33 | req.body | semmle.label | req.body |
| dynamodb.js:11:11:11:19 | statement | semmle.label | statement |
| dynamodb.js:11:64:11:77 | maliciousInput | semmle.label | maliciousInput |

View File

@@ -6,7 +6,7 @@ const app = express();
app.use(bodyParser.json());
app.post('/v3/athena/all', async (req, res) => {
const userQuery = req.body.query; // $ MISSING: Source
const userQuery = req.body.query; // $ Source
const client = new AthenaClient({ region: "us-east-1" });
@@ -16,7 +16,7 @@ app.post('/v3/athena/all', async (req, res) => {
ResultConfiguration: { OutputLocation: "s3://my-results/" }
};
const p = new StartQueryExecutionCommand(params1);
await client.send(p); // $ MISSING: Alert
await client.send(p); // $ Alert
const params2 = {
Name: "user_query",
@@ -24,7 +24,7 @@ app.post('/v3/athena/all', async (req, res) => {
QueryString: userQuery,
Description: "User-provided query"
};
await client.send(new CreateNamedQueryCommand(params2)); // $ MISSING: Alert -- This only stores query to database, not executed
await client.send(new CreateNamedQueryCommand(params2)); // $ Alert -- This only stores query to database, not executed
const params3 = {
NamedQueryId: "namedQueryId",
@@ -33,19 +33,19 @@ app.post('/v3/athena/all', async (req, res) => {
QueryString: userQuery,
Description: "Updated user-provided query"
};
await client.send(new UpdateNamedQueryCommand(params3)); // $ MISSING: Alert -- This only stores query to database, not executed
await client.send(new UpdateNamedQueryCommand(params3)); // $ Alert -- This only stores query to database, not executed
res.end();
});
app.post('/v2/athena/all', async (req, res) => {
const userQuery = req.body.query; // $ MISSING: Source
const userQuery = req.body.query; // $ Source
const athena = new AWS.Athena({ region: "us-east-1" });
const params1 = {
QueryString: userQuery, // $ MISSING: Alert
QueryString: userQuery, // $ Alert
QueryExecutionContext: { Database: "default" },
ResultConfiguration: { OutputLocation: "s3://my-results/" }
};
@@ -54,7 +54,7 @@ app.post('/v2/athena/all', async (req, res) => {
const params2 = {
Name: "user_query",
Database: "default",
QueryString: userQuery, // $ MISSING: Alert -- This only stores query to database, not executed
QueryString: userQuery, // $ Alert -- This only stores query to database, not executed
Description: "User-provided query"
};
await athena.createNamedQuery(params2).promise();
@@ -63,7 +63,7 @@ app.post('/v2/athena/all', async (req, res) => {
NamedQueryId: "namedQueryId",
Name: "user_query_updated",
Database: "default",
QueryString: userQuery, // $ MISSING: Alert -- This only stores query to database, not executed
QueryString: userQuery, // $ Alert -- This only stores query to database, not executed
Description: "Updated user-provided query"
};
await athena.updateNamedQuery(params3).promise();