@@ -123,3 +123,107 @@ class OsCommandFirstArgument extends CommandSink {
123123 }
124124
125125}
126+
127+ // -------------------------------------------------------------------------- //
128+ // Modeling of the 'invoke' package and 'fabric' package (v 2.x)
129+ //
130+ // Since fabric build so closely upon invoke, we model them together to avoid
131+ // duplication
132+ // -------------------------------------------------------------------------- //
133+
134+ /** A taint sink that is potentially vulnerable to malicious shell commands.
135+ * The `vuln` in `invoke.run(vuln, ...)` and similar calls.
136+ */
137+ class InvokeRun extends CommandSink {
138+ InvokeRun ( ) {
139+ this = Value:: named ( "invoke.run" ) .( FunctionValue ) .getArgumentForCall ( _, 0 )
140+ or
141+ this = Value:: named ( "invoke.sudo" ) .( FunctionValue ) .getArgumentForCall ( _, 0 )
142+ }
143+
144+ override string toString ( ) { result = "InvokeRun" }
145+
146+ override predicate sinks ( TaintKind kind ) {
147+ kind instanceof ExternalStringKind
148+ }
149+ }
150+
151+ /** Internal TaintKind to track the invoke.Context instance passed to functions
152+ * marked with @invoke.task
153+ */
154+ private class InvokeContextArg extends TaintKind {
155+ InvokeContextArg ( ) { this = "InvokeContextArg" }
156+ }
157+
158+ /** Internal TaintSource to track the context passed to functions marked with @invoke.task */
159+ private class InvokeContextArgSource extends TaintSource {
160+ InvokeContextArgSource ( ) {
161+ exists ( Function f , Expr decorator |
162+ count ( f .getADecorator ( ) ) = 1 and
163+ (
164+ decorator = f .getADecorator ( ) and not decorator instanceof Call
165+ or
166+ decorator = f .getADecorator ( ) .( Call ) .getFunc ( )
167+
168+ ) and
169+ (
170+ decorator .pointsTo ( Value:: named ( "invoke.task" ) )
171+ or
172+ decorator .pointsTo ( Value:: named ( "fabric.task" ) )
173+ )
174+ |
175+ this .( ControlFlowNode ) .getNode ( ) = f .getArg ( 0 )
176+ )
177+ }
178+
179+ override predicate isSourceOf ( TaintKind kind ) {
180+ kind instanceof InvokeContextArg
181+ }
182+ }
183+
184+ /** A taint sink that is potentially vulnerable to malicious shell commands.
185+ * The `vuln` in `invoke.Context().run(vuln, ...)` and similar calls.
186+ */
187+ class InvokeContextRun extends CommandSink {
188+ InvokeContextRun ( ) {
189+ exists ( CallNode call |
190+ any ( InvokeContextArg k ) .taints ( call .getFunction ( ) .( AttrNode ) .getObject ( "run" ) )
191+ or
192+ call = Value:: named ( "invoke.Context" ) .( ClassValue ) .lookup ( "run" ) .getACall ( )
193+ or
194+ // fabric.connection.Connection is a subtype of invoke.context.Context
195+ // since fabric.Connection.run has a decorator, it doesn't work with FunctionValue :|
196+ // and `Value::named("fabric.Connection").(ClassValue).lookup("run").getACall()` returned no results,
197+ // so here is the hacky solution that works :\
198+ call .getFunction ( ) .( AttrNode ) .getObject ( "run" ) .pointsTo ( ) .getClass ( ) = Value:: named ( "fabric.Connection" )
199+ |
200+ this = call .getArg ( 0 )
201+ or
202+ this = call .getArgByName ( "command" )
203+ )
204+ }
205+
206+ override string toString ( ) { result = "InvokeContextRun" }
207+
208+ override predicate sinks ( TaintKind kind ) {
209+ kind instanceof ExternalStringKind
210+ }
211+ }
212+
213+ /** A taint sink that is potentially vulnerable to malicious shell commands.
214+ * The `vuln` in `fabric.Group().run(vuln, ...)` and similar calls.
215+ */
216+ class FabricGroupRun extends CommandSink {
217+ FabricGroupRun ( ) {
218+ exists ( ClassValue cls |
219+ cls .getASuperType ( ) = Value:: named ( "fabric.Group" ) and
220+ this = cls .lookup ( "run" ) .( FunctionValue ) .getArgumentForCall ( _, 1 )
221+ )
222+ }
223+
224+ override string toString ( ) { result = "FabricGroupRun" }
225+
226+ override predicate sinks ( TaintKind kind ) {
227+ kind instanceof ExternalStringKind
228+ }
229+ }
0 commit comments