Merge pull request #15060 from am0o0/amammad-js-envinjection

JS: Env Injection query
This commit is contained in:
Erik Krogh Kristensen
2024-06-20 21:27:21 +02:00
committed by GitHub
12 changed files with 300 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Controlling the value of arbitrary environment variables from user-controllable data is not safe.
</p>
</overview>
<recommendation>
<p>
Restrict this operation only to privileged users or only for some not important environment variables.
</p>
</recommendation>
<example>
<p>
The following example allows unauthorized users to assign a value to any environment variable.
</p>
<sample src="examples/Bad_Value_And_Key_Assignment.js" />
</example>
<references>
<li> <a href="https://huntr.com/bounties/00ec6847-125b-43e9-9658-d3cace1751d6/">Admin account TakeOver in mintplex-labs/anything-llm</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,69 @@
/**
* @name User controlled arbitrary environment variable injection
* @description creating arbitrary environment variables from user controlled data is not secure
* @kind path-problem
* @id js/env-key-and-value-injection
* @problem.severity error
* @security-severity 7.5
* @precision medium
* @tags security
* external/cwe/cwe-089
*/
import javascript
import DataFlow::PathGraph
/** A taint tracking configuration for unsafe environment injection. */
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "envInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink = keyOfEnv() or
sink = valueOfEnv()
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::InvokeNode ikn |
ikn = DataFlow::globalVarRef("Object").getAMemberInvocation("keys")
|
pred = ikn.getArgument(0) and
(
succ = ikn.getAChainedMethodCall(["filter", "map"]) or
succ = ikn or
succ = ikn.getAChainedMethodCall("forEach").getABoundCallbackParameter(0, 0)
)
)
}
}
DataFlow::Node keyOfEnv() {
result =
NodeJSLib::process().getAPropertyRead("env").getAPropertyWrite().getPropertyNameExpr().flow()
}
DataFlow::Node valueOfEnv() {
result = API::moduleImport("process").getMember("env").getAMember().asSink()
}
private predicate readToProcessEnv(DataFlow::Node envKey, DataFlow::Node envValue) {
exists(DataFlow::PropWrite env |
env = NodeJSLib::process().getAPropertyRead("env").getAPropertyWrite()
|
envKey = env.getPropertyNameExpr().flow() and
envValue = env.getRhs()
)
}
from
Configuration cfgForValue, Configuration cfgForKey, DataFlow::PathNode source,
DataFlow::PathNode envKey, DataFlow::PathNode envValue
where
cfgForValue.hasFlowPath(source, envKey) and
envKey.getNode() = keyOfEnv() and
cfgForKey.hasFlowPath(source, envValue) and
envValue.getNode() = valueOfEnv() and
readToProcessEnv(envKey.getNode(), envValue.getNode())
select envKey.getNode(), source, envKey, "arbitrary environment variable assignment from this $@.",
source.getNode(), "user controllable source"

View File

@@ -0,0 +1,36 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Assigning Value to environment variables from user-controllable data is not safe.
</p>
</overview>
<recommendation>
<p>
Restrict this operation only to privileged users or only for some not important environment variables.
</p>
</recommendation>
<example>
<p>
The following example allows unauthorized users to assign a value to a critical environment variable.
</p>
<sample src="examples/Bad_Value_Assignment.js" />
</example>
<references>
<li><a href="https://huntr.com/bounties/00ec6847-125b-43e9-9658-d3cace1751d6/">Admin account TakeOver in mintplex-labs/anything-llm</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,30 @@
/**
* @name User controlled environment variable value injection
* @description assigning important environment variables from user controlled data is not secure
* @kind path-problem
* @id js/env-value-injection
* @problem.severity error
* @security-severity 7.5
* @precision medium
* @tags security
* external/cwe/cwe-089
*/
import javascript
import DataFlow::PathGraph
/** A taint tracking configuration for unsafe environment injection. */
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "envInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink = API::moduleImport("process").getMember("env").getAMember().asSink()
}
}
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "this environment variable assignment is $@.",
source.getNode(), "user controllable"

View File

@@ -0,0 +1,8 @@
const http = require('node:http');
http.createServer((req, res) => {
const { EnvValue, EnvKey } = req.body;
process.env[EnvKey] = EnvValue; // NOT OK
res.end('env has been injected!');
});

View File

@@ -0,0 +1,8 @@
const http = require('node:http');
http.createServer((req, res) => {
const { EnvValue } = req.body;
process.env["A_Critical_Env"] = EnvValue; // NOT OK
res.end('env has been injected!');
});