File tree Expand file tree Collapse file tree 6 files changed +43
-7
lines changed
lib/semmle/code/powershell
test/query-tests/security/cwe-078/CommandInjection Expand file tree Collapse file tree 6 files changed +43
-7
lines changed Original file line number Diff line number Diff line change @@ -76,14 +76,14 @@ class CmdCall extends CallExpr, TCmd {
76
76
class CallOperator extends CmdCall {
77
77
CallOperator ( ) { getRawAst ( this ) instanceof Raw:: CallOperator }
78
78
79
- Expr getCommand ( ) { result = this .getArgument ( 0 ) }
79
+ Expr getCommand ( ) { result = this .getCallee ( ) }
80
80
}
81
81
82
82
/** A call to the dot-sourcing `.`. */
83
83
class DotSourcingOperator extends CmdCall {
84
84
DotSourcingOperator ( ) { getRawAst ( this ) instanceof Raw:: DotSourcingOperator }
85
85
86
- Expr getPath ( ) { result = this .getArgument ( 0 ) }
86
+ Expr getCommand ( ) { result = this .getCallee ( ) }
87
87
}
88
88
89
89
class JoinPath extends CmdCall {
Original file line number Diff line number Diff line change @@ -605,7 +605,22 @@ module ExprNodes {
605
605
606
606
override CallOperator getExpr ( ) { result = e }
607
607
608
- ExprCfgNode getCommand ( ) { result = this .getArgument ( 0 ) }
608
+ ExprCfgNode getCommand ( ) { result = this .getCallee ( ) }
609
+ }
610
+
611
+ private class DotSourcingOperatorChildMapping extends CallExprChildMapping instanceof DotSourcingOperator
612
+ {
613
+ override predicate relevantChild ( Ast child ) { super .relevantChild ( child ) }
614
+ }
615
+
616
+ class DotSourcingOperatorCfgNode extends CallExprCfgNode {
617
+ override string getAPrimaryQlClass ( ) { result = "DotSourcingOperatorCfgNode" }
618
+
619
+ override DotSourcingOperatorChildMapping e ;
620
+
621
+ override DotSourcingOperator getExpr ( ) { result = e }
622
+
623
+ ExprCfgNode getCommand ( ) { result = this .getCallee ( ) }
609
624
}
610
625
611
626
private class ToStringCallChildmapping extends CallExprChildMapping instanceof ToStringCall {
Original file line number Diff line number Diff line change @@ -540,11 +540,18 @@ class CallNode extends ExprNode {
540
540
Node getCallee ( ) { result .asExpr ( ) = call .getCallee ( ) }
541
541
}
542
542
543
- /** A call to operator `&`, viwed as a node in a data flow graph. */
543
+ /** A call to operator `&`, viewed as a node in a data flow graph. */
544
544
class CallOperatorNode extends CallNode {
545
545
override CfgNodes:: ExprNodes:: CallOperatorCfgNode call ;
546
546
547
- Node getCommand ( ) { result .asExpr ( ) = call .getCommand ( ) } // TODO: Alternatively, we could remap calls to & as command expressions.
547
+ Node getCommand ( ) { result .asExpr ( ) = call .getCommand ( ) }
548
+ }
549
+
550
+ /** A call to operator `.`, viewed as a node in a data flow graph. */
551
+ class DotSourcingOperatorNode extends CallNode {
552
+ override CfgNodes:: ExprNodes:: DotSourcingOperatorCfgNode call ;
553
+
554
+ Node getCommand ( ) { result .asExpr ( ) = call .getCommand ( ) }
548
555
}
549
556
550
557
/**
Original file line number Diff line number Diff line change @@ -46,8 +46,10 @@ module CommandInjection {
46
46
call .getAnArgument ( ) = this
47
47
)
48
48
or
49
- // Or the call command itself in case it's a use of operator &.
49
+ // Or the call command itself in case it's a use of " operator &" or "operator ." .
50
50
any ( DataFlow:: CallOperatorNode call ) .getCommand ( ) = this
51
+ or
52
+ any ( DataFlow:: DotSourcingOperatorNode call ) .getCommand ( ) = this
51
53
}
52
54
53
55
override string getSinkType ( ) { result = "call to Invoke-Expression" }
Original file line number Diff line number Diff line change 53
53
| test.ps1:170:36:170:41 | input | test.ps1:129:11:129:20 | userinput | provenance | |
54
54
| test.ps1:172:42:172:47 | input | test.ps1:136:11:136:20 | userinput | provenance | |
55
55
| test.ps1:173:42:173:47 | input | test.ps1:144:11:144:20 | userinput | provenance | |
56
+ | test.ps1:214:10:214:32 | Call to read-host | test.ps1:217:7:217:10 | $o | provenance | Src:MaD:0 |
56
57
nodes
57
58
| test.ps1:3:11:3:20 | userinput | semmle.label | userinput |
58
59
| test.ps1:4:23:4:52 | Get-Process -Name $UserInput | semmle.label | Get-Process -Name $UserInput |
@@ -109,6 +110,8 @@ nodes
109
110
| test.ps1:170:36:170:41 | input | semmle.label | input |
110
111
| test.ps1:172:42:172:47 | input | semmle.label | input |
111
112
| test.ps1:173:42:173:47 | input | semmle.label | input |
113
+ | test.ps1:214:10:214:32 | Call to read-host | semmle.label | Call to read-host |
114
+ | test.ps1:217:7:217:10 | $o | semmle.label | $o |
112
115
subpaths
113
116
#select
114
117
| test.ps1:4:23:4:52 | Get-Process -Name $UserInput | test.ps1:152:10:152:32 | Call to read-host | test.ps1:4:23:4:52 | Get-Process -Name $UserInput | This command depends on a $@. | test.ps1:152:10:152:32 | Call to read-host | user-provided value |
@@ -129,3 +132,4 @@ subpaths
129
132
| test.ps1:131:28:131:37 | UserInput | test.ps1:152:10:152:32 | Call to read-host | test.ps1:131:28:131:37 | UserInput | This command depends on a $@. | test.ps1:152:10:152:32 | Call to read-host | user-provided value |
130
133
| test.ps1:139:50:139:59 | UserInput | test.ps1:152:10:152:32 | Call to read-host | test.ps1:139:50:139:59 | UserInput | This command depends on a $@. | test.ps1:152:10:152:32 | Call to read-host | user-provided value |
131
134
| test.ps1:147:63:147:72 | UserInput | test.ps1:152:10:152:32 | Call to read-host | test.ps1:147:63:147:72 | UserInput | This command depends on a $@. | test.ps1:152:10:152:32 | Call to read-host | user-provided value |
135
+ | test.ps1:217:7:217:10 | $o | test.ps1:214:10:214:32 | Call to read-host | test.ps1:217:7:217:10 | $o | This command depends on a $@. | test.ps1:214:10:214:32 | Call to read-host | user-provided value |
Original file line number Diff line number Diff line change @@ -207,4 +207,12 @@ function Invoke-InvokeExpressionInjectionSafe4
207
207
Invoke-InvokeExpressionInjectionSafe1 - UserInput $input
208
208
Invoke-InvokeExpressionInjectionSafe2 - UserInput $input
209
209
Invoke-InvokeExpressionInjectionSafe3 - UserInput $input
210
- Invoke-InvokeExpressionInjectionSafe4 - UserInput $input
210
+ Invoke-InvokeExpressionInjectionSafe4 - UserInput $input
211
+
212
+ function false-positive-in-call-operator ($d )
213
+ {
214
+ $o = Read-Host " enter input"
215
+ & unzip - o " $o " - d $d # GOOD
216
+
217
+ . " $o " # BAD
218
+ }
You can’t perform that action at this time.
0 commit comments