Skip to content

Commit c2bdc7a

Browse files
committed
PS: Add experimental query from the internal repo.
1 parent 2fe3cee commit c2bdc7a

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* @name Command Injection
3+
* @description Variable expression executed as command
4+
* @kind problem
5+
* @id powershell/command-injection
6+
* @problem.severity warning
7+
* @precision low
8+
* @tags security
9+
*/
10+
11+
import powershell
12+
13+
predicate containsScope(VariableExpression outer, VariableExpression inner) {
14+
outer.getUserPath() = inner.getUserPath() and
15+
outer != inner
16+
}
17+
18+
predicate constantTernaryExpression(TernaryExpression ternary) {
19+
onlyConstantExpressions(ternary.getIfTrue()) and onlyConstantExpressions(ternary.getIfFalse())
20+
}
21+
22+
predicate constantBinaryExpression(BinaryExpression binary) {
23+
onlyConstantExpressions(binary.getLeftHandSide()) and onlyConstantExpressions(binary.getRightHandSide())
24+
}
25+
26+
predicate onlyConstantExpressions(Expression expr){
27+
expr instanceof StringConstantExpression or constantBinaryExpression(expr) or constantTernaryExpression(expr)
28+
}
29+
30+
VariableExpression getNonConstantVariableAssignment(VariableExpression varexpr) {
31+
(
32+
exists(AssignmentStatement assignment |
33+
not onlyConstantExpressions(assignment.getRightHandSide().(CommandExpression).getExpression()) and
34+
result = assignment.getLeftHandSide()
35+
)
36+
) and
37+
containsScope(result, varexpr)
38+
}
39+
40+
VariableExpression getParameterWithVariableScope(VariableExpression varexpr) {
41+
exists(Parameter parameter |
42+
result = parameter.getName() and
43+
containsScope(result, varexpr)
44+
)
45+
}
46+
47+
Expression getAllSubExpressions(Expression expr)
48+
{
49+
result = expr or
50+
result = getAllSubExpressions(expr.(ArrayLiteral).getAnElement()) or
51+
result = getAllSubExpressions(expr.(ArrayExpression).getStatementBlock().getAStatement().(Pipeline).getAComponent().(CommandExpression).getExpression())
52+
}
53+
54+
Expression dangerousCommandElement(Command command)
55+
{
56+
(
57+
command.getKind() = 28 or
58+
command.getName() = "Invoke-Expression"
59+
) and
60+
result = getAllSubExpressions(command.getAnElement())
61+
}
62+
63+
from Expression commandarg, VariableExpression unknownDeclaration
64+
where
65+
exists(Command command |
66+
(
67+
unknownDeclaration = getNonConstantVariableAssignment(commandarg) or
68+
unknownDeclaration = getParameterWithVariableScope(commandarg)
69+
)
70+
and
71+
commandarg = dangerousCommandElement(command)
72+
)
73+
select commandarg.(VariableExpression).getLocation(), "Unsafe flow to command argument from $@.",
74+
unknownDeclaration, unknownDeclaration.getUserPath()

powershell/ql/src/qlpack.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: microsoft-sdl/powershell-queries
2+
version: 0.0.1
3+
groups:
4+
- powershell
5+
- microsoft-all
6+
- queries
7+
extractor: powershell
8+
dependencies:
9+
microsoft-sdl/powershell-all: ${workspace}
10+
codeql/suite-helpers: ${workspace}
11+
warnOnImplicitThis: true

0 commit comments

Comments
 (0)