From cfed2d4ce029136bab61eefaaf666c77ecbff8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Thu, 14 Mar 2024 16:30:23 +0100 Subject: [PATCH] Split queries --- ql/src/Security/CWE-078/CommandInjection.ql | 38 +++++++++++++++ .../CWE-078/CriticalCommandInjection.ql | 44 ++++++++++++++++++ ql/src/Security/CWE-094/CodeInjection.ql | 40 ++++++++++++++++ .../Security/CWE-094/CriticalCodeInjection.ql | 46 +++++++++++++++++++ .../Security/CWE-094/ExpressionInjection.ql | 3 +- ql/src/Security/CWE-918/RequestForgery.ql | 37 +++++++++++++++ 6 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 ql/src/Security/CWE-078/CommandInjection.ql create mode 100644 ql/src/Security/CWE-078/CriticalCommandInjection.ql create mode 100644 ql/src/Security/CWE-094/CodeInjection.ql create mode 100644 ql/src/Security/CWE-094/CriticalCodeInjection.ql create mode 100644 ql/src/Security/CWE-918/RequestForgery.ql diff --git a/ql/src/Security/CWE-078/CommandInjection.ql b/ql/src/Security/CWE-078/CommandInjection.ql new file mode 100644 index 00000000000..2a2225e17b6 --- /dev/null +++ b/ql/src/Security/CWE-078/CommandInjection.ql @@ -0,0 +1,38 @@ +/** + * @name Command built from user-controlled sources + * @description Building a system command from user-controlled sources is vulnerable to insertion of + * malicious code by the user. + * @kind path-problem + * @problem.severity warning + * @security-severity 5.0 + * @precision high + * @id actions/command-injection + * @tags actions + * security + * external/cwe/cwe-078 + */ + +import actions +import codeql.actions.TaintTracking +import codeql.actions.dataflow.FlowSources +import codeql.actions.dataflow.ExternalFlow + +private class CommandInjectionSink extends DataFlow::Node { + CommandInjectionSink() { externallyDefinedSink(this, "command-injection") } +} + +private module MyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink } +} + +module MyFlow = TaintTracking::Global; + +import MyFlow::PathGraph + +from MyFlow::PathNode source, MyFlow::PathNode sink +where MyFlow::flowPath(source, sink) +select sink.getNode(), source, sink, + "Potential expression injection in $@, which may be controlled by an external user.", sink, + sink.getNode().asExpr().(Expression).getRawExpression() diff --git a/ql/src/Security/CWE-078/CriticalCommandInjection.ql b/ql/src/Security/CWE-078/CriticalCommandInjection.ql new file mode 100644 index 00000000000..3834b0ac0d0 --- /dev/null +++ b/ql/src/Security/CWE-078/CriticalCommandInjection.ql @@ -0,0 +1,44 @@ +/** + * @name Command built from user-controlled sources + * @description Building a system command from user-controlled sources is vulnerable to insertion of + * malicious code by the user. + * @kind path-problem + * @problem.severity error + * @security-severity 9 + * @precision high + * @id actions/command-injection + * @tags actions + * security + * external/cwe/cwe-078 + */ + +import actions +import codeql.actions.TaintTracking +import codeql.actions.dataflow.FlowSources +import codeql.actions.dataflow.ExternalFlow + +private class CommandInjectionSink extends DataFlow::Node { + CommandInjectionSink() { externallyDefinedSink(this, "command-injection") } +} + +private module MyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink } +} + +module MyFlow = TaintTracking::Global; + +import MyFlow::PathGraph + +from MyFlow::PathNode source, MyFlow::PathNode sink, Workflow w +where + MyFlow::flowPath(source, sink) and + w = source.getNode().asExpr().getEnclosingWorkflow() and + ( + w instanceof ReusableWorkflow or + w.hasTriggerEvent(source.getNode().(RemoteFlowSource).getATriggerEvent()) + ) +select sink.getNode(), source, sink, + "Potential expression injection in $@, which may be controlled by an external user.", sink, + sink.getNode().asExpr().(Expression).getRawExpression() diff --git a/ql/src/Security/CWE-094/CodeInjection.ql b/ql/src/Security/CWE-094/CodeInjection.ql new file mode 100644 index 00000000000..7ad0e98bc49 --- /dev/null +++ b/ql/src/Security/CWE-094/CodeInjection.ql @@ -0,0 +1,40 @@ +/** + * @name Code injection + * @description Interpreting unsanitized user input as code allows a malicious user to perform arbitrary + * code execution. + * @kind path-problem + * @problem.severity warning + * @security-severity 5.0 + * @precision high + * @id actions/code-injection + * @tags actions + * security + * external/cwe/cwe-094 + * external/cwe/cwe-095 + * external/cwe/cwe-116 + */ + +import actions +import codeql.actions.TaintTracking +import codeql.actions.dataflow.FlowSources +import codeql.actions.dataflow.ExternalFlow + +private class CodeInjectionSink extends DataFlow::Node { + CodeInjectionSink() { externallyDefinedSink(this, "request-forgery") } +} + +private module MyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink } +} + +module MyFlow = TaintTracking::Global; + +import MyFlow::PathGraph + +from MyFlow::PathNode source, MyFlow::PathNode sink +where MyFlow::flowPath(source, sink) +select sink.getNode(), source, sink, + "Potential expression injection in $@, which may be controlled by an external user.", sink, + sink.getNode().asExpr().(Expression).getRawExpression() diff --git a/ql/src/Security/CWE-094/CriticalCodeInjection.ql b/ql/src/Security/CWE-094/CriticalCodeInjection.ql new file mode 100644 index 00000000000..5a4bbaca034 --- /dev/null +++ b/ql/src/Security/CWE-094/CriticalCodeInjection.ql @@ -0,0 +1,46 @@ +/** + * @name Code injection + * @description Interpreting unsanitized user input as code allows a malicious user to perform arbitrary + * code execution. + * @kind path-problem + * @problem.severity error + * @security-severity 9 + * @precision high + * @id actions/code-injection + * @tags actions + * security + * external/cwe/cwe-094 + * external/cwe/cwe-095 + * external/cwe/cwe-116 + */ + +import actions +import codeql.actions.TaintTracking +import codeql.actions.dataflow.FlowSources +import codeql.actions.dataflow.ExternalFlow + +private class CodeInjectionSink extends DataFlow::Node { + CodeInjectionSink() { externallyDefinedSink(this, "request-forgery") } +} + +private module MyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink } +} + +module MyFlow = TaintTracking::Global; + +import MyFlow::PathGraph + +from MyFlow::PathNode source, MyFlow::PathNode sink, Workflow w +where + MyFlow::flowPath(source, sink) and + w = source.getNode().asExpr().getEnclosingWorkflow() and + ( + w instanceof ReusableWorkflow or + w.hasTriggerEvent(source.getNode().(RemoteFlowSource).getATriggerEvent()) + ) +select sink.getNode(), source, sink, + "Potential expression injection in $@, which may be controlled by an external user.", sink, + sink.getNode().asExpr().(Expression).getRawExpression() diff --git a/ql/src/Security/CWE-094/ExpressionInjection.ql b/ql/src/Security/CWE-094/ExpressionInjection.ql index 33d6260203e..d59cc07cad2 100644 --- a/ql/src/Security/CWE-094/ExpressionInjection.ql +++ b/ql/src/Security/CWE-094/ExpressionInjection.ql @@ -20,8 +20,7 @@ import codeql.actions.dataflow.ExternalFlow private class ExpressionInjectionSink extends DataFlow::Node { ExpressionInjectionSink() { exists(Run e | e.getAnScriptExpr() = this.asExpr()) or - externallyDefinedSink(this, - ["expression-injection", "command-injection", "request-forgery", "code-injection"]) + externallyDefinedSink(this, "expression-injection") } } diff --git a/ql/src/Security/CWE-918/RequestForgery.ql b/ql/src/Security/CWE-918/RequestForgery.ql new file mode 100644 index 00000000000..3675597fcd7 --- /dev/null +++ b/ql/src/Security/CWE-918/RequestForgery.ql @@ -0,0 +1,37 @@ +/** + * @name Uncontrolled data used in network request + * @description Sending network requests with user-controlled data allows for request forgery attacks. + * @kind path-problem + * @problem.severity error + * @security-severity 9.1 + * @precision high + * @id actions/request-forgery + * @tags actions + * security + * external/cwe/cwe-918 + */ + +import actions +import codeql.actions.TaintTracking +import codeql.actions.dataflow.FlowSources +import codeql.actions.dataflow.ExternalFlow + +private class RequestForgerySink extends DataFlow::Node { + RequestForgerySink() { externallyDefinedSink(this, "request-forgery") } +} + +private module MyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgerySink } +} + +module MyFlow = TaintTracking::Global; + +import MyFlow::PathGraph + +from MyFlow::PathNode source, MyFlow::PathNode sink +where MyFlow::flowPath(source, sink) +select sink.getNode(), source, sink, + "Potential expression injection in $@, which may be controlled by an external user.", sink, + sink.getNode().asExpr().(Expression).getRawExpression()