Module: Aikido::Zen::Sinks::Kernel::Extensions

Defined in:
lib/aikido/zen/sinks/kernel.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.scan_command(command, operation) ⇒ Aikido::Zen::Attacks::ShellInjectionAttack?

Checks if the user introduced input is trying to execute other commands using Shell Injection kind of attacks.

user input is detected as part of a Shell Injection Attack, or nil if it’s safe.

Parameters:

  • command (String)

    the _full command_ that will be executed.

  • context (Aikido::Zen::Context)
  • sink (Aikido::Zen::Sink)

    the Sink that is running the scan.

  • operation (Symbol, String)

    name of the method being scanned.

Returns:



21
22
23
24
25
26
# File 'lib/aikido/zen/sinks/kernel.rb', line 21

def self.scan_command(command, operation)
  SINK.scan(
    command: command,
    operation: operation
  )
end

Instance Method Details

#send_arg_to_scan(args, operation) ⇒ Object

‘system, spawn` functions can be invoked in several ways. For more details, see [the documentation](ruby-doc.org/3.4.1/Kernel.html#method-i-spawn)

In our context, we care primarily about two common scenarios:

- one argument (String)
    e.g.: system("ls"), system("echo something")
- two arguments (Hash, String)
    e.g.: system({"foo" => "bar"}, "ls"), system({"foo" => "bar"}, "echo something")

In all other cases, we do not protect against shell argument injections. Specifically:

If a user input contains something like $(whoami) and is passed as part of the command arguments (e.g., user_input = “$(whoami)”):

system("echo", user_input)   This is safe because Ruby automatically escapes arguments
                             passed to system/spawn in this form.

system("echo #{user_input}") This is not safe because Ruby interpolates the user_input
                             into the command string, resulting in a potentially harmful
                             command like `echo $(whoami)`.


48
49
50
51
52
53
54
55
56
# File 'lib/aikido/zen/sinks/kernel.rb', line 48

def send_arg_to_scan(args, operation)
  if args.size == 1 && args[0].is_a?(String)
    Extensions.scan_command(args[0], operation)
  end

  if args.size == 2 && args[0].is_a?(Hash)
    Extensions.scan_command(args[1], operation)
  end
end

#spawn(*args) ⇒ Object



63
64
65
66
# File 'lib/aikido/zen/sinks/kernel.rb', line 63

def spawn(*args, **)
  send_arg_to_scan(args, "spawn")
  super
end

#system(*args) ⇒ Object



58
59
60
61
# File 'lib/aikido/zen/sinks/kernel.rb', line 58

def system(*args, **)
  send_arg_to_scan(args, "system")
  super
end