Skip to content

Commit

Permalink
Merge pull request #136 from microsoft/powershell-first-query-preps
Browse files Browse the repository at this point in the history
PS: Add AST and CFG classes for operator `&` and add environment variable reads as local flow sources
  • Loading branch information
MathiasVP authored Nov 8, 2024
2 parents 1e1fd45 + 4a2fd52 commit 16aacd8
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 1 deletion.
7 changes: 7 additions & 0 deletions powershell/ql/lib/semmle/code/powershell/Command.qll
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import powershell

private predicate parseCommandName(Cmd cmd, string namespace, string name) {
exists(string qualified | command(cmd, qualified, _, _, _) |
namespace = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 1) and
Expand All @@ -11,6 +12,7 @@ private predicate parseCommandName(Cmd cmd, string namespace, string name) {
)
}

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

Expand Down Expand Up @@ -88,3 +90,8 @@ class Cmd extends @command, CmdBase {

Redirection getARedirection() { result = this.getRedirection(_) }
}

/** A call to operator `&`. */
class CallOperator extends Cmd {
CallOperator() { this.getKind() = 28 }
}
15 changes: 15 additions & 0 deletions powershell/ql/lib/semmle/code/powershell/Variable.qll
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,21 @@ class LocalVariable extends AbstractLocalScopeVariable, TLocalVariable {
final override Scope getDeclaringScope() { result = scope }
}

/**
* A variable of the form `$Env:HOME`.
*/
class EnvVariable extends Variable {
string var;

EnvVariable() { this.getName() = ["env:", "Env:"] + var }

/**
* Gets the part of the variable name that represens which environment
* variable.
*/
string getEnvironmentVariable() { result = var }
}

class Parameter extends AbstractLocalScopeVariable, TParameter {
ParameterImpl p;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,12 @@ class VarWriteAccess extends VarAccess {

predicate isImplicit() { isImplicitVariableWriteAccess(this) }
}

/** An access to an environment variable such as `$Env:PATH` */
class EnvVarAccess extends VarAccess {
EnvVarAccess() { super.getVariable() instanceof EnvVariable }

override EnvVariable getVariable() { result = super.getVariable() }

string getEnvironmentVariable() { result = this.getVariable().getEnvironmentVariable() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,11 @@ module StmtNodes {
final override string getName() { result = s.getCmdName().getValue().getValue() }
}

/** A control-flow node that wraps a call to operator `&` */
class CallOperatorCfgNode extends CmdCfgNode {
CallOperatorCfgNode() { this.getStmt() instanceof CallOperator }
}

private class AssignStmtChildMapping extends PipelineBaseChildMapping, AssignStmt {
override predicate relevantChild(Ast n) {
n = this.getLeftHandSide() or n = this.getRightHandSide()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** Provides classes representing various flow sources for taint tracking. */
import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlow
private import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlow
import semmle.code.powershell.dataflow.flowsources.Remote
import semmle.code.powershell.dataflow.flowsources.Local
import semmle.code.powershell.frameworks.data.internal.ApiGraphModels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ abstract class EnvironmentVariableSource extends LocalFlowSource {
override string getSourceType() { result = "environment variable" }
}

private class EnvironmentVariableEnv extends EnvironmentVariableSource {
EnvironmentVariableEnv() {
this.asExpr().getExpr().(VarReadAccess).getVariable() instanceof EnvVariable
}
}

private class ExternalEnvironmentVariableSource extends EnvironmentVariableSource {
ExternalEnvironmentVariableSource() {
this = ModelOutput::getASourceNode("environment", _).asSource()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,30 @@ class CallNode extends AstNode {

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

/** Gets the i'th argument to this call. */
Node getArgument(int i) { result.asExpr() = call.getArgument(i) }

/** Gets the i'th positional argument to this call. */
Node getPositionalArgument(int i) { result.asExpr() = call.getPositionalArgument(i) }

/** Gets the argument with the name `name`, if any. */
Node getNamedArgument(string name) { result.asExpr() = call.getNamedArgument(name) }

/**
* Gets any argument of this call.
*
* Note that this predicate doesn't get the pipeline argument, if any.
*/
Node getAnArgument() { result.asExpr() = call.getAnArgument() }

int getNumberOfArguments() { result = call.getNumberOfArguments() }
}

/** A call to operator `&`, viwed as a node in a data flow graph. */
class CallOperatorNode extends CallNode {
CallOperatorNode() { this.getCallNode() instanceof CfgNodes::StmtNodes::CallOperatorCfgNode }
}

/** A use of a type name, viewed as a node in a data flow graph. */
class TypeNameNode extends ExprNode {
override CfgNodes::ExprNodes::TypeNameCfgNode n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,15 @@ private module Cached {
}

import Cached
import SpeculativeTaintFlow

private module SpeculativeTaintFlow {
private import semmle.code.powershell.dataflow.internal.DataFlowDispatch as DataFlowDispatch
private import semmle.code.powershell.dataflow.internal.DataFlowPublic as DataFlowPublic

/**
* Holds if the additional step from `src` to `sink` should be considered in
* speculative taint flow exploration.
*/
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
}

0 comments on commit 16aacd8

Please sign in to comment.