From a03c06802e7f08baadf6796dc19a968cd72fdc67 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Tue, 6 Feb 2024 09:34:20 +0000 Subject: [PATCH] Ruby: Add some more command injection sinks --- ruby/ql/lib/codeql/ruby/frameworks/core/Kernel.qll | 10 ++++++++-- ruby/ql/lib/codeql/ruby/frameworks/stdlib/Open3.qll | 8 +++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Kernel.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Kernel.qll index 96568e74902..2aa46ab550a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/Kernel.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Kernel.qll @@ -130,13 +130,19 @@ module Kernel { * `Kernel.spawn` takes the same argument forms as `Kernel.system`. * See `KernelSystemCall` for details. * Ruby documentation: https://docs.ruby-lang.org/en/3.0.0/Kernel.html#method-i-spawn + * Methods with the same effect exist in the `Process` and `PTY` classes, so they are also modeled here. * TODO: document and handle the env and option arguments. * ``` * spawn([env,] command... [,options]) -> pid * ``` */ - class KernelSpawnCall extends SystemCommandExecution::Range instanceof KernelMethodCall { - KernelSpawnCall() { this.getMethodName() = "spawn" } + class KernelSpawnCall extends SystemCommandExecution::Range instanceof DataFlow::CallNode { + KernelSpawnCall() { + this.getMethodName() = "spawn" and + this instanceof KernelMethodCall + or + this = DataFlow::getConstant(["Process", "PTY"]).getAMethodCall("spawn") + } override DataFlow::Node getAnArgument() { result = super.getArgument(_) } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Open3.qll b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Open3.qll index e65f3005503..5f349c451f3 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Open3.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Open3.qll @@ -7,7 +7,7 @@ private import codeql.ruby.ApiGraphs private import codeql.ruby.Concepts /** - * Provides modeling for the `Open3` library. + * Provides modeling for the `Open3` and `Open4` libraries. */ module Open3 { /** @@ -18,8 +18,10 @@ module Open3 { class Open3Call extends SystemCommandExecution::Range instanceof DataFlow::CallNode { Open3Call() { this = - API::getTopLevelMember("Open3") - .getAMethodCall(["popen3", "popen2", "popen2e", "capture3", "capture2", "capture2e"]) + API::getTopLevelMember(["Open3", "Open4"]) + .getAMethodCall([ + "popen3", "popen2", "popen2e", "capture3", "capture2", "capture2e", "popen4" + ]) } override DataFlow::Node getAnArgument() { result = super.getArgument(_) }