Skip to content

Commit 13aaa22

Browse files
committed
add bosted version of ShellCommandInjectionFromEnvironment
1 parent a743fbc commit 13aaa22

File tree

11 files changed

+132
-2
lines changed

11 files changed

+132
-2
lines changed

javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointCharacteristics.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,28 @@ private class NosqlInjectionSinkCharacteristic extends EndpointCharacteristic {
278278
}
279279
}
280280

281+
/**
282+
* Endpoints identified as "ShellCommandInjectionFromEnvironmentSink" by the standard JavaScript libraries are
283+
* ShellCommandInjectionFromEnvironment sinks with maximal confidence.
284+
*/
285+
private class ShellCommandInjectionFromEnvironmentSinkCharacteristic extends EndpointCharacteristic {
286+
ShellCommandInjectionFromEnvironmentSinkCharacteristic() {
287+
this = "ShellCommandInjectionFromEnvironmentSink"
288+
}
289+
290+
override predicate appliesToEndpoint(DataFlow::Node n) {
291+
n instanceof ShellCommandInjectionFromEnvironment::Sink
292+
}
293+
294+
override predicate hasImplications(
295+
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
296+
) {
297+
endpointClass instanceof ShellCommandInjectionFromEnvironmentSinkType and
298+
isPositiveIndicator = true and
299+
confidence = maximalConfidence()
300+
}
301+
}
302+
281303
/*
282304
* Characteristics that are indicative of not being a sink of any type, and have historically been used to select
283305
* negative samples for training.

javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointTypes.qll

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ newtype TEndpointType =
1010
TXssSinkType() or
1111
TNosqlInjectionSinkType() or
1212
TSqlInjectionSinkType() or
13-
TTaintedPathSinkType()
13+
TTaintedPathSinkType() or
14+
TShellCommandInjectionFromEnvironmentSinkType()
1415

1516
/** A class that can be predicted by endpoint scoring models. */
1617
abstract class EndpointType extends TEndpointType {
@@ -60,3 +61,11 @@ class TaintedPathSinkType extends EndpointType, TTaintedPathSinkType {
6061

6162
override int getEncoding() { result = 4 }
6263
}
64+
65+
/** The `ShellCommandInjectionFromEnvironmentSink` class that can be predicted by endpoint scoring models. */
66+
class ShellCommandInjectionFromEnvironmentSinkType extends EndpointType,
67+
TShellCommandInjectionFromEnvironmentSinkType {
68+
override string getDescription() { result = "ShellCommandInjectionFromEnvironmentSink" }
69+
70+
override int getEncoding() { result = 5 }
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* For internal use only.
3+
*
4+
* A taint-tracking configuration for reasoning about command-injection
5+
* vulnerabilities.
6+
* Defines shared code used by the ShellCommandInjectionFromEnvironment boosted query.
7+
*/
8+
9+
private import semmle.javascript.heuristics.SyntacticHeuristics
10+
private import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentCustomizations::ShellCommandInjectionFromEnvironment as ShellCommandInjectionFromEnvironment
11+
import AdaptiveThreatModeling
12+
13+
class ShellCommandInjectionFromEnvironmentAtmConfig extends AtmConfig {
14+
ShellCommandInjectionFromEnvironmentAtmConfig() {
15+
this = "ShellCommandInjectionFromEnvironmentAtmConfig"
16+
}
17+
18+
override predicate isKnownSource(DataFlow::Node source) {
19+
source instanceof ShellCommandInjectionFromEnvironment::Source
20+
}
21+
22+
override EndpointType getASinkEndpointType() {
23+
result instanceof ShellCommandInjectionFromEnvironmentSinkType
24+
}
25+
26+
override predicate isSanitizer(DataFlow::Node node) {
27+
super.isSanitizer(node) or
28+
node instanceof ShellCommandInjectionFromEnvironment::Sanitizer
29+
}
30+
}

javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/DebugResultInclusion.ql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ private import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjecti
1717
private import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
1818
private import experimental.adaptivethreatmodeling.XssATM as XssAtm
1919
private import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
20+
private import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM as ShellCommandInjectionFromEnvironmentAtm
2021

2122
string getAReasonSinkExcluded(DataFlow::Node sinkCandidate, Query query) {
2223
query instanceof NosqlInjectionQuery and
@@ -33,6 +34,11 @@ string getAReasonSinkExcluded(DataFlow::Node sinkCandidate, Query query) {
3334
or
3435
query instanceof XssThroughDomQuery and
3536
result = any(XssThroughDomAtm::XssThroughDomAtmConfig cfg).getAReasonSinkExcluded(sinkCandidate)
37+
or
38+
query instanceof ShellCommandInjectionFromEnvironmentQuery and
39+
result =
40+
any(ShellCommandInjectionFromEnvironmentAtm::ShellCommandInjectionFromEnvironmentAtmConfig cfg)
41+
.getAReasonSinkExcluded(sinkCandidate)
3642
}
3743

3844
pragma[inline]

javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointDataTraining.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ private import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjecti
1515
private import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
1616
private import experimental.adaptivethreatmodeling.XssATM as XssAtm
1717
private import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
18+
private import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM as ShellCommandInjectionFromEnvironmentAtm
1819

1920
/**
2021
* Gets the set of featureName-featureValue pairs for each endpoint in the training set.
@@ -217,6 +218,10 @@ DataFlow::Configuration getDataFlowCfg(Query query) {
217218
query instanceof XssQuery and result instanceof XssAtm::DomBasedXssAtmConfig
218219
or
219220
query instanceof XssThroughDomQuery and result instanceof XssThroughDomAtm::XssThroughDomAtmConfig
221+
or
222+
query instanceof ShellCommandInjectionFromEnvironmentQuery and
223+
result instanceof
224+
ShellCommandInjectionFromEnvironmentAtm::ShellCommandInjectionFromEnvironmentAtmConfig
220225
}
221226

222227
// TODO: Delete this once we are no longer surfacing `hasFlowFromSource`.

javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAt
99
import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
1010
import experimental.adaptivethreatmodeling.XssATM as XssAtm
1111
import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
12+
import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM as ShellCommandInjectionFromEnvironmentAtm
1213
import experimental.adaptivethreatmodeling.AdaptiveThreatModeling
1314

1415
from string queryName, AtmConfig c, EndpointType e
@@ -26,6 +27,10 @@ where
2627
queryName = "Xss" and c instanceof XssAtm::DomBasedXssAtmConfig
2728
or
2829
queryName = "XssThroughDom" and c instanceof XssThroughDomAtm::XssThroughDomAtmConfig
30+
or
31+
queryName = "ShellCommandInjectionFromEnvironment" and
32+
c instanceof
33+
ShellCommandInjectionFromEnvironmentAtm::ShellCommandInjectionFromEnvironmentAtmConfig
2934
) and
3035
e = c.getASinkEndpointType()
3136
select queryName, e.getEncoding() as label

javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/Queries.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ newtype TQuery =
99
TSqlInjectionQuery() or
1010
TTaintedPathQuery() or
1111
TXssQuery() or
12-
TXssThroughDomQuery()
12+
TXssThroughDomQuery() or
13+
TShellCommandInjectionFromEnvironmentQuery()
1314

1415
abstract class Query extends TQuery {
1516
abstract string getName();
@@ -36,3 +37,8 @@ class XssQuery extends Query, TXssQuery {
3637
class XssThroughDomQuery extends Query, TXssThroughDomQuery {
3738
override string getName() { result = "XssThroughDom" }
3839
}
40+
41+
class ShellCommandInjectionFromEnvironmentQuery extends Query,
42+
TShellCommandInjectionFromEnvironmentQuery {
43+
override string getName() { result = "ShellCommandInjectionFromEnvironment" }
44+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* For internal use only.
3+
*
4+
* @name Shell command built from environment values
5+
* @description Building a shell command string with values from the enclosing
6+
* environment may cause subtle bugs or vulnerabilities.
7+
* @kind path-problem
8+
* @scored
9+
* @problem.severity warning
10+
* @security-severity 6.3
11+
* @precision high
12+
* @id js/ml-powered/shell-command-injection-from-environment
13+
* @tags experimental security
14+
* correctness
15+
* security
16+
* external/cwe/cwe-078
17+
* external/cwe/cwe-088
18+
*/
19+
20+
import javascript
21+
import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM
22+
import ATM::ResultsInfo
23+
import DataFlow::PathGraph
24+
25+
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
26+
where cfg.hasBoostedFlowPath(source, sink, score)
27+
select sink.getNode(), source, sink,
28+
"(Experimental) This shell command depends on $@. Identified using machine learning.",
29+
source.getNode(), "an uncontrolled value", score

javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/EndpointFeatures.ql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm
1212
import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
1313
import experimental.adaptivethreatmodeling.XssATM as XssAtm
1414
import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
15+
import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM as ShellCommandInjectionFromEnvironmentAtm
1516
import experimental.adaptivethreatmodeling.EndpointFeatures as EndpointFeatures
1617
import extraction.NoFeaturizationRestrictionsConfig
1718
private import experimental.adaptivethreatmodeling.EndpointCharacteristics as EndpointCharacteristics
@@ -23,6 +24,10 @@ query predicate tokenFeatures(DataFlow::Node endpoint, string featureName, strin
2324
not exists(any(TaintedPathAtm::TaintedPathAtmConfig cfg).getAReasonSinkExcluded(endpoint)) or
2425
not exists(any(XssAtm::DomBasedXssAtmConfig cfg).getAReasonSinkExcluded(endpoint)) or
2526
not exists(any(XssThroughDomAtm::XssThroughDomAtmConfig cfg).getAReasonSinkExcluded(endpoint)) or
27+
not exists(
28+
any(ShellCommandInjectionFromEnvironmentAtm::ShellCommandInjectionFromEnvironmentAtmConfig cfg)
29+
.getAReasonSinkExcluded(endpoint)
30+
) or
2631
any(EndpointCharacteristics::IsArgumentToModeledFunctionCharacteristic characteristic)
2732
.appliesToEndpoint(endpoint)
2833
) and

javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/ExtractEndpointDataInference.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ private import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjecti
1919
private import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm
2020
private import experimental.adaptivethreatmodeling.XssATM as XssAtm
2121
private import experimental.adaptivethreatmodeling.XssThroughDomATM as XssThroughDomAtm
22+
private import experimental.adaptivethreatmodeling.ShellCommandInjectionFromEnvironmentATM as ShellCommandInjectionFromEnvironmentAtm
2223

2324
query predicate isSinkCandidateForQuery(
2425
AtmConfig::AtmConfig queryConfig, JS::DataFlow::PathNode sink

0 commit comments

Comments
 (0)