Skip to content

Commit 238568d

Browse files
committed
Added modeling of athena v2 and v3 for sql injections
1 parent c725191 commit 238568d

File tree

3 files changed

+83
-8
lines changed

3 files changed

+83
-8
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/javascript-all
4+
extensible: sinkModel
5+
data:
6+
- ["AthenaClientV3", "ReturnValue.Member[send].Argument[0]", "sql-injection"]
7+
- ["AthenaClientV2", "ReturnValue.Member[startQueryExecution,createNamedQuery,updateNamedQuery].Argument[0].Member[QueryString]", "sql-injection"]
8+
9+
10+
- addsTo:
11+
pack: codeql/javascript-all
12+
extensible: summaryModel
13+
data:
14+
- ["@aws-sdk/client-athena", "Member[StartQueryExecutionCommand,CreateNamedQueryCommand,UpdateNamedQueryCommand]", "Argument[0].Member[QueryString]", "ReturnValue", "taint"]
15+
16+
- addsTo:
17+
pack: codeql/javascript-all
18+
extensible: typeModel
19+
data:
20+
- ["AthenaClientV3", "@aws-sdk/client-athena", "Member[AthenaClient]"]
21+
- ["AthenaClientV2", "aws-sdk", "Member[Athena]"]

javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
#select
2+
| 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 |
3+
| 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 |
4+
| 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 |
5+
| 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 |
6+
| 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 |
7+
| 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 |
28
| 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 |
39
| 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 |
410
| 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,6 +152,29 @@
146152
| 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 |
147153
| 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 |
148154
edges
155+
| athena.js:9:11:9:36 | userQuery | athena.js:14:30:14:38 | userQuery | provenance | |
156+
| athena.js:9:11:9:36 | userQuery | athena.js:24:22:24:30 | userQuery | provenance | |
157+
| athena.js:9:11:9:36 | userQuery | athena.js:33:22:33:30 | userQuery | provenance | |
158+
| athena.js:9:23:9:30 | req.body | athena.js:9:11:9:36 | userQuery | provenance | |
159+
| athena.js:13:11:17:5 | params1 [QueryString] | athena.js:18:46:18:52 | params1 [QueryString] | provenance | |
160+
| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | athena.js:13:11:17:5 | params1 [QueryString] | provenance | |
161+
| athena.js:14:22:14:38 | "SQL" + userQuery | athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | provenance | |
162+
| athena.js:14:30:14:38 | userQuery | athena.js:14:22:14:38 | "SQL" + userQuery | provenance | |
163+
| athena.js:18:11:18:53 | p | athena.js:19:23:19:23 | p | provenance | |
164+
| athena.js:18:15:18:53 | new Sta ... arams1) | athena.js:18:11:18:53 | p | provenance | |
165+
| athena.js:18:46:18:52 | params1 [QueryString] | athena.js:18:15:18:53 | new Sta ... arams1) | provenance | |
166+
| athena.js:21:11:26:5 | params2 [QueryString] | athena.js:27:51:27:57 | params2 [QueryString] | provenance | |
167+
| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | athena.js:21:11:26:5 | params2 [QueryString] | provenance | |
168+
| athena.js:24:22:24:30 | userQuery | athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | provenance | |
169+
| athena.js:27:51:27:57 | params2 [QueryString] | athena.js:27:23:27:58 | new Cre ... arams2) | provenance | |
170+
| athena.js:29:11:35:5 | params3 [QueryString] | athena.js:36:51:36:57 | params3 [QueryString] | provenance | |
171+
| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | athena.js:29:11:35:5 | params3 [QueryString] | provenance | |
172+
| athena.js:33:22:33:30 | userQuery | athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | provenance | |
173+
| athena.js:36:51:36:57 | params3 [QueryString] | athena.js:36:23:36:58 | new Upd ... arams3) | provenance | |
174+
| athena.js:43:11:43:36 | userQuery | athena.js:48:22:48:30 | userQuery | provenance | |
175+
| athena.js:43:11:43:36 | userQuery | athena.js:57:22:57:30 | userQuery | provenance | |
176+
| athena.js:43:11:43:36 | userQuery | athena.js:66:22:66:30 | userQuery | provenance | |
177+
| athena.js:43:23:43:30 | req.body | athena.js:43:11:43:36 | userQuery | provenance | |
149178
| clients3.js:10:9:10:40 | maliciousInput | clients3.js:16:55:16:68 | maliciousInput | provenance | |
150179
| clients3.js:10:26:10:33 | req.body | clients3.js:10:9:10:40 | maliciousInput | provenance | |
151180
| clients3.js:12:11:17:5 | params [Expression] | clients3.js:18:54:18:59 | params [Expression] | provenance | |
@@ -562,6 +591,31 @@ edges
562591
| tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | provenance | |
563592
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | provenance | |
564593
nodes
594+
| athena.js:9:11:9:36 | userQuery | semmle.label | userQuery |
595+
| athena.js:9:23:9:30 | req.body | semmle.label | req.body |
596+
| athena.js:13:11:17:5 | params1 [QueryString] | semmle.label | params1 [QueryString] |
597+
| athena.js:13:21:17:5 | {\\n ... }\\n } [QueryString] | semmle.label | {\\n ... }\\n } [QueryString] |
598+
| athena.js:14:22:14:38 | "SQL" + userQuery | semmle.label | "SQL" + userQuery |
599+
| athena.js:14:30:14:38 | userQuery | semmle.label | userQuery |
600+
| athena.js:18:11:18:53 | p | semmle.label | p |
601+
| athena.js:18:15:18:53 | new Sta ... arams1) | semmle.label | new Sta ... arams1) |
602+
| athena.js:18:46:18:52 | params1 [QueryString] | semmle.label | params1 [QueryString] |
603+
| athena.js:19:23:19:23 | p | semmle.label | p |
604+
| athena.js:21:11:26:5 | params2 [QueryString] | semmle.label | params2 [QueryString] |
605+
| athena.js:21:21:26:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] |
606+
| athena.js:24:22:24:30 | userQuery | semmle.label | userQuery |
607+
| athena.js:27:23:27:58 | new Cre ... arams2) | semmle.label | new Cre ... arams2) |
608+
| athena.js:27:51:27:57 | params2 [QueryString] | semmle.label | params2 [QueryString] |
609+
| athena.js:29:11:35:5 | params3 [QueryString] | semmle.label | params3 [QueryString] |
610+
| athena.js:29:21:35:5 | {\\n ... "\\n } [QueryString] | semmle.label | {\\n ... "\\n } [QueryString] |
611+
| athena.js:33:22:33:30 | userQuery | semmle.label | userQuery |
612+
| athena.js:36:23:36:58 | new Upd ... arams3) | semmle.label | new Upd ... arams3) |
613+
| athena.js:36:51:36:57 | params3 [QueryString] | semmle.label | params3 [QueryString] |
614+
| athena.js:43:11:43:36 | userQuery | semmle.label | userQuery |
615+
| athena.js:43:23:43:30 | req.body | semmle.label | req.body |
616+
| athena.js:48:22:48:30 | userQuery | semmle.label | userQuery |
617+
| athena.js:57:22:57:30 | userQuery | semmle.label | userQuery |
618+
| athena.js:66:22:66:30 | userQuery | semmle.label | userQuery |
565619
| clients3.js:10:9:10:40 | maliciousInput | semmle.label | maliciousInput |
566620
| clients3.js:10:26:10:33 | req.body | semmle.label | req.body |
567621
| clients3.js:12:11:17:5 | params [Expression] | semmle.label | params [Expression] |

