11import javascript
22
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.
55 API:: Node dataSource ( ) {
66 result = API:: moduleImport ( "typeorm" ) .getMember ( "DataSource" ) .getInstance ( )
77 }
88
9+ // Gets an `QueryRunner`
10+ API:: Node queryRunner ( ) { result = dataSource ( ) .getMember ( "createQueryRunner" ) .getReturn ( ) }
11+
912 // Gets `createQueryBuilder` return value from a Active record based Entity
1013 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 ( )
1815 }
1916
2017 // Gets `createQueryBuilder` return value from a Data Mapper based Entity
@@ -26,7 +23,7 @@ module Sqlite {
2623 // Using repository
2724 dataSource ( ) .getMember ( "getRepository" ) .getReturn ( ) ,
2825 // Using entity manager
29- dataSource ( ) .getMember ( "manager" )
26+ dataSource ( ) .getMember ( "manager" ) , queryRunner ( ) . getMember ( "manager" )
3027 ] .getMember ( "createQueryBuilder" ) .getReturn ( )
3128 }
3229
@@ -67,9 +64,9 @@ module Sqlite {
6764
6865 /**
6966 * 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,
7168 * 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 ,
7370 * Also Consider it that `Order By` clause is one of the most popular injectable sinks
7471 */
7572 string selectExpression ( ) {
@@ -78,7 +75,8 @@ module Sqlite {
7875 "select" , "addSelect" , "from" , "where" , "andWhere" , "orWhere" , "having" , "orHaving" ,
7976 "andHaving" , "orderBy" , "addOrderBy" , "distinctOn" , "groupBy" , "addCommonTableExpression" ,
8077 "leftJoinAndSelect" , "innerJoinAndSelect" , "leftJoin" , "innerJoin" , "leftJoinAndMapOne" ,
81- "innerJoinAndMapOne" , "leftJoinAndMapMany" , "innerJoinAndMapMany"
78+ "innerJoinAndMapOne" , "leftJoinAndMapMany" , "innerJoinAndMapMany" , "orUpdate" , "orIgnore" ,
79+ "values" , "set"
8280 ]
8381 }
8482
@@ -88,22 +86,19 @@ module Sqlite {
8886 }
8987
9088 /**
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
9290 */
93- private class QueryCall extends DatabaseAccess , API:: CallNode {
91+ private class QueryBuilderCall extends DatabaseAccess , API:: CallNode {
9492 API:: Node typeOrmNode ;
9593
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
107102 }
108103
109104 override DataFlow:: Node getAResult ( ) {
@@ -126,27 +121,33 @@ module Sqlite {
126121 "addCommonTableExpression"
127122 ] and
128123 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 ( )
129131 )
130132 }
131133 }
132134
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 ) }
136144 }
137- }
138145
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+ }
152153}
0 commit comments