diff --git a/codeql/addipamconfig-to-exec.ql b/codeql/addipamconfig-to-exec.ql new file mode 100644 index 0000000000..9b9068fddb --- /dev/null +++ b/codeql/addipamconfig-to-exec.ql @@ -0,0 +1,51 @@ +/** + * @name Command Injection From CNS ipam add result / CNS multitenancy ipam add result + * @description Flow exists from CNS ipam add result / CNS multitenancy ipam add result (untrusted) to exec command + * @kind path-problem + * @problem.severity warning + * @id go/cmd-inject-ipam-add-result + * @tags security + */ + +// Detect inputs from CNS add ipam result / CNS multitenancy ipam add result to command injection +// 1 linux, 2 windows +import go + +private class Sink extends DataFlow2::Node { + Sink() { + exists(DataFlow::CallNode c | + c.getTarget().hasQualifiedName("os/exec", "CommandContext") and + (c.getArgument(2) = this or c.getArgument(1) = this) + or + c.getTarget().hasQualifiedName("os/exec", "Command") and + (c.getArgument(0) = this or c.getArgument(1) = this) + ) + } +} + +private class Source extends DataFlow2::Node { + Source() { + exists(DataFlow::CallNode c, Method m | + //m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "NetPlugin", + // "addIpamInvoker") or // this is maybe not necessary since we call GetAllNetworkContainers right next to this = duplicated results + m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "Multitenancy", + "GetAllNetworkContainers") and + c = m.getACall() and + c.getResult(0) = this + ) + } +} + +module MyConfiguration implements DataFlow::ConfigSig { + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isSource(DataFlow::Node source) { source instanceof Source } +} + +module Flow = TaintTracking::Global; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink +where Flow::flowPath(source, sink) +select sink.getNode(), source, sink, "potential command injection" diff --git a/codeql/cni-args-to-exec.ql b/codeql/cni-args-to-exec.ql new file mode 100644 index 0000000000..4c236e6f6c --- /dev/null +++ b/codeql/cni-args-to-exec.ql @@ -0,0 +1,57 @@ +/** + * @name Command Injection From CNI Args + * @description Flow exists from CNI Args (untrusted) to exec command + * @kind path-problem + * @problem.severity warning + * @id go/cmd-inject-cni + * @tags security + */ + +// Detect inputs from CNI ARGS to command injection +// 2 windows, 1 linux +import go + +private class Sink extends DataFlow2::Node { + Sink() { + exists(DataFlow::CallNode c | + c.getTarget().hasQualifiedName("os/exec", "CommandContext") and + (c.getArgument(2) = this or c.getArgument(1) = this) + or + c.getTarget().hasQualifiedName("os/exec", "Command") and + (c.getArgument(0) = this or c.getArgument(1) = this) + ) + } +} + +private class Source extends DataFlow2::Node { + Source() { + exists(DataFlow::CallNode c, Method m | + ( + m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "NetPlugin", + "Add") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "NetPlugin", + "Delete") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "NetPlugin", + "Update") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cni/network", "NetPlugin", + "Get") + ) and + c = m.getACall() and + c.getArgument(0) = this + ) + } +} + +module MyConfiguration implements DataFlow::ConfigSig { + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isSource(DataFlow::Node source) { source instanceof Source } +} + +module Flow = TaintTracking::Global; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink +where Flow::flowPath(source, sink) +select sink.getNode(), source, sink, "potential command injection" diff --git a/codeql/cns-invoker-to-exec.ql b/codeql/cns-invoker-to-exec.ql new file mode 100644 index 0000000000..9fd88fad14 --- /dev/null +++ b/codeql/cns-invoker-to-exec.ql @@ -0,0 +1,57 @@ +/** + * @name Command Injection From CNS Invoker + * @description Flow exists from CNS Invoker (untrusted) to exec command + * @kind path-problem + * @problem.severity warning + * @id go/cmd-inject-cns-invoker + * @tags security + */ + +// Detect inputs from CNS Invoker to command injection +// Does not detect flow to outside the enclosed method (which is why we analyze addIpamInvoker's results too) +import go + +private class Sink extends DataFlow2::Node { + Sink() { + exists(DataFlow::CallNode c | + c.getTarget().hasQualifiedName("os/exec", "CommandContext") and + (c.getArgument(2) = this or c.getArgument(1) = this) + or + c.getTarget().hasQualifiedName("os/exec", "Command") and + (c.getArgument(0) = this or c.getArgument(1) = this) + ) + } +} + +private class Source extends DataFlow2::Node { + Source() { + exists(DataFlow::CallNode c, Method m | + ( + m.hasQualifiedName("github.com/Azure/azure-container-networking/cns/client", "Client", + "RequestIPs") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cns/client", "Client", + "RequestIPAddress") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cns/client", "Client", + "GetNetworkContainer") or + m.hasQualifiedName("github.com/Azure/azure-container-networking/cns/client", "Client", + "GetAllNetworkContainers") + ) and + c = m.getACall() and + c.getResult(0) = this + ) + } +} + +module MyConfiguration implements DataFlow::ConfigSig { + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isSource(DataFlow::Node source) { source instanceof Source } +} + +module Flow = TaintTracking::Global; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink +where Flow::flowPath(source, sink) +select sink.getNode(), source, sink, "potential command injection" diff --git a/codeql/query3.ql b/codeql/decode-to-exec.ql similarity index 100% rename from codeql/query3.ql rename to codeql/decode-to-exec.ql diff --git a/codeql/query1.ql b/codeql/query1.ql deleted file mode 100644 index 3cf9916863..0000000000 --- a/codeql/query1.ql +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name Call to library function - * @description Finds calls - * @id go/examples/calltocommand - * @kind problem - * @problem.severity warning - * @tags call - * function - */ - -import go - -from Function println, DataFlow::CallNode call -where - println.hasQualifiedName("os/exec", "Command") and - call = println.getACall() -select call, "found cmd" diff --git a/codeql/query2.ql b/codeql/query2.ql deleted file mode 100644 index 47262aabf3..0000000000 --- a/codeql/query2.ql +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name Call to library function - * @description Finds calls - * @id go/examples/calltocommandctx - * @kind problem - * @problem.severity error - * @tags call - * function - */ - -import go - -from Function println, DataFlow::CallNode call -where - println.hasQualifiedName("os/exec", "CommandContext") and - call = println.getACall() -select call, "found cmd context"