mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
v1
This commit is contained in:
@@ -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.js" />
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<a href="https://huntr.com/bounties/00ec6847-125b-43e9-9658-d3cace1751d6/">Admin account TakeOver in mintplex-labs/anything-llm</a>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @name User controlled environment injection
|
||||
* @description full control on creating environment variables from user controlled data is not secure
|
||||
* @kind path-problem
|
||||
* @id js/envinjection
|
||||
* @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"
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @name User controlled environment injection
|
||||
* @description full control on creating environment variables from user controlled data is not secure
|
||||
* @kind path-problem
|
||||
* @id js/envinjection
|
||||
* @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) {
|
||||
NodeJSLib::process()
|
||||
.getAPropertyRead("env")
|
||||
.asExpr()
|
||||
.getParent()
|
||||
.(IndexExpr)
|
||||
.getAChildExpr()
|
||||
.(VarRef) = sink.asExpr()
|
||||
or
|
||||
sink = API::moduleImport("process").getMember("env").getAMember().asSink()
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
Configuration cfg, Configuration cfg2, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
DataFlow::PathNode sink2
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
sink.getNode() = API::moduleImport("process").getMember("env").getAMember().asSink() and
|
||||
cfg2.hasFlowPath(source, sink2) and
|
||||
sink.getNode().asExpr() =
|
||||
NodeJSLib::process()
|
||||
.getAPropertyRead("env")
|
||||
.asExpr()
|
||||
.getParent()
|
||||
.(IndexExpr)
|
||||
.getAChildExpr()
|
||||
.(VarRef)
|
||||
select sink.getNode(), source, sink, "this environment variable assignment is $@.",
|
||||
source.getNode(), "user controllable"
|
||||
@@ -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!');
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
nodes
|
||||
| test.js:4:9:4:20 | { EnvValue } |
|
||||
| test.js:4:9:4:31 | EnvValue |
|
||||
| test.js:4:11:4:18 | EnvValue |
|
||||
| test.js:4:24:4:31 | req.body |
|
||||
| test.js:4:24:4:31 | req.body |
|
||||
| test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:6:23:6:30 | EnvValue |
|
||||
edges
|
||||
| test.js:4:9:4:20 | { EnvValue } | test.js:4:11:4:18 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:4:11:4:18 | EnvValue | test.js:4:9:4:31 | EnvValue |
|
||||
| test.js:4:24:4:31 | req.body | test.js:4:9:4:20 | { EnvValue } |
|
||||
| test.js:4:24:4:31 | req.body | test.js:4:9:4:20 | { EnvValue } |
|
||||
#select
|
||||
| test.js:5:35:5:42 | EnvValue | test.js:4:24:4:31 | req.body | test.js:5:35:5:42 | EnvValue | this environment variable assignment is $@. | test.js:4:24:4:31 | req.body | user controllable |
|
||||
| test.js:6:23:6:30 | EnvValue | test.js:4:24:4:31 | req.body | test.js:6:23:6:30 | EnvValue | this environment variable assignment is $@. | test.js:4:24:4:31 | req.body | user controllable |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-099/EnvInjection.ql
|
||||
9
javascript/ql/test/experimental/Security/CWE-099/test.js
Normal file
9
javascript/ql/test/experimental/Security/CWE-099/test.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const http = require('node:http');
|
||||
|
||||
http.createServer((req, res) => {
|
||||
const { EnvValue } = req.body;
|
||||
process.env["A_Critical_Env"] = EnvValue; // NOT OK
|
||||
process.env[AKey] = EnvValue; // NOT OK
|
||||
|
||||
res.end('env has been injected!');
|
||||
});
|
||||
Reference in New Issue
Block a user