javascript/ql/test/query-tests/Security/CWE-089/untyped/athena.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const app = express();
66
app.use(bodyParser.json());
77

88
app.post('/v3/athena/all', async (req, res) => {
9-
const userQuery = req.body.query; // $ MISSING: Source
9+
const userQuery = req.body.query; // $ Source
1010

1111
const client = new AthenaClient({ region: "us-east-1" });
1212

@@ -16,15 +16,15 @@ app.post('/v3/athena/all', async (req, res) => {
1616
ResultConfiguration: { OutputLocation: "s3://my-results/" }
1717
};
1818
const p = new StartQueryExecutionCommand(params1);
19-
await client.send(p); // $ MISSING: Alert
19+
await client.send(p); // $ Alert
2020

2121
const params2 = {
2222
Name: "user_query",
2323
Database: "default",
2424
QueryString: userQuery,
2525
Description: "User-provided query"
2626
};
27-
await client.send(new CreateNamedQueryCommand(params2)); // $ MISSING: Alert -- This only stores query to database, not executed
27+
await client.send(new CreateNamedQueryCommand(params2)); // $ Alert -- This only stores query to database, not executed
2828

2929
const params3 = {
3030
NamedQueryId: "namedQueryId",
@@ -33,19 +33,19 @@ app.post('/v3/athena/all', async (req, res) => {
3333
QueryString: userQuery,
3434
Description: "Updated user-provided query"
3535
};
36-
await client.send(new UpdateNamedQueryCommand(params3)); // $ MISSING: Alert -- This only stores query to database, not executed
36+
await client.send(new UpdateNamedQueryCommand(params3)); // $ Alert -- This only stores query to database, not executed
3737

3838
res.end();
3939
});
4040

4141

4242
app.post('/v2/athena/all', async (req, res) => {
43-
const userQuery = req.body.query; // $ MISSING: Source
43+
const userQuery = req.body.query; // $ Source
4444

4545
const athena = new AWS.Athena({ region: "us-east-1" });
4646

4747
const params1 = {
48-
QueryString: userQuery, // $ MISSING: Alert
48+
QueryString: userQuery, // $ Alert
4949
QueryExecutionContext: { Database: "default" },
5050
ResultConfiguration: { OutputLocation: "s3://my-results/" }
5151
};
@@ -54,7 +54,7 @@ app.post('/v2/athena/all', async (req, res) => {
5454
const params2 = {
5555
Name: "user_query",
5656
Database: "default",
57-
QueryString: userQuery, // $ MISSING: Alert -- This only stores query to database, not executed
57+
QueryString: userQuery, // $ Alert -- This only stores query to database, not executed
5858
Description: "User-provided query"
5959
};
6060
await athena.createNamedQuery(params2).promise();
@@ -63,7 +63,7 @@ app.post('/v2/athena/all', async (req, res) => {
6363
NamedQueryId: "namedQueryId",
6464
Name: "user_query_updated",
6565
Database: "default",
66-
QueryString: userQuery, // $ MISSING: Alert -- This only stores query to database, not executed
66+
QueryString: userQuery, // $ Alert -- This only stores query to database, not executed
6767
Description: "Updated user-provided query"
6868
};
6969
await athena.updateNamedQuery(params3).promise();

0 commit comments

Comments
 (0)