1
1
import javascript
2
2
3
- module Sqlite {
4
- // Gets an expression that constructs or returns a Sqlite database instance.
3
+ module TypeOrm {
4
+ // Gets an expression that constructs or returns a TypeORM database instance.
5
5
API:: Node dataSource ( ) {
6
6
result = API:: moduleImport ( "typeorm" ) .getMember ( "DataSource" ) .getInstance ( )
7
7
}
8
8
9
+ // Gets an `QueryRunner`
10
+ API:: Node queryRunner ( ) { result = dataSource ( ) .getMember ( "createQueryRunner" ) .getReturn ( ) }
11
+
9
12
// Gets `createQueryBuilder` return value from a Active record based Entity
10
13
API:: Node activeRecordQueryBuilder ( ) {
11
- result =
12
- API:: moduleImport ( "typeorm" )
13
- .getMember ( "Entity" )
14
- .getReturn ( )
15
- .getADecoratedClass ( )
16
- .getMember ( "createQueryBuilder" )
17
- .getReturn ( )
14
+ result = queryRunner ( ) .getMember ( "manager" ) .getMember ( "createQueryBuilder" ) .getReceiver ( )
18
15
}
19
16
20
17
// Gets `createQueryBuilder` return value from a Data Mapper based Entity
@@ -26,7 +23,7 @@ module Sqlite {
26
23
// Using repository
27
24
dataSource ( ) .getMember ( "getRepository" ) .getReturn ( ) ,
28
25
// Using entity manager
29
- dataSource ( ) .getMember ( "manager" )
26
+ dataSource ( ) .getMember ( "manager" ) , queryRunner ( ) . getMember ( "manager" )
30
27
] .getMember ( "createQueryBuilder" ) .getReturn ( )
31
28
}
32
29
@@ -67,9 +64,9 @@ module Sqlite {
67
64
68
65
/**
69
66
* Gets functions responsible for select expressions
70
- * `orderBy` is not injectable in sqlite , if we want to write a filter we should specify a DataSource parameter string value,
67
+ * `orderBy` is not injectable in TypeORM , if we want to write a filter we should specify a DataSource parameter string value,
71
68
* which mostly is taken from config files and we will loose many sinks,
72
- * Also many application support multiple DBMSs besides sqlite ,
69
+ * Also many application support multiple DBMSs besides TypeORM ,
73
70
* Also Consider it that `Order By` clause is one of the most popular injectable sinks
74
71
*/
75
72
string selectExpression ( ) {
@@ -78,7 +75,8 @@ module Sqlite {
78
75
"select" , "addSelect" , "from" , "where" , "andWhere" , "orWhere" , "having" , "orHaving" ,
79
76
"andHaving" , "orderBy" , "addOrderBy" , "distinctOn" , "groupBy" , "addCommonTableExpression" ,
80
77
"leftJoinAndSelect" , "innerJoinAndSelect" , "leftJoin" , "innerJoin" , "leftJoinAndMapOne" ,
81
- "innerJoinAndMapOne" , "leftJoinAndMapMany" , "innerJoinAndMapMany"
78
+ "innerJoinAndMapOne" , "leftJoinAndMapMany" , "innerJoinAndMapMany" , "orUpdate" , "orIgnore" ,
79
+ "values" , "set"
82
80
]
83
81
}
84
82
@@ -88,22 +86,19 @@ module Sqlite {
88
86
}
89
87
90
88
/**
91
- * A call to a TypeORM Query Builder method and its successor nodes.
89
+ * A call to some successor functions of TypeORM `createQueryBuilder` function which are dangerous
92
90
*/
93
- private class QueryCall extends DatabaseAccess , API:: CallNode {
91
+ private class QueryBuilderCall extends DatabaseAccess , API:: CallNode {
94
92
API:: Node typeOrmNode ;
95
93
96
- QueryCall ( ) {
97
- (
98
- typeOrmNode = getASuccessorOfBuilderInstance ( ) and
99
- this = typeOrmNode .asSource ( )
100
- or
101
- // I'm doing following because this = typeOrmNode.asSource()s
102
- // won't let me to get a member in getAQueryArgument
103
- typeOrmNode = getASuccessorOfBrackets ( ) and
104
- typeOrmNode .getMember ( selectExpression ( ) ) .getACall ( ) = this
105
- ) and
106
- this .getFile ( ) .getLocation ( ) .toString ( ) .matches ( "%.ts%" )
94
+ QueryBuilderCall ( ) {
95
+ typeOrmNode = getASuccessorOfBuilderInstance ( ) and
96
+ this = typeOrmNode .asSource ( )
97
+ or
98
+ // I'm doing following because this = TypeORMNode.asSource()s
99
+ // won't let me to get a member in getAQueryArgument
100
+ typeOrmNode = getASuccessorOfBrackets ( ) and
101
+ typeOrmNode .getMember ( selectExpression ( ) ) .getACall ( ) = this
107
102
}
108
103
109
104
override DataFlow:: Node getAResult ( ) {
@@ -126,27 +121,33 @@ module Sqlite {
126
121
"addCommonTableExpression"
127
122
] and
128
123
result = typeOrmNode .getMember ( memberName ) .getParameter ( 0 ) .asSink ( )
124
+ or
125
+ memberName = [ "orIgnore" , "orUpdate" ] and
126
+ result = typeOrmNode .getMember ( memberName ) .getParameter ( [ 0 , 1 ] ) .asSink ( )
127
+ or
128
+ // following functions if use a function as their input fields,called function parameters which are vulnerable
129
+ memberName = [ "values" , "set" ] and
130
+ result = typeOrmNode .getMember ( memberName ) .getParameter ( 0 ) .getAMember ( ) .getReturn ( ) .asSink ( )
129
131
)
130
132
}
131
133
}
132
134
133
- /** An expression that is passed to the `query` method and hence interpreted as SQL. */
134
- class QueryString extends SQL:: SqlString {
135
- QueryString ( ) { this = any ( QueryCall qc ) .getAQueryArgument ( ) }
135
+ /**
136
+ * A call to a TypeORM `query` function of QueryRunner
137
+ */
138
+ private class QueryRunner extends DatabaseAccess , API:: CallNode {
139
+ QueryRunner ( ) { queryRunner ( ) .getMember ( "query" ) .getACall ( ) = this }
140
+
141
+ override DataFlow:: Node getAResult ( ) { result = this }
142
+
143
+ override DataFlow:: Node getAQueryArgument ( ) { result = this .getArgument ( 0 ) }
136
144
}
137
- }
138
145
139
- predicate test ( API:: Node n ) { n = API:: moduleImport ( "typeorm" ) .getASuccessor * ( ) .getMember ( "where" ) }
140
-
141
- predicate test2 ( API:: Node n ) {
142
- n =
143
- API:: moduleImport ( "typeorm" )
144
- .getMember ( "DataSource" )
145
- .getInstance ( )
146
- .getMember ( "getRepository" )
147
- .getReturn ( )
148
- .getMember ( "createQueryBuilder" )
149
- .getReturn ( )
150
- .getMember ( "where" )
151
- .getParameter ( 0 )
146
+ /** An expression that is passed to the `query` function and hence interpreted as SQL. */
147
+ class QueryString extends SQL:: SqlString {
148
+ QueryString ( ) {
149
+ this = any ( QueryRunner qc ) .getAQueryArgument ( ) or
150
+ this = any ( QueryBuilderCall qc ) .getAQueryArgument ( )
151
+ }
152
+ }
152
153
}
0 commit comments