@@ -21,7 +21,7 @@ module CommandInjection {
2121 /**
2222 * A data flow sink for command-injection vulnerabilities.
2323 */
24- abstract class Sink extends DataFlow:: Node {
24+ abstract class Sink extends DataFlow:: Node {
2525 abstract string getSinkType ( ) ;
2626 }
2727
@@ -49,9 +49,8 @@ module CommandInjection {
4949 // Or the call command itself in case it's a use of operator &.
5050 any ( DataFlow:: CallOperatorNode call ) .getCommand ( ) = this
5151 }
52- override string getSinkType ( ) {
53- result = "call to Invoke-Expression"
54- }
52+
53+ override string getSinkType ( ) { result = "call to Invoke-Expression" }
5554 }
5655
5756 class AddTypeSink extends Sink {
@@ -61,151 +60,143 @@ module CommandInjection {
6160 call .getAnArgument ( ) = this
6261 )
6362 }
64- override string getSinkType ( ) {
65- result = "call to Add-Type"
66- }
63+
64+ override string getSinkType ( ) { result = "call to Add-Type" }
6765 }
6866
6967 class InvokeScriptSink extends Sink {
70- InvokeScriptSink ( ) {
71- exists ( API:: Node call |
72- API:: getTopLevelMember ( "executioncontext" ) .getMember ( "invokecommand" ) .getMethod ( "invokescript" ) = call and
73- this = call .getArgument ( _) .asSink ( )
74- )
68+ InvokeScriptSink ( ) {
69+ exists ( API:: Node call |
70+ API:: getTopLevelMember ( "executioncontext" )
71+ .getMember ( "invokecommand" )
72+ .getMethod ( "invokescript" ) = call and
73+ this = call .getArgument ( _) .asSink ( )
74+ )
7575 }
76- override string getSinkType ( ) {
77- result = "call to InvokeScript"
78- }
79- }
8076
81- class CreateNestedPipelineSink extends Sink {
82- CreateNestedPipelineSink ( ) {
83- exists ( API:: Node call |
84- API:: getTopLevelMember ( "host" ) .getMember ( "runspace" ) .getMethod ( "createnestedpipeline" ) = call and
85- this = call .getArgument ( _) .asSink ( )
86- )
87- }
88- override string getSinkType ( ) {
89- result = "call to CreateNestedPipeline"
77+ override string getSinkType ( ) { result = "call to InvokeScript" }
78+ }
79+
80+ class CreateNestedPipelineSink extends Sink {
81+ CreateNestedPipelineSink ( ) {
82+ exists ( API:: Node call |
83+ API:: getTopLevelMember ( "host" ) .getMember ( "runspace" ) .getMethod ( "createnestedpipeline" ) =
84+ call and
85+ this = call .getArgument ( _) .asSink ( )
86+ )
9087 }
91- }
9288
93- class AddScriptInvokeSink extends Sink {
94- AddScriptInvokeSink ( ) {
95- exists ( InvokeMemberExpr addscript , InvokeMemberExpr create |
96- this .asExpr ( ) .getExpr ( ) = addscript .getAnArgument ( ) and
97- addscript .matchesName ( "AddScript" ) and
98- create .matchesName ( "Create" ) and
89+ override string getSinkType ( ) { result = "call to CreateNestedPipeline" }
90+ }
9991
100- addscript .getQualifier ( ) .( InvokeMemberExpr ) = create and
101- create .getQualifier ( ) .( TypeNameExpr ) .getName ( ) = "PowerShell"
92+ class AddScriptInvokeSink extends Sink {
93+ AddScriptInvokeSink ( ) {
94+ exists ( InvokeMemberExpr addscript , InvokeMemberExpr create |
95+ this .asExpr ( ) .getExpr ( ) = addscript .getAnArgument ( ) and
96+ addscript .matchesName ( "AddScript" ) and
97+ create .matchesName ( "Create" ) and
98+ addscript .getQualifier ( ) .( InvokeMemberExpr ) = create and
99+ create .getQualifier ( ) .( TypeNameExpr ) .getName ( ) = "PowerShell"
102100 )
101+ }
102+
103+ override string getSinkType ( ) { result = "call to AddScript" }
103104 }
104- override string getSinkType ( ) {
105- result = "call to AddScript"
105+
106+ class PowershellSink extends Sink {
107+ PowershellSink ( ) {
108+ exists ( CmdCall c | c .matchesName ( "powershell" ) |
109+ this .asExpr ( ) .getExpr ( ) = c .getArgument ( 1 ) and
110+ c .getArgument ( 0 ) .getValue ( ) .asString ( ) = "-command"
111+ or
112+ this .asExpr ( ) .getExpr ( ) = c .getArgument ( 0 )
113+ )
114+ }
115+
116+ override string getSinkType ( ) { result = "call to Powershell" }
106117 }
107- }
108118
109- class PowershellSink extends Sink {
110- PowershellSink ( ) {
111- exists ( CmdCall c |
112- c .matchesName ( "powershell" ) |
113- (
114- this .asExpr ( ) .getExpr ( ) = c .getArgument ( 1 ) and
115- c .getArgument ( 0 ) .getValue ( ) .asString ( ) = "-command"
116- ) or
117- (
118- this .asExpr ( ) .getExpr ( ) = c .getArgument ( 0 )
119- )
120- )
119+ class CmdSink extends Sink {
120+ CmdSink ( ) {
121+ exists ( CmdCall c |
122+ this .asExpr ( ) .getExpr ( ) = c .getArgument ( 1 ) and
123+ c .matchesName ( "cmd" ) and
124+ c .getArgument ( 0 ) .getValue ( ) .asString ( ) = "/c"
125+ )
121126 }
122- override string getSinkType ( ) {
123- result = "call to Powershell"
127+
128+ override string getSinkType ( ) { result = "call to Cmd" }
129+ }
130+
131+ class ForEachObjectSink extends Sink {
132+ ForEachObjectSink ( ) {
133+ exists ( CmdCall c |
134+ this .asExpr ( ) .getExpr ( ) = c .getAnArgument ( ) and
135+ c .matchesName ( "Foreach-Object" )
136+ )
124137 }
125- }
126138
127- class CmdSink extends Sink {
128- CmdSink ( ) {
129- exists ( CmdCall c |
130- this .asExpr ( ) .getExpr ( ) = c .getArgument ( 1 ) and
131- c .matchesName ( "cmd" ) and
132- c .getArgument ( 0 ) .getValue ( ) .asString ( ) = "/c"
139+ override string getSinkType ( ) { result = "call to ForEach-Object" }
140+ }
141+
142+ class InvokeSink extends Sink {
143+ InvokeSink ( ) {
144+ exists ( InvokeMemberExpr ie |
145+ this .asExpr ( ) .getExpr ( ) = ie .getCallee ( ) or
146+ this .asExpr ( ) .getExpr ( ) = ie .getQualifier ( ) .getAChild * ( )
133147 )
134- }
135- override string getSinkType ( ) {
136- result = "call to Cmd"
148+ }
149+
150+ override string getSinkType ( ) { result = "call to Invoke" }
137151 }
138- }
139152
140- class ForEachObjectSink extends Sink {
141- ForEachObjectSink ( ) {
142- exists ( CmdCall c |
143- this .asExpr ( ) .getExpr ( ) = c .getAnArgument ( ) and
144- c .matchesName ( "Foreach-Object" )
153+ class CreateScriptBlockSink extends Sink {
154+ CreateScriptBlockSink ( ) {
155+ exists ( InvokeMemberExpr ie |
156+ this .asExpr ( ) .getExpr ( ) = ie .getAnArgument ( ) and
157+ ie .matchesName ( "Create" ) and
158+ ie .getQualifier ( ) .( TypeNameExpr ) .getName ( ) = "ScriptBlock"
145159 )
146- }
147- override string getSinkType ( ) {
148- result = "call to ForEach-Object"
160+ }
161+
162+ override string getSinkType ( ) { result = "call to CreateScriptBlock" }
149163 }
150- }
151164
152- class InvokeSink extends Sink {
153- InvokeSink ( ) {
154- exists ( InvokeMemberExpr ie |
155- this .asExpr ( ) .getExpr ( ) = ie .getCallee ( ) or
156- this .asExpr ( ) .getExpr ( ) = ie .getQualifier ( ) .getAChild * ( )
157- )
158- }
159- override string getSinkType ( ) {
160- result = "call to Invoke"
165+ class NewScriptBlockSink extends Sink {
166+ NewScriptBlockSink ( ) {
167+ exists ( API:: Node call |
168+ API:: getTopLevelMember ( "executioncontext" )
169+ .getMember ( "invokecommand" )
170+ .getMethod ( "newscriptblock" ) = call and
171+ this = call .getArgument ( _) .asSink ( )
172+ )
161173 }
162- }
163174
164- class CreateScriptBlockSink extends Sink {
165- CreateScriptBlockSink ( ) {
166- exists ( InvokeMemberExpr ie |
167- this .asExpr ( ) .getExpr ( ) = ie .getAnArgument ( ) and
168- ie .matchesName ( "Create" ) and
169- ie .getQualifier ( ) .( TypeNameExpr ) .getName ( ) = "ScriptBlock"
175+ override string getSinkType ( ) { result = "call to NewScriptBlock" }
176+ }
177+
178+ class ExpandStringSink extends Sink {
179+ ExpandStringSink ( ) {
180+ exists ( API:: Node call | this = call .getArgument ( _) .asSink ( ) |
181+ API:: getTopLevelMember ( "executioncontext" )
182+ .getMember ( "invokecommand" )
183+ .getMethod ( "expandstring" ) = call or
184+ API:: getTopLevelMember ( "executioncontext" )
185+ .getMember ( "sessionstate" )
186+ .getMember ( "invokecommand" )
187+ .getMethod ( "expandstring" ) = call
170188 )
171- }
172- override string getSinkType ( ) {
173- result = "call to CreateScriptBlock"
174- }
175- }
176-
177- class NewScriptBlockSink extends Sink {
178- NewScriptBlockSink ( ) {
179- exists ( API:: Node call |
180- API:: getTopLevelMember ( "executioncontext" ) .getMember ( "invokecommand" ) .getMethod ( "newscriptblock" ) = call and
181- this = call .getArgument ( _) .asSink ( )
182- )
183- }
184- override string getSinkType ( ) {
185- result = "call to NewScriptBlock"
186- }
187- }
189+ }
188190
189- class ExpandStringSink extends Sink {
190- ExpandStringSink ( ) {
191- exists ( API:: Node call | this = call .getArgument ( _) .asSink ( ) |
192- API:: getTopLevelMember ( "executioncontext" ) .getMember ( "invokecommand" ) .getMethod ( "expandstring" ) = call or
193- API:: getTopLevelMember ( "executioncontext" ) .getMember ( "sessionstate" ) .getMember ( "invokecommand" ) .getMethod ( "expandstring" ) = call
194-
195- )
196- }
197- override string getSinkType ( ) {
198- result = "call to ExpandString"
199- }
200- }
191+ override string getSinkType ( ) { result = "call to ExpandString" }
192+ }
201193
202194 private class ExternalCommandInjectionSink extends Sink {
203195 ExternalCommandInjectionSink ( ) {
204196 this = ModelOutput:: getASinkNode ( "command-injection" ) .asSink ( )
205197 }
206- override string getSinkType ( ) {
207- result = "external command injection"
208- }
198+
199+ override string getSinkType ( ) { result = "external command injection" }
209200 }
210201
211202 class TypedParameterSanitizer extends Sanitizer {
@@ -217,15 +208,16 @@ class ExpandStringSink extends Sink {
217208 )
218209 }
219210 }
220-
211+
221212 class SingleQuoteSanitizer extends Sanitizer {
222- SingleQuoteSanitizer ( ) {
223- exists ( ExpandableStringExpr e , VarReadAccess v |
224- v = this .asExpr ( ) .getExpr ( ) and
225- e .getUnexpandedValue ( ) .toLowerCase ( ) .matches ( "%'$" + v .getVariable ( ) .getLowerCaseName ( ) + "'%" ) and
226- e .getAnExpr ( ) = v
227- )
213+ SingleQuoteSanitizer ( ) {
214+ exists ( ExpandableStringExpr e , VarReadAccess v |
215+ v = this .asExpr ( ) .getExpr ( ) and
216+ e .getUnexpandedValue ( )
217+ .toLowerCase ( )
218+ .matches ( "%'$" + v .getVariable ( ) .getLowerCaseName ( ) + "'%" ) and
219+ e .getAnExpr ( ) = v
220+ )
228221 }
229222 }
230223}
231-
0 commit comments