perl-tricks.md (5778B)
1 --- 2 title: "Perl Command-Execution Sinks" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/perl-tricks.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/perl-tricks.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Perl Command-Execution Sinks 14 15 ## Perl backticks/qx// sinks in Apache mod_perl handlers (reachability and exploitation) 16 17 One real-world pattern is Perl code building a shell command and executing it with backticks (`qx//`). In a `mod_perl` access handler, request data such as `$r->uri()` can reach that string before authentication completes. RCE requires both reachable attacker input and shell interpretation; neither `mod_perl` nor URI access alone creates command injection.<sup>[[1]](#references)</sup> 18 19 Risky Perl execution primitives include:<sup>[[4]](#references)</sup> 20 21 - Backticks / `qx//`: ``my $out = `cmd ...`;``. 22 - One-argument `system STRING` when the string contains shell metacharacters; list form (`system PROGRAM, LIST`) avoids shell parsing. 23 - Two-argument `open` with a pipe expression, such as `open my $fh, "cmd |"` or `"| cmd"`. Prefer three-argument `open` and explicit argument lists. 24 - `IPC::Open3` with one command scalar can inherit Perl's single-string shell handling. Pass the program and arguments as separate list elements when no shell is required.<sup>[[5]](#references)</sup> 25 - An explicit shell such as `system('/bin/sh', '-c', $attacker_string)`, which is dangerous even though it uses list form. 26 27 Minimal vulnerable shape observed in the wild:<sup>[[1]](#references)</sup> 28 ```perl 29 sub getCASURL { 30 ... 31 my $exec_cmd = "..."; 32 if ($type eq 'login') { 33 $exec_cmd .= $uri; # $uri from $r->uri() → attacker-controlled 34 my $out = `$exec_cmd`; # backticks = shell 35 } 36 } 37 ``` 38 Key reachability considerations in `mod_perl`:<sup>[[1]](#references)</sup> 39 40 - **Handler registration**: `httpd.conf` must route the request into the Perl module, for example with `PerlModule MOD_SEC_EMC::AccessHandler` and an applicable access-handler configuration. 41 - **Vulnerable branch**: The Dell chain required the unauthenticated login flow (`type eq "login"`), reached by omitting the expected authentication cookie. 42 - **Resolvable path**: The requested URI must fall within a scope processed by the handler. Otherwise the sink is never reached. 43 44 ### Exploitation workflow <sup>[[1]](#references)</sup> 45 1) Inspect httpd.conf for PerlModule/MOD_PERL handler scopes to find a resolvable path processed by the handler. 46 2) Send an unauthenticated request so the login redirect path is taken (type == "login"). 47 3) Place shell metacharacters in the request-URI path so $r->uri() carries your payload into the command string. 48 49 Example HTTP PoC (path injection via ';') 50 ```http 51 GET /ui/health;id HTTP/1.1 52 Host: target 53 Connection: close 54 ``` 55 ### Payload notes 56 - Try separators such as `;`, `&&`, `|`, backticks, `$()`, and encoded newlines (`%0A`) according to the surrounding quote context. 57 - If other arguments are quoted but the URI remains raw in one branch, an end-of-string payload such as `;id#` or `&&/usr/bin/id#` may terminate the intended command and comment the remainder. 58 59 ### Hardening 60 - Do not build shell strings. Prefer argument-vector execution: `system('/usr/bin/curl', '--silent', '--', $safe_url)`.<sup>[[4]](#references)</sup> 61 - If a shell is unavoidable, escape strictly and consistently across all branches; treat $r->uri() as hostile. Consider URI::Escape for paths/queries and strong allowlists. 62 - Avoid backticks/qx// for command execution; capture output via open3/list form if truly needed without invoking a shell. 63 - In mod_perl handlers, keep auth/redirect code paths free of command execution or ensure identical sanitization across branches to avoid “fixed everywhere but one branch” regressions. 64 65 ### Vulnerability hunting 66 - Patch-diff modules that assemble shell commands; look for inconsistent quoting between branches (e.g., if ($type eq 'login') left unescaped). 67 - Grep for backticks, qx//, open\s*\(|\||, and system\s*\(\s*" to find string-based shells. Build a call graph from sink to request entry ($r) to verify pre-auth reachability. 68 69 Real-world case: Dell UnityVSA pre-auth RCE (CVE-2025-36604)<sup>[[1]](#references)[[2]](#references)[[3]](#references)</sup> 70 - Pre-auth command injection via backticks in AccessTool.pm:getCASURL when type == "login" concatenated raw $uri ($r->uri()). 71 - Reachable through MOD_SEC_EMC::AccessHandler → make_return_address($r) → getCASLoginURL(..., type="login") → getCASURL(..., $uri, 'login'). 72 - Practical nuance: use a resolvable path covered by the handler; otherwise the module won’t execute and the sink won’t be hit. 73 74 ## References 75 76 - [1] [It’s Never Simple Until It Is: Dell UnityVSA Pre‑Auth Command Injection (CVE‑2025‑36604)](https://labs.watchtowr.com/its-never-simple-until-it-is-dell-unityvsa-pre-auth-command-injection-cve-2025-36604/) 77 - [2] [Dell PSIRT DSA‑2025‑281 – Security update for Dell Unity/UnityVSA/Unity XT](https://www.dell.com/support/kbdoc/en-uk/000350756/dsa-2025-281-security-update-for-dell-unity-dell-unityvsa-and-dell-unity-xt-security-update-for-multiple-vulnerabilities) 78 - [3] [watchTowr Detection Artefact Generator – Dell UnityVSA Pre‑Auth CVE‑2025‑36604](https://github.com/watchtowrlabs/watchTowr-vs-Dell-UnityVSA-PreAuth-CVE-2025-36604) 79 - [4] [Perl documentation — `system`, `exec`, and avoiding the shell](https://perldoc.perl.org/functions/system) 80 - [5] [Perl documentation — `IPC::Open3`](https://perldoc.perl.org/IPC::Open3)