Skip to content

Commit e566145

Browse files
committed
PS: Use the same sinks for '&sqlcmd' as we do for 'Invoke-SqlCmd'.
1 parent e1efae5 commit e566145

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

powershell/ql/lib/semmle/code/powershell/security/SqlInjectionCustomizations.qll

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,27 @@ module SqlInjection {
5252

5353
private string inputfile() { result = ["inputfile", "i"] }
5454

55+
bindingset[call]
56+
pragma[inline_late]
57+
private predicate sqlCmdSinkCommon(DataFlow::CallNode call, DataFlow::Node s) {
58+
s = call.getNamedArgument(query())
59+
or
60+
// If the input is not provided as a query parameter or an input file
61+
// parameter then it's the first argument.
62+
not call.hasNamedArgument(query()) and
63+
not call.hasNamedArgument(inputfile()) and
64+
s = call.getArgument(0)
65+
or
66+
// TODO: Here we really should pick a splat argument, but we don't yet extract whether an
67+
// argument is a splat argument.
68+
s = unique( | | call.getAnArgument())
69+
}
70+
5571
class InvokeSqlCmdSink extends Sink {
5672
InvokeSqlCmdSink() {
57-
exists(DataFlow::CallNode call | call.matchesName("Invoke-Sqlcmd") |
58-
this = call.getNamedArgument(query())
59-
or
60-
// If the input is not provided as a query parameter or an input file
61-
// parameter then it's the first argument.
62-
not call.hasNamedArgument(query()) and
63-
not call.hasNamedArgument(inputfile()) and
64-
this = call.getArgument(0)
65-
or
66-
// TODO: Here we really should pick a splat argument, but we don't yet extract whether an
67-
// argument is a splat argument.
68-
this = unique( | | call.getAnArgument())
73+
exists(DataFlow::CallNode call |
74+
call.matchesName("Invoke-Sqlcmd") and
75+
sqlCmdSinkCommon(call, this)
6976
)
7077
}
7178

@@ -94,11 +101,17 @@ module SqlInjection {
94101
override string getSinkType() { result = "write to " + memberName }
95102
}
96103

104+
/**
105+
* A call of the form `&sqlcmd`.
106+
*
107+
* We don't know if this is actually a call to an SQL execution procedure, but it is
108+
* very common to define a `sqlcmd` variable and point it to an SQL execution program.
109+
*/
97110
class SqlCmdSink extends Sink {
98111
SqlCmdSink() {
99112
exists(DataFlow::CallOperatorNode call |
100113
call.getCommand().asExpr().getValue().stringMatches("sqlcmd") and
101-
call.getAnArgument() = this
114+
sqlCmdSinkCommon(call, this)
102115
)
103116
}
104117

0 commit comments

Comments
 (0)