Skip to content

Commit 16aacd8

Browse files
authored
Merge pull request #136 from microsoft/powershell-first-query-preps
PS: Add AST and CFG classes for operator `&` and add environment variable reads as local flow sources
2 parents 1e1fd45 + 4a2fd52 commit 16aacd8

File tree

8 files changed

+76
-1
lines changed

8 files changed

+76
-1
lines changed

powershell/ql/lib/semmle/code/powershell/Command.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import powershell
2+
23
private predicate parseCommandName(Cmd cmd, string namespace, string name) {
34
exists(string qualified | command(cmd, qualified, _, _, _) |
45
namespace = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 1) and
@@ -11,6 +12,7 @@ private predicate parseCommandName(Cmd cmd, string namespace, string name) {
1112
)
1213
}
1314

15+
/** A call to a command. */
1416
class Cmd extends @command, CmdBase {
1517
override string toString() { result = "call to " + this.getQualifiedCommandName() }
1618

@@ -88,3 +90,8 @@ class Cmd extends @command, CmdBase {
8890

8991
Redirection getARedirection() { result = this.getRedirection(_) }
9092
}
93+
94+
/** A call to operator `&`. */
95+
class CallOperator extends Cmd {
96+
CallOperator() { this.getKind() = 28 }
97+
}

powershell/ql/lib/semmle/code/powershell/Variable.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,21 @@ class LocalVariable extends AbstractLocalScopeVariable, TLocalVariable {
273273
final override Scope getDeclaringScope() { result = scope }
274274
}
275275

276+
/**
277+
* A variable of the form `$Env:HOME`.
278+
*/
279+
class EnvVariable extends Variable {
280+
string var;
281+
282+
EnvVariable() { this.getName() = ["env:", "Env:"] + var }
283+
284+
/**
285+
* Gets the part of the variable name that represens which environment
286+
* variable.
287+
*/
288+
string getEnvironmentVariable() { result = var }
289+
}
290+
276291
class Parameter extends AbstractLocalScopeVariable, TParameter {
277292
ParameterImpl p;
278293

powershell/ql/lib/semmle/code/powershell/VariableExpression.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,12 @@ class VarWriteAccess extends VarAccess {
4848

4949
predicate isImplicit() { isImplicitVariableWriteAccess(this) }
5050
}
51+
52+
/** An access to an environment variable such as `$Env:PATH` */
53+
class EnvVarAccess extends VarAccess {
54+
EnvVarAccess() { super.getVariable() instanceof EnvVariable }
55+
56+
override EnvVariable getVariable() { result = super.getVariable() }
57+
58+
string getEnvironmentVariable() { result = this.getVariable().getEnvironmentVariable() }
59+
}

powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ module StmtNodes {
597597
final override string getName() { result = s.getCmdName().getValue().getValue() }
598598
}
599599

600+
/** A control-flow node that wraps a call to operator `&` */
601+
class CallOperatorCfgNode extends CmdCfgNode {
602+
CallOperatorCfgNode() { this.getStmt() instanceof CallOperator }
603+
}
604+
600605
private class AssignStmtChildMapping extends PipelineBaseChildMapping, AssignStmt {
601606
override predicate relevantChild(Ast n) {
602607
n = this.getLeftHandSide() or n = this.getRightHandSide()

powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/FlowSources.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** Provides classes representing various flow sources for taint tracking. */
2-
import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlow
2+
private import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlow
33
import semmle.code.powershell.dataflow.flowsources.Remote
44
import semmle.code.powershell.dataflow.flowsources.Local
55
import semmle.code.powershell.frameworks.data.internal.ApiGraphModels

powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ abstract class EnvironmentVariableSource extends LocalFlowSource {
3030
override string getSourceType() { result = "environment variable" }
3131
}
3232

33+
private class EnvironmentVariableEnv extends EnvironmentVariableSource {
34+
EnvironmentVariableEnv() {
35+
this.asExpr().getExpr().(VarReadAccess).getVariable() instanceof EnvVariable
36+
}
37+
}
38+
3339
private class ExternalEnvironmentVariableSource extends EnvironmentVariableSource {
3440
ExternalEnvironmentVariableSource() {
3541
this = ModelOutput::getASourceNode("environment", _).asSource()

powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPublic.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,30 @@ class CallNode extends AstNode {
448448

449449
Node getQualifier() { result.asExpr() = call.getQualifier() }
450450

451+
/** Gets the i'th argument to this call. */
452+
Node getArgument(int i) { result.asExpr() = call.getArgument(i) }
453+
454+
/** Gets the i'th positional argument to this call. */
455+
Node getPositionalArgument(int i) { result.asExpr() = call.getPositionalArgument(i) }
456+
457+
/** Gets the argument with the name `name`, if any. */
458+
Node getNamedArgument(string name) { result.asExpr() = call.getNamedArgument(name) }
459+
460+
/**
461+
* Gets any argument of this call.
462+
*
463+
* Note that this predicate doesn't get the pipeline argument, if any.
464+
*/
465+
Node getAnArgument() { result.asExpr() = call.getAnArgument() }
466+
451467
int getNumberOfArguments() { result = call.getNumberOfArguments() }
452468
}
453469

470+
/** A call to operator `&`, viwed as a node in a data flow graph. */
471+
class CallOperatorNode extends CallNode {
472+
CallOperatorNode() { this.getCallNode() instanceof CfgNodes::StmtNodes::CallOperatorCfgNode }
473+
}
474+
454475
/** A use of a type name, viewed as a node in a data flow graph. */
455476
class TypeNameNode extends ExprNode {
456477
override CfgNodes::ExprNodes::TypeNameCfgNode n;

powershell/ql/lib/semmle/code/powershell/dataflow/internal/TaintTrackingPrivate.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,15 @@ private module Cached {
6565
}
6666

6767
import Cached
68+
import SpeculativeTaintFlow
69+
70+
private module SpeculativeTaintFlow {
71+
private import semmle.code.powershell.dataflow.internal.DataFlowDispatch as DataFlowDispatch
72+
private import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlowPublic
73+
74+
/**
75+
* Holds if the additional step from `src` to `sink` should be considered in
76+
* speculative taint flow exploration.
77+
*/
78+
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
79+
}

0 commit comments

Comments
 (0)