diff --git a/src/macos-hardening/macos-red-teaming/macos-mdm/README.md b/src/macos-hardening/macos-red-teaming/macos-mdm/README.md index b87c35258..8ce8bb74a 100644 --- a/src/macos-hardening/macos-red-teaming/macos-mdm/README.md +++ b/src/macos-hardening/macos-red-teaming/macos-mdm/README.md @@ -2,146 +2,202 @@ {{#include ../../../banners/hacktricks-training.md}} -**macOS MDM에 대해 알아보려면 다음을 확인하세요:** +**macOS MDM에 대해 알아보려면 확인:** - [https://www.youtube.com/watch?v=ku8jZe-MHUU](https://www.youtube.com/watch?v=ku8jZe-MHUU) - [https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe) -## 기본 사항 +## 기본 -### **MDM (모바일 장치 관리) 개요** +### **MDM (Mobile Device Management) 개요** -[모바일 장치 관리](https://en.wikipedia.org/wiki/Mobile_device_management) (MDM)는 스마트폰, 노트북 및 태블릿과 같은 다양한 최종 사용자 장치를 관리하는 데 사용됩니다. 특히 Apple의 플랫폼(iOS, macOS, tvOS)에 대해, 이는 일련의 전문 기능, API 및 관행을 포함합니다. MDM의 작동은 상용 또는 오픈 소스인 호환 MDM 서버에 의존하며, [MDM 프로토콜](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)을 지원해야 합니다. 주요 사항은 다음과 같습니다: +[Mobile Device Management](https://en.wikipedia.org/wiki/Mobile_device_management) (MDM)은 스마트폰, 노트북, 태블릿 등 다양한 엔드유저 디바이스를 관리하기 위해 사용됩니다. 특히 Apple 플랫폼(iOS, macOS, tvOS)에 대해 특화된 기능, API 및 관행을 포함합니다. MDM의 운영은 상용 또는 오픈소스의 호환되는 MDM 서버에 의존하며, 해당 서버는 [MDM Protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)을 지원해야 합니다. 주요 내용은 다음과 같습니다: -- 장치에 대한 중앙 집중식 제어. +- 디바이스에 대한 중앙 집중식 제어. - MDM 프로토콜을 준수하는 MDM 서버에 의존. -- MDM 서버가 원격 데이터 삭제 또는 구성 설치와 같은 다양한 명령을 장치에 전송할 수 있는 기능. +- MDM 서버는 원격 데이터 삭제나 구성 설치와 같은 다양한 명령을 디바이스로 전송할 수 있음. -### **DEP (장치 등록 프로그램) 기본 사항** +### **DEP (Device Enrollment Program) 기초** -Apple에서 제공하는 [장치 등록 프로그램](https://www.apple.com/business/site/docs/DEP_Guide.pdf) (DEP)은 iOS, macOS 및 tvOS 장치에 대한 제로 터치 구성을 용이하게 하여 모바일 장치 관리(MDM)의 통합을 간소화합니다. DEP는 등록 프로세스를 자동화하여 장치가 최소한의 사용자 또는 관리 개입으로 즉시 작동할 수 있도록 합니다. 필수 측면은 다음과 같습니다: +[Device Enrollment Program](https://www.apple.com/business/site/docs/DEP_Guide.pdf) (DEP)은 Apple이 제공하는 것으로, iOS, macOS, tvOS 디바이스의 MDM 통합을 자동화하여 제로 터치 설정을 가능하게 합니다. DEP는 등록 프로세스를 자동화하여 디바이스가 박스에서 꺼내자마자 최소한의 사용자/관리자 개입으로 운영될 수 있게 합니다. 핵심 사항은 다음과 같습니다: -- 장치가 초기 활성화 시 미리 정의된 MDM 서버에 자율적으로 등록할 수 있도록 합니다. -- 주로 새 장치에 유용하지만 재구성 중인 장치에도 적용 가능합니다. -- 간단한 설정을 통해 장치를 신속하게 조직에서 사용할 수 있도록 합니다. +- 디바이스가 초기 활성화 시 미리 정의된 MDM 서버에 자동으로 등록되도록 허용. +- 주로 새 디바이스에 유용하지만 재구성되는 디바이스에도 적용 가능. +- 간단한 설정으로 조직에서 빠르게 사용 준비를 할 수 있게 함. -### **보안 고려 사항** +### **보안 고려사항** -DEP가 제공하는 등록의 용이성은 유익하지만 보안 위험을 초래할 수 있습니다. MDM 등록에 대한 보호 조치가 적절하게 시행되지 않으면 공격자는 이 간소화된 프로세스를 악용하여 자신의 장치를 조직의 MDM 서버에 등록하고 기업 장치로 가장할 수 있습니다. +DEP가 제공하는 간편한 등록은 유용하지만 보안 리스크를 동반할 수 있다는 점에 유의해야 합니다. MDM 등록에 대한 적절한 보호조치가 없다면 공격자가 이 간소화된 절차를 악용하여 조직의 MDM 서버에 자신의 디바이스를 기업 디바이스로 가장하여 등록할 수 있습니다. > [!CAUTION] -> **보안 경고**: 간소화된 DEP 등록은 적절한 보호 장치가 마련되지 않은 경우 조직의 MDM 서버에 무단 장치 등록을 허용할 수 있습니다. +> **보안 경고**: DEP의 간편한 등록 절차는 적절한 보호 장치가 없을 경우, 승인되지 않은 디바이스가 조직의 MDM 서버에 등록될 수 있게 할 수 있습니다. -### SCEP (간단한 인증서 등록 프로토콜)란 무엇인가요? +### SCEP (Simple Certificate Enrolment Protocol)란? -- TLS 및 HTTPS가 널리 퍼지기 전에 만들어진 비교적 오래된 프로토콜입니다. -- 클라이언트가 인증서를 부여받기 위해 **인증서 서명 요청** (CSR)을 보내는 표준화된 방법을 제공합니다. 클라이언트는 서버에 서명된 인증서를 요청합니다. +- TLS와 HTTPS가 널리 보급되기 전 만들어진 비교적 오래된 프로토콜. +- 클라이언트가 인증서를 발급받기 위해 **Certificate Signing Request**(CSR)를 표준화된 방식으로 서버에 전송할 수 있게 함. 클라이언트는 서버에 서명된 인증서를 요청함. -### 구성 프로파일(모바일 구성 파일)이란 무엇인가요? +### Configuration Profiles (aka mobileconfigs)란? -- Apple의 공식적인 **시스템 구성 설정/강제 적용 방법**입니다. -- 여러 페이로드를 포함할 수 있는 파일 형식입니다. -- 속성 목록(XML 형식)을 기반으로 합니다. -- “출처를 검증하고, 무결성을 보장하며, 내용을 보호하기 위해 서명 및 암호화될 수 있습니다.” 기본 사항 — 페이지 70, iOS 보안 가이드, 2018년 1월. +- Apple이 시스템 구성을 설정/강제하기 위해 제공하는 공식 방식. +- 여러 페이로드를 포함할 수 있는 파일 포맷. +- property lists(XML 형식)를 기반으로 함. +- “can be signed and encrypted to validate their origin, ensure their integrity, and protect their contents.” — Basics — Page 70, iOS Security Guide, January 2018. ## 프로토콜 ### MDM -- APNs (**Apple 서버**) + RESTful API (**MDM** **벤더** 서버)의 조합 -- **통신**은 **장치**와 **장치 관리** **제품**과 관련된 서버 간에 발생합니다. -- **명령**은 **plist 인코딩된 사전** 형식으로 MDM에서 장치로 전달됩니다. -- 모든 것이 **HTTPS**를 통해 이루어집니다. MDM 서버는 (대개) 핀 고정됩니다. -- Apple은 인증을 위해 MDM 벤더에게 **APNs 인증서**를 부여합니다. +- APNs(**Apple server**s) + RESTful API(**MDM** **vendor** servers)의 결합 +- **device**와 해당 **device management product**에 연동된 서버 간의 **통신** +- **Commands**는 **plist-encoded dictionaries** 형태로 MDM에서 디바이스로 전달됨 +- 모두 **HTTPS**로 통신. MDM 서버는 (일반적으로) pinning 되어 있을 수 있음. +- Apple은 인증을 위해 MDM 벤더에 **APNs certificate**를 발급함 ### DEP -- **3개의 API**: 1개는 리셀러용, 1개는 MDM 벤더용, 1개는 장치 식별용(문서화되지 않음): -- 소위 [DEP "클라우드 서비스" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). 이는 MDM 서버가 특정 장치와 DEP 프로파일을 연결하는 데 사용됩니다. -- [Apple 공인 리셀러가 사용하는 DEP API](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html)로 장치를 등록하고, 등록 상태를 확인하며, 거래 상태를 확인합니다. -- 문서화되지 않은 비공식 DEP API. 이는 Apple 장치가 자신의 DEP 프로파일을 요청하는 데 사용됩니다. macOS에서는 `cloudconfigurationd` 바이너리가 이 API를 통해 통신하는 책임이 있습니다. -- 더 현대적이고 **JSON** 기반입니다(대비 plist). -- Apple은 MDM 벤더에게 **OAuth 토큰**을 부여합니다. +- **3개의 API**: 리셀러용 1개, MDM 벤더용 1개, 디바이스 신원용(비공개) 1개 +- 소위 말하는 [DEP "cloud service" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). MDM 서버가 DEP 프로파일을 특정 디바이스와 연동하기 위해 사용됨. +- [Apple Authorized Resellers가 사용하는 DEP API](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html)로 디바이스 등록, 등록 상태 확인, 트랜잭션 상태 확인 등에 사용됨. +- 비공개의 undocumented DEP API. Apple 디바이스가 자신의 DEP 프로파일을 요청하는 데 사용됨. macOS에서는 `cloudconfigurationd` 바이너리가 이 API와 통신을 담당. +- plist 대비 보다 현대적이고 **JSON** 기반 +- Apple은 MDM 벤더에 **OAuth token**을 발급함 -**DEP "클라우드 서비스" API** +**DEP "cloud service" API** - RESTful -- Apple에서 MDM 서버로 장치 기록 동기화 -- MDM 서버에서 Apple로 “DEP 프로파일” 동기화(나중에 장치에 전달됨) -- DEP “프로파일”에는 다음이 포함됩니다: -- MDM 벤더 서버 URL -- 서버 URL에 대한 추가 신뢰할 수 있는 인증서(선택적 핀 고정) -- 추가 설정(예: 설정 도우미에서 건너뛸 화면) +- Apple에서 MDM 서버로 디바이스 레코드를 동기화 +- MDM 서버에서 Apple로 “DEP profiles”을 동기화(나중에 Apple이 디바이스에 전달) +- DEP “profile”에는 다음이 포함됨: + - MDM vendor 서버 URL + - 서버 URL에 대한 추가 신뢰 인증서(선택적 pinning) + - 추가 설정(예: Setup Assistant에서 건너뛸 화면들) -## 일련 번호 +## 시리얼 번호 -2010년 이후 제조된 Apple 장치는 일반적으로 **12자리 알phanumeric** 일련 번호를 가지며, **첫 세 자리는 제조 위치**를 나타내고, 다음 **두 자리는 제조 연도**와 **주**를 나타내며, 다음 **세 자리는 고유 식별자**를 제공하고, **마지막 네 자리는 모델 번호**를 나타냅니다. +2010년 이후 제조된 Apple 디바이스는 일반적으로 **12글자의 영숫자** 시리얼 번호를 가지며, 처음 **3자리**는 제조 위치, 다음 **2자리**는 제조 연도 및 주, 다음 **3자리**는 고유 식별자, 마지막 **4자리**는 모델 번호를 나타냅니다. {{#ref}} macos-serial-number.md {{#endref}} -## 등록 및 관리 단계 +## 등록 및 관리 절차 -1. 장치 기록 생성 (리셀러, Apple): 새 장치에 대한 기록이 생성됩니다. -2. 장치 기록 할당 (고객): 장치가 MDM 서버에 할당됩니다. -3. 장치 기록 동기화 (MDM 벤더): MDM이 장치 기록을 동기화하고 DEP 프로파일을 Apple에 푸시합니다. -4. DEP 체크인 (장치): 장치가 자신의 DEP 프로파일을 받습니다. -5. 프로파일 검색 (장치) -6. 프로파일 설치 (장치) a. MDM, SCEP 및 루트 CA 페이로드 포함 -7. MDM 명령 발행 (장치) +1. Device record 생성(Reseller, Apple): 새 디바이스의 레코드가 생성됨 +2. Device record 할당(Customer): 디바이스가 MDM 서버에 할당됨 +3. Device record 동기화(MDM vendor): MDM은 디바이스 레코드를 동기화하고 DEP 프로파일을 Apple에 푸시함 +4. DEP 체크인(Device): 디바이스가 자신의 DEP 프로파일을 가져옴 +5. Profile retrieval(Device) +6. Profile 설치(Device) — 예: MDM, SCEP 및 root CA 페이로드 포함 +7. MDM 명령 발행(Device) ![](<../../../images/image (694).png>) -파일 `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd`는 등록 프로세스의 **고급 "단계"**로 간주될 수 있는 기능을 내보냅니다. +파일 `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd`는 등록 프로세스의 고수준 "단계"로 간주될 수 있는 함수들을 export합니다. -### 단계 4: DEP 체크인 - 활성화 기록 가져오기 +### Step 4: DEP 체크인 - Activation Record 얻기 -이 프로세스의 일부는 **사용자가 Mac을 처음 부팅할 때**(또는 완전 초기화 후) 발생합니다. +이 단계는 사용자가 Mac을 처음 부팅할 때(또는 완전 초기화 후) 발생합니다. ![](<../../../images/image (1044).png>) -또는 `sudo profiles show -type enrollment`을 실행할 때 +또는 `sudo profiles show -type enrollment` 실행 시에도 발생 -- **장치가 DEP 활성화되었는지 여부를 확인합니다.** -- 활성화 기록은 **DEP “프로파일”**의 내부 이름입니다. -- 장치가 인터넷에 연결되면 시작됩니다. -- **`CPFetchActivationRecord`**에 의해 구동됩니다. -- **`cloudconfigurationd`**가 XPC를 통해 구현합니다. **"설정 도우미"**(장치가 처음 부팅될 때) 또는 **`profiles`** 명령이 이 데몬에 연락하여 활성화 기록을 검색합니다. -- LaunchDaemon (항상 root로 실행됨) +- **디바이스가 DEP 활성화인지 여부 판단** +- Activation Record는 내부적으로 **DEP “profile”**의 명칭임 +- 디바이스가 인터넷에 연결되는 즉시 시작됨 +- **`CPFetchActivationRecord`**에 의해 구동 +- **`cloudconfigurationd`**가 XPC를 통해 구현. **Setup Assistant**(디바이스가 처음 부팅될 때)나 `profiles` 명령이 이 데몬에 연락해 activation record를 가져옴. +- LaunchDaemon(항상 root로 실행) -활성화 기록을 가져오기 위해 **`MCTeslaConfigurationFetcher`**가 수행하는 몇 가지 단계를 따릅니다. 이 프로세스는 **Absinthe**라는 암호화를 사용합니다. +Activation Record를 얻기 위해 **`MCTeslaConfigurationFetcher`**가 수행하는 몇 단계가 있으며, 이 과정은 **Absinthe**라는 암호화를 사용합니다. -1. **인증서 검색** -1. GET [https://iprofiles.apple.com/resource/certificate.cer](https://iprofiles.apple.com/resource/certificate.cer) -2. 인증서에서 상태 **초기화** (**`NACInit`**) -1. 다양한 장치 특정 데이터를 사용합니다(예: **`IOKit`를 통한 일련 번호**). -3. **세션 키 검색** -1. POST [https://iprofiles.apple.com/session](https://iprofiles.apple.com/session) -4. 세션 설정 (**`NACKeyEstablishment`**) -5. 요청하기 -1. POST [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile)로 데이터 `{ "action": "RequestProfileConfiguration", "sn": "" }` 전송 -2. JSON 페이로드는 Absinthe로 암호화됩니다(**`NACSign`**). -3. 모든 요청은 HTTPs를 통해 이루어지며, 내장된 루트 인증서가 사용됩니다. +1. **certificate** 가져오기 + 1. GET [https://iprofiles.apple.com/resource/certificate.cer](https://iprofiles.apple.com/resource/certificate.cer) +2. 인증서로부터 상태 초기화(**`NACInit`**) + 1. 다양한 디바이스 특정 데이터를 사용(예: **Serial Number via `IOKit`**) +3. **session key** 가져오기 + 1. POST [https://iprofiles.apple.com/session](https://iprofiles.apple.com/session) +4. 세션 수립(**`NACKeyEstablishment`**) +5. 요청 수행 + 1. POST to [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile) 에 데이터 `{ "action": "RequestProfileConfiguration", "sn": "" }` 전송 + 2. JSON 페이로드는 Absinthe(**`NACSign`**)로 암호화됨 + 3. 모든 요청은 HTTPS, 내장된 루트 인증서를 사용 ![](<../../../images/image (566) (1).png>) -응답은 다음과 같은 중요한 데이터를 포함하는 JSON 사전입니다: +응답은 다음과 같은 중요한 데이터를 포함하는 JSON 딕셔너리입니다: -- **url**: 활성화 프로파일을 위한 MDM 벤더 호스트의 URL -- **anchor-certs**: 신뢰할 수 있는 앵커로 사용되는 DER 인증서 배열 +- **url**: activation profile을 제공하는 MDM vendor 호스트의 URL +- **anchor-certs**: 신뢰 앵커로 사용되는 DER 인증서 배열 -### **단계 5: 프로파일 검색** +### **Step 5: Profile Retrieval** ![](<../../../images/image (444).png>) -- **DEP 프로파일**에 제공된 **url**로 요청이 전송됩니다. -- 제공된 경우 **앵커 인증서**가 **신뢰성 평가**에 사용됩니다. -- 알림: **DEP 프로파일의 anchor_certs** 속성 -- **요청은 장치 식별이 포함된 간단한 .plist**입니다. -- 예: **UDID, OS 버전**. -- CMS 서명, DER 인코딩 -- **장치 식별 인증서(APNS에서)**를 사용하여 서명됩니다. -- **인증서 체인**에는 만료된 **Apple iPhone Device CA**가 포함됩니다. +- 요청은 **DEP 프로파일에 제공된 url**로 전송됨. +- **Anchor certificates**가 제공되면 신뢰 평가에 사용됨. +- 참고: DEP 프로파일의 **anchor_certs** 속성 +- **요청은 간단한 .plist**로 디바이스 식별 정보를 담음 +- 예: **UDID, OS version** +- CMS-signed, DER-encoded +- APNS의 **device identity certificate**로 서명됨 +- **Certificate chain**에는 만료된 **Apple iPhone Device CA**가 포함될 수 있음 -![](<../../../images/image (567) (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) +![](<../../../images/image (567) (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2).png>) + +### Step 6: Profile Installation + +- 일단 받아오면 **프로파일은 시스템에 저장됨** +- 이 단계는 (Setup Assistant인 경우) 자동으로 시작됨 +- **`CPInstallActivationProfile`**에 의해 구동 +- mdmclient가 XPC를 통해 구현 +- 컨텍스트에 따라 LaunchDaemon(root) 또는 LaunchAgent(사용자)로 실행 +- Configuration profiles은 설치할 여러 페이로드를 가짐 +- 프레임워크는 플러그인 기반 아키텍처로 페이로드를 설치 +- 각 페이로드 타입은 플러그인과 연동 +- 프레임워크 내부의 XPC이거나 전통적 Cocoa(ManagedClient.app)일 수 있음 +- 예시: + - Certificate Payloads는 CertificateService.xpc 사용 + +일반적으로 MDM 벤더가 제공하는 **activation profile**에는 다음과 같은 페이로드가 포함됩니다: + +- `com.apple.mdm`: 디바이스를 MDM에 **enroll**하기 위한 페이로드 +- `com.apple.security.scep`: 디바이스에 **client certificate**를 안전하게 제공하기 위한 SCEP 페이로드 +- `com.apple.security.pem`: 시스템 키체인에 **trusted CA 인증서**를 설치하기 위한 PEM 페이로드 +- MDM 페이로드 설치는 문서상의 **MDM check-in**에 해당 +- 페이로드는 다음과 같은 주요 속성을 포함: + - MDM Check-In URL(**`CheckInURL`**) + - MDM Command Polling URL(**`ServerURL`**) + 이를 트리거하는 APNs topic +- MDM 페이로드를 설치하려면 요청이 **`CheckInURL`**로 전송됨 +- **`mdmclient`**에서 구현 +- MDM 페이로드는 다른 페이로드에 의존할 수 있음 +- 특정 인증서에 요청을 pinning하도록 허용: + - 속성: **`CheckInURLPinningCertificateUUIDs`** + - 속성: **`ServerURLPinningCertificateUUIDs`** + - PEM 페이로드를 통해 전달됨 +- 디바이스에 identity certificate를 부여할 수 있음: + - 속성: IdentityCertificateUUID + - SCEP 페이로드를 통해 전달됨 + +### Step 7: Listening for MDM commands + +- MDM 체크인이 완료되면, 벤더는 **APNs를 사용해 푸시 알림을 발행**할 수 있음 +- 수신 시 **`mdmclient`**가 처리 +- MDM 명령을 폴링하려면 요청이 ServerURL로 전송됨 +- 이전에 설치된 MDM 페이로드를 사용: + - **`ServerURLPinningCertificateUUIDs`**로 요청 pinning + - **`IdentityCertificateUUID`**로 TLS 클라이언트 인증서 사용 + +## 공격 + +### 다른 조직에 디바이스 등록 + +앞서 언급한 바와 같이, 디바이스를 어떤 조직에 등록하려고 시도할 때에는 **그 조직에 속한 Serial Number만 있으면** 됩니다. 일단 디바이스가 등록되면 여러 조직은 새 디바이스에 민감한 데이터를 설치할 수 있습니다: 인증서, 애플리케이션, WiFi 비밀번호, VPN 구성 등([and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf)).\ +따라서 등록 프로세스가 적절히 보호되지 않으면 이는 공격자에게 위험한 진입점이 될 수 있습니다. + +{{#ref}} +enrolling-devices-in-other-organisations.md +{{#endref}} + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md b/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md index 365b0cb75..2e639e0b9 100644 --- a/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md +++ b/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md @@ -2,75 +2,75 @@ {{#include ../../banners/hacktricks-training.md}} -이 페이지는 Android 앱이 감지/루트 차단 기법을 탐지하거나 TLS 핀닝을 강제할 때 동적 분석을 재개하기 위한 실용적인 워크플로를 제공합니다. 빠른 분류, 일반적인 탐지 및 가능한 경우 재포장 없이 우회하기 위한 복사-붙여넣기 가능한 훅/전술에 중점을 둡니다. +이 페이지는 instrumentation을 탐지/차단하거나 TLS pinning을 적용하는 Android 앱에 대해 dynamic analysis를 다시 수행할 수 있도록 실용적인 워크플로우를 제공합니다. 빠른 분류, 흔한 탐지 기법, 그리고 가능하면 repacking 없이 우회할 수 있는 복사·붙여넣기 가능한 hooks/전술에 중점을 둡니다. -## Detection Surface (앱이 확인하는 것) +## Detection Surface (what apps check) -- 루트 확인: su 바이너리, Magisk 경로, getprop 값, 일반적인 루트 패키지 -- Frida/디버거 확인 (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), /proc 스캔, classpath, 로드된 라이브러리 -- 네이티브 안티-디버그: ptrace(), 시스템 호출, anti-attach, 중단점, 인라인 훅 -- 초기화 확인: Application.onCreate() 또는 기기가 존재할 경우 충돌하는 프로세스 시작 훅 -- TLS 핀닝: 사용자 정의 TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt 핀닝, 네이티브 핀 +- Root checks: su binary, Magisk paths, getprop values, common root packages +- Frida/debugger checks (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs +- Native anti‑debug: ptrace(), syscalls, anti‑attach, breakpoints, inline hooks +- Early init checks: Application.onCreate() or process start hooks that crash if instrumentation is present +- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins -## Step 1 — 빠른 승리: Magisk DenyList로 루트 숨기기 +## Step 1 — Quick win: hide root with Magisk DenyList -- Magisk에서 Zygisk 활성화 -- DenyList 활성화, 대상 패키지 추가 -- 재부팅 및 재테스트 +- Enable Zygisk in Magisk +- Enable DenyList, add the target package +- Reboot and retest -많은 앱은 명백한 지표(su/Magisk 경로/getprop)만 확인합니다. DenyList는 종종 단순한 확인을 무력화합니다. +많은 앱은 su/Magisk 경로/getprop 같은 명확한 지표만 확인합니다. DenyList는 종종 이런 단순한 검사들을 무력화합니다. References: - Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk -## Step 2 — 30초 Frida Codeshare 테스트 +## Step 2 — 30‑second Frida Codeshare tests -깊이 파고들기 전에 일반적인 드롭인 스크립트를 시도해 보세요: +딥다이브 전에 흔히 쓰이는 drop‑in 스크립트를 먼저 시도해 보세요: - anti-root-bypass.js - anti-frida-detection.js - hide_frida_gum.js -예: +Example: ```bash frida -U -f com.example.app -l anti-frida-detection.js ``` -이들은 일반적으로 Java 루트/디버그 검사, 프로세스/서비스 스캔 및 네이티브 ptrace()를 스텁합니다. 보호가 약한 앱에서 유용하며, 강화된 타겟은 맞춤형 후크가 필요할 수 있습니다. +이들은 일반적으로 Java의 root/debug checks, process/service scans, 그리고 native ptrace()를 스텁 처리합니다. 경미하게 보호된 앱에서 유용하지만, 강화된 대상은 맞춤형 훅이 필요할 수 있습니다. - Codeshare: https://codeshare.frida.re/ -## Step 3 — 초기 탐지기를 늦게 연결하여 우회하기 +## Step 3 — init-time detectors를 늦게 attach하여 우회하기 -많은 탐지는 프로세스 생성/onCreate() 중에만 실행됩니다. 생성 시 주입(-f) 또는 가젯이 포착되며, UI 로드 후에 연결하면 우회할 수 있습니다. +많은 탐지들은 process spawn/onCreate() 동안에만 동작합니다. Spawn‑time injection (-f)이나 gadgets는 차단되므로, UI가 로드된 이후에 attach하면 우회할 수 있습니다. ```bash # Launch the app normally (launcher/adb), wait for UI, then attach frida -U -n com.example.app # Or with Objection to attach to running process aobjection --gadget com.example.app explore # if using gadget ``` -이 작업이 성공하면 세션을 안정적으로 유지하고 매핑 및 스텁 검사를 진행합니다. +이 방법이 작동하면 세션을 안정적으로 유지한 뒤 map 및 stub checks로 진행하세요. -## 4단계 — Jadx 및 문자열 검색을 통한 탐지 로직 매핑 +## Step 4 — Jadx와 string hunting을 통해 탐지 로직 매핑 -Jadx의 정적 분류 키워드: +Static triage keywords in Jadx: - "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger" -일반적인 Java 패턴: +Typical Java patterns: ```java public boolean isFridaDetected() { return getRunningServices().contains("frida"); } ``` -Common APIs to review/hook: +검토/hook할 공통 API: - android.os.Debug.isDebuggerConnected - android.app.ActivityManager.getRunningAppProcesses / getRunningServices - java.lang.System.loadLibrary / System.load (native bridge) - java.lang.Runtime.exec / ProcessBuilder (probing commands) - android.os.SystemProperties.get (root/emulator heuristics) -## Step 5 — Runtime stubbing with Frida (Java) +## 5단계 — Runtime stubbing with Frida (Java) -Override custom guards to return safe values without repacking: +repacking 없이 안전한 값을 반환하도록 커스텀 가드를 오버라이드: ```js Java.perform(() => { const Checks = Java.use('com.example.security.Checks'); @@ -85,7 +85,7 @@ const AM = Java.use('android.app.ActivityManager'); AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); }; }); ``` -조기 크래시를 분류하나요? 죽기 직전에 클래스 덤프를 생성하여 감지 가능성이 높은 네임스페이스를 찾아보세요: +초기 크래시를 분류하고 있나요? 앱이 죽기 직전에 classes를 덤프해서 탐지 가능성이 높은 네임스페이스를 찾아보세요: ```js Java.perform(() => { Java.enumerateLoadedClasses({ @@ -94,7 +94,7 @@ onComplete: () => console.log('Done') }); }); ``` -의심스러운 메서드를 기록하고 중립화하여 실행 흐름을 확인합니다: +실행 흐름을 확인하기 위해 의심스러운 메서드를 로깅하고 무력화하세요: ```js Java.perform(() => { const Det = Java.use('com.example.security.DetectionManager'); @@ -104,24 +104,24 @@ return false; }; }); ``` -## Step 6 — Java 훅이 실패할 때 JNI/native 경로를 따라가세요 +## Step 6 — Java hooks가 실패할 때 JNI/native 경로를 따라가세요 -JNI 진입점을 추적하여 네이티브 로더와 탐지 초기화를 찾습니다: +JNI entry points를 추적하여 native loaders와 detection init을 찾아보세요: ```bash frida-trace -n com.example.app -i "JNI_OnLoad" ``` -번들된 .so 파일의 빠른 네이티브 트리아지: +번들된 .so 파일의 빠른 네이티브 분류: ```bash # List exported symbols & JNI nm -D libfoo.so | head objdump -T libfoo.so | grep Java_ strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root' ``` -인터랙티브/네이티브 리버싱: +인터랙티브/네이티브 reversing: - Ghidra: https://ghidra-sre.org/ - r2frida: https://github.com/nowsecure/r2frida -예시: libc에서 간단한 안티 디버그를 무력화하기 위해 ptrace를 중립화: +예시: ptrace를 무력화하여 libc의 간단한 anti‑debug를 무력화: ```js const ptrace = Module.findExportByName(null, 'ptrace'); if (ptrace) { @@ -130,40 +130,43 @@ return -1; // pretend failure }, 'int', ['int', 'int', 'pointer', 'pointer'])); } ``` -See also: {{#ref}} +참고: +{{#ref}} reversing-native-libraries.md {{#endref}} -## Step 7 — Objection 패칭 (임베드 가젯 / 스트립 기본) +## 7단계 — Objection patching (embed gadget / strip basics) -런타임 훅보다 리패킹을 선호할 때, 시도해 보세요: +repacking을 runtime hooks보다 선호한다면, 시도해보세요: ```bash objection patchapk --source app.apk ``` -노트: -- apktool이 필요합니다; 빌드 문제를 피하기 위해 공식 가이드에서 최신 버전을 확인하세요: https://apktool.org/docs/install -- Gadget injection은 루트 없이도 instrumentation을 가능하게 하지만, 더 강력한 init‑time 체크에 의해 여전히 감지될 수 있습니다. +참고: +- apktool이 필요합니다; 빌드 문제를 피하려면 공식 가이드에서 최신 버전을 사용하세요: https://apktool.org/docs/install +- Gadget injection은 root 없이 instrumentation을 가능하게 하지만 더 강력한 init‑time 검사에는 여전히 감지될 수 있습니다. 참조: - Objection: https://github.com/sensepost/objection -## 8단계 — 대체: 네트워크 가시성을 위한 TLS pinning 패치 +## Step 8 — 대체 방법: 네트워크 가시성 확보를 위해 TLS pinning 패치 -instrumentation이 차단된 경우, pinning을 정적으로 제거하여 여전히 트래픽을 검사할 수 있습니다: +instrumentation이 차단된 경우, pinning을 정적으로 제거해서 트래픽을 여전히 검사할 수 있습니다: ```bash apk-mitm app.apk # Then install the patched APK and proxy via Burp/mitmproxy ``` - 도구: https://github.com/shroudedcode/apk-mitm -- 네트워크 구성 CA‑trust 트릭(및 Android 7+ 사용자 CA 신뢰)에 대한 내용은 다음을 참조하세요: +- 네트워크 구성 CA‑trust tricks (및 Android 7+ user CA trust)에 대해서는 다음을 참조: + {{#ref}} make-apk-accept-ca-certificate.md {{#endref}} + {{#ref}} install-burp-certificate.md {{#endref}} -## 유용한 명령어 치트 시트 +## 유용한 명령 치트시트 ```bash # List processes and attach frida-ps -Uai @@ -181,12 +184,12 @@ objection --gadget com.example.app explore # Static TLS pinning removal apk-mitm app.apk ``` -## Tips & caveats +## 팁 및 주의사항 -- 앱이 시작할 때 충돌할 경우, 생성하는 것보다 늦게 연결하는 것을 선호하세요. -- 일부 탐지는 중요한 흐름(예: 결제, 인증)에서 다시 실행됩니다 — 탐색 중에 후크를 활성 상태로 유지하세요. -- 정적 및 동적 혼합: Jadx에서 문자열 검색으로 클래스를 선별한 후, 런타임에서 검증하기 위해 메서드를 후킹하세요. -- 강화된 앱은 패커와 네이티브 TLS 핀닝을 사용할 수 있습니다 — 네이티브 코드를 리버스 엔지니어링할 것으로 예상하세요. +- 앱이 실행 시 crash할 경우 spawning 대신 attaching을 늦게 적용하는 것을 권장합니다 +- 일부 detections는 결제(payment), 인증(auth) 같은 중요한 흐름에서 재실행됩니다 — navigation 동안 hooks를 활성 상태로 유지하세요 +- static과 dynamic을 혼합하세요: Jadx에서 string hunt로 shortlist classes를 찾아낸 뒤 hook methods로 runtime에서 검증하세요 +- 하드닝된 앱은 packers와 native TLS pinning을 사용할 수 있으므로 native code를 reverse해야 할 것으로 예상하세요 ## References diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 07359df25..32f705f7c 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -2,63 +2,70 @@ {{#include ../../banners/hacktricks-training.md}} -## What is -이 취약점은 **프론트엔드 프록시**와 **백엔드** 서버 간의 **비동기화**로 인해 **공격자**가 **HTTP 요청**을 **전송**할 수 있게 되며, 이 요청은 **프론트엔드** 프록시(로드 밸런스/리버스 프록시)에서는 **단일 요청**으로 해석되고 **백엔드** 서버에서는 **2개의 요청**으로 해석됩니다.\ -이로 인해 사용자는 자신의 요청 이후에 백엔드 서버에 도착하는 **다음 요청을 수정**할 수 있습니다. +## 개요 -### Theory +이 취약점은 **desyncronization**이 **front-end proxies**와 **back-end** 서버 사이에서 발생하여, **attacker**가 **send**한 HTTP **request**가 **front-end** proxies(로드 밸런서/리버스-프록시)에는 **single request**로, **back-end** 서버에는 **as 2 request**로 **interpreted**될 때 발생합니다.\ +이로 인해 사용자는 **modify the next request that arrives to the back-end server after his** 할 수 있게 됩니다. + +### 이론 [**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616) -> 메시지가 Transfer-Encoding 헤더 필드와 Content-Length 헤더 필드를 모두 포함하여 수신되면, 후자는 무시해야 합니다. +> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored. +> +> 메시지가 Transfer-Encoding 헤더 필드와 Content-Length 헤더 필드를 둘 다 포함하여 수신된 경우, 후자는 무시되어야 한다. **Content-Length** -> Content-Length 엔터티 헤더는 수신자에게 전송된 엔터티 본문의 크기를 바이트 단위로 나타냅니다. +> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient. +> +> Content-Length 엔터티 헤더는 수신자에게 전송되는 엔터티 본문의 크기를 바이트 단위로 나타냅니다. **Transfer-Encoding: chunked** -> Transfer-Encoding 헤더는 페이로드 본문을 사용자에게 안전하게 전송하는 데 사용되는 인코딩 형식을 지정합니다.\ -> Chunked는 대량의 데이터가 일련의 청크로 전송됨을 의미합니다. +> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\ +> Chunked means that large data is sent in a series of chunks +> +> Transfer-Encoding 헤더는 payload body를 안전하게 전송하기 위해 사용되는 인코딩 형식을 지정합니다.\ +> Chunked는 큰 데이터를 연속된 청크들로 전송함을 의미합니다. -### Reality +### 실제 -**프론트엔드**(로드 밸런스/리버스 프록시)는 _**content-length**_ 또는 _**transfer-encoding**_ 헤더를 처리하고 **백엔드** 서버는 다른 하나를 처리하여 두 시스템 간의 **비동기화**를 유발합니다.\ -이는 **공격자가 리버스 프록시**에 **하나의 요청을 전송**할 수 있게 하여 **백엔드** 서버가 이를 **2개의 서로 다른 요청으로 해석**하게 할 수 있으므로 매우 치명적일 수 있습니다. 이 기술의 **위험**은 **백엔드** 서버가 **주입된 2번째 요청**을 **다음 클라이언트**에서 온 것처럼 해석하고, 그 클라이언트의 **실제 요청**이 **주입된 요청의 일부**가 된다는 사실에 있습니다. +**Front-End**(로드-밸런서/리버스-프록시)가 _**Content-Length**_ 또는 _**Transfer-Encoding**_ 헤더를 처리하고, **Back-end** 서버가 _다른_ 헤더를 처리하면서 두 시스템 간에 **desyncronization**이 발생합니다.\ +이것은 매우 치명적일 수 있는데, **attacker**가 리버스-프록시에 한 요청을 보내면 **back-end** 서버는 그것을 **2개의 다른 요청**으로 해석할 수 있기 때문입니다. 이 기법의 위험은 **back-end** 서버가 **주입된 2번째 요청을 다음 클라이언트로부터 온 것으로 취급**하고, 해당 클라이언트의 실제 요청이 **주입된 요청의 일부**가 된다는 점에 있습니다. -### Particularities +### 세부사항 -HTTP에서 **새 줄 문자는 2바이트로 구성됩니다:** +HTTP에서 **new line** 문자는 2바이트로 구성된다는 점을 기억하세요: -- **Content-Length**: 이 헤더는 요청 본문의 **바이트 수**를 나타내기 위해 **10진수**를 사용합니다. 본문은 마지막 문자에서 끝나야 하며, **요청 끝에 새 줄이 필요하지 않습니다**. -- **Transfer-Encoding:** 이 헤더는 본문에서 **16진수**를 사용하여 **다음 청크의 바이트 수**를 나타냅니다. **청크**는 **새 줄**로 **끝나야** 하지만 이 새 줄은 **길이 지표에 포함되지 않습니다**. 이 전송 방법은 **크기 0의 청크로 끝나고 2개의 새 줄**로 이어져야 합니다: `0` -- **Connection**: 제 경험에 따르면 요청 스머글링의 첫 번째 요청에서는 **`Connection: keep-alive`**를 사용하는 것이 좋습니다. +- **Content-Length**: 이 헤더는 요청 본문의 바이트 수를 나타내는 **10진수**를 사용합니다. 본문은 마지막 문자에서 끝나는 것으로 기대되며, 요청 끝에 별도의 new line은 필요하지 않습니다. +- **Transfer-Encoding:** 이 헤더는 본문에서 다음 청크의 크기를 나타내는 **16진수** 숫자를 사용합니다. 청크는 **new line**으로 끝나야 하지만, 이 new line은 길이 표시에는 포함되지 않습니다. 이 전송 방식은 `0` 크기의 청크가 나오고 이어서 2개의 new line으로 끝나야 합니다: `0` +- **Connection**: 제 경험상 request Smuggling의 첫 요청에는 **`Connection: keep-alive`** 사용을 권장합니다. -## Basic Examples +## 기본 예제 > [!TIP] -> Burp Suite로 이를 악용하려고 할 때 **`Update Content-Length` 및 `Normalize HTTP/1 line endings`**를 리피터에서 비활성화하세요. 일부 도구는 새 줄, 캐리지 리턴 및 잘못된 content-length를 악용합니다. +> Burp Suite로 이 취약점을 시도할 때는 repeater에서 `Update Content-Length` 및 `Normalize HTTP/1 line endings`를 비활성화하세요. 일부 가젯은 newlines, carriage returns 및 malformed content-lengths를 악용합니다. -HTTP 요청 스머글링 공격은 프론트엔드와 백엔드 서버가 `Content-Length` (CL) 및 `Transfer-Encoding` (TE) 헤더를 해석하는 방식의 불일치를 이용하여 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, 및 **TE.TE** 형태로 나타날 수 있습니다. 각 유형은 프론트엔드와 백엔드 서버가 이러한 헤더를 우선시하는 방식의 고유한 조합을 나타냅니다. 취약점은 서버가 동일한 요청을 서로 다른 방식으로 처리하여 예상치 못한 결과와 잠재적으로 악의적인 결과를 초래하는 데서 발생합니다. +HTTP request smuggling 공격은 front-end와 back-end 서버가 `Content-Length`(CL)와 `Transfer-Encoding`(TE) 헤더를 해석하는 방식의 불일치를 악용하도록 모호한 요청을 전송하여 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, **TE.TE**의 형태로 나타납니다. 각 유형은 front-end와 back-end가 해당 헤더들을 우선적으로 처리하는 서로 다른 조합을 나타냅니다. 취약점은 동일한 요청을 서버들이 서로 다르게 처리하면서 발생하며, 이는 예기치 않은 및 악의적인 결과를 초래할 수 있습니다. -### Basic Examples of Vulnerability Types +### 취약점 유형의 기본 예시 ![https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../images/EKi5edAUUAAIPIK.jpg) > [!TIP] -> 이전 표에 TE.0 기술을 추가해야 하며, CL.0 기술과 유사하지만 Transfer Encoding을 사용합니다. +> 위 테이블에는 TE.0 기법을 추가해야 합니다. CL.0 기법과 유사하지만 Transfer-Encoding을 사용하는 방식입니다. #### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End) -- **프론트엔드 (CL):** `Content-Length` 헤더를 기반으로 요청을 처리합니다. -- **백엔드 (TE):** `Transfer-Encoding` 헤더를 기반으로 요청을 처리합니다. -- **공격 시나리오:** - -- 공격자는 `Content-Length` 헤더의 값이 실제 콘텐츠 길이와 일치하지 않는 요청을 보냅니다. -- 프론트엔드 서버는 `Content-Length` 값을 기반으로 전체 요청을 백엔드로 전달합니다. -- 백엔드 서버는 `Transfer-Encoding: chunked` 헤더로 인해 요청을 청크로 처리하며, 나머지 데이터를 별도의 후속 요청으로 해석합니다. -- **예시:** +- **Front-End (CL):** `Content-Length` 헤더를 기준으로 요청을 처리합니다. +- **Back-End (TE):** `Transfer-Encoding` 헤더를 기준으로 요청을 처리합니다. +- **Attack Scenario:** + - 공격자는 `Content-Length` 헤더 값이 실제 콘텐츠 길이와 일치하지 않는 요청을 전송합니다. + - front-end 서버는 `Content-Length` 값에 따라 전체 요청을 back-end로 전달합니다. + - back-end 서버는 `Transfer-Encoding: chunked` 헤더 때문에 요청을 청크 방식으로 처리하여 남은 데이터를 별도의 후속 요청으로 해석합니다. +- **Example:** ``` POST / HTTP/1.1 @@ -75,14 +82,13 @@ Foo: x #### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End) -- **프론트엔드 (TE):** `Transfer-Encoding` 헤더를 기반으로 요청을 처리합니다. -- **백엔드 (CL):** `Content-Length` 헤더를 기반으로 요청을 처리합니다. -- **공격 시나리오:** - -- 공격자는 청크 크기(`7b`)와 실제 콘텐츠 길이(`Content-Length: 4`)가 일치하지 않는 청크 요청을 보냅니다. -- 프론트엔드 서버는 `Transfer-Encoding`을 존중하여 전체 요청을 백엔드로 전달합니다. -- 백엔드 서버는 `Content-Length`를 존중하여 요청의 초기 부분(`7b` 바이트)만 처리하고 나머지는 의도하지 않은 후속 요청의 일부로 남깁니다. -- **예시:** +- **Front-End (TE):** `Transfer-Encoding` 헤더를 기준으로 요청을 처리합니다. +- **Back-End (CL):** `Content-Length` 헤더를 기준으로 요청을 처리합니다. +- **Attack Scenario:** + - 공격자는 청크 크기(`7b`)와 실제 콘텐츠 길이(`Content-Length: 4`)가 일치하지 않는 chunked 요청을 보냅니다. + - front-end 서버는 `Transfer-Encoding`을 존중하여 전체 요청을 back-end로 전달합니다. + - back-end 서버는 `Content-Length`만을 따르며 요청의 초기 부분(`7b` 바이트)만 처리하고, 나머지는 의도치 않은 후속 요청의 일부로 남깁니다. +- **Example:** ``` POST / HTTP/1.1 @@ -104,13 +110,12 @@ x= #### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation) -- **서버:** 두 서버 모두 `Transfer-Encoding`을 지원하지만, 하나는 난독화를 통해 이를 무시하도록 속일 수 있습니다. -- **공격 시나리오:** - -- 공격자는 난독화된 `Transfer-Encoding` 헤더가 포함된 요청을 보냅니다. -- 어떤 서버(프론트엔드 또는 백엔드)가 난독화를 인식하지 못하는지에 따라 CL.TE 또는 TE.CL 취약점이 악용될 수 있습니다. -- 요청의 처리되지 않은 부분은 한 서버에서 보았을 때 후속 요청의 일부가 되어 스머글링으로 이어집니다. -- **예시:** +- **Servers:** 둘 다 `Transfer-Encoding`을 지원하지만, 하나는 난독화를 통해 이를 인식하지 못하게 만들 수 있습니다. +- **Attack Scenario:** + - 공격자는 obfuscated된 `Transfer-Encoding` 헤더들을 포함한 요청을 보냅니다. + - 어느 서버(front-end 또는 back-end)가 난독화를 인식하지 못하느냐에 따라 CL.TE 또는 TE.CL 취약점이 발생할 수 있습니다. + - 한 서버가 처리하지 못한 요청의 나머지 부분이 후속 요청의 일부가 되어 smuggling이 발생합니다. +- **Example:** ``` POST / HTTP/1.1 @@ -131,9 +136,9 @@ Transfer-Encoding #### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)** -- 두 서버 모두 `Content-Length` 헤더만을 기반으로 요청을 처리합니다. -- 이 시나리오는 일반적으로 스머글링으로 이어지지 않으며, 두 서버가 요청 길이를 해석하는 방식이 일치합니다. -- **예시:** +- 양쪽 서버 모두 `Content-Length` 헤더만을 기준으로 요청을 처리합니다. +- 일반적으로 두 서버가 요청 길이를 동일하게 해석하므로 smuggling으로 이어지지 않습니다. +- **Example:** ``` POST / HTTP/1.1 @@ -146,9 +151,9 @@ Normal Request #### **CL.0 Scenario** -- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지며 요청 본문에 콘텐츠가 있음을 나타냅니다. 백엔드는 `Content-Length` 헤더를 무시하고(0으로 처리됨), 프론트엔드는 이를 파싱합니다. -- 이는 스머글링 공격을 이해하고 구성하는 데 중요하며, 서버가 요청의 끝을 결정하는 방식에 영향을 미칩니다. -- **예시:** +- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지는 상황을 가리킵니다. 이 경우 back-end는 `Content-Length`를 무시(0으로 처리)하지만 front-end는 이를 파싱합니다. +- 이는 smuggling을 이해하고 제작하는 데 중요합니다. 서버들이 요청의 끝을 어떻게 판단하는지에 영향을 미칩니다. +- **Example:** ``` POST / HTTP/1.1 @@ -161,9 +166,9 @@ Non-Empty Body #### TE.0 Scenario -- 이전과 유사하지만 TE를 사용합니다. -- 기술 [여기에서 보고됨](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/) -- **예시:** +- 이전과 유사하지만 TE를 사용하는 경우입니다. +- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/) +- **Example**: ``` OPTIONS / HTTP/1.1 Host: {HOST} @@ -181,34 +186,35 @@ x: X EMPTY_LINE_HERE EMPTY_LINE_HERE ``` -#### 웹 서버 파괴 +#### 웹 서버 중단시키기 -이 기술은 **초기 HTTP 데이터를 읽는 동안 웹 서버를 파괴할 수 있는** 시나리오에서 유용하지만 **연결을 닫지 않고** 사용할 수 있습니다. 이렇게 하면 HTTP 요청의 **본문**이 **다음 HTTP 요청**으로 간주됩니다. +이 기법은 초기 HTTP 데이터를 읽는 동안 **웹 서버를 중단시킬 수 있는** 상황에서도 유용하며, 특히 연결을 **닫지 않고** 유지할 수 있을 때 그렇습니다. 이렇게 하면 HTTP 요청의 **body**는 **next HTTP request**로 간주됩니다. -예를 들어, [**이 글**](https://mizu.re/post/twisty-python)에서 설명된 바와 같이, Werkzeug에서는 일부 **유니코드** 문자를 전송하여 서버를 **파괴**할 수 있었습니다. 그러나 HTTP 연결이 **`Connection: keep-alive`** 헤더로 생성된 경우 요청의 본문은 읽히지 않으며 연결은 여전히 열려 있으므로 요청의 **본문**은 **다음 HTTP 요청**으로 처리됩니다. +예를 들어, [**this writeup**](https://mizu.re/post/twisty-python)에서 설명된 것처럼, Werkzeug에서는 일부 **Unicode** 문자를 전송하면 서버가 **break**될 수 있었습니다. 그러나 HTTP 연결이 헤더 **`Connection: keep-alive`**로 생성되었다면 요청의 body는 읽히지 않고 연결은 계속 열려 있으므로, 요청의 **body**는 **next HTTP request**로 처리됩니다. -#### 홉-바이-홉 헤더를 통한 강제화 +#### hop-by-hop headers를 통한 강제 -홉-바이-홉 헤더를 악용하여 프록시에게 **Content-Length 또는 Transfer-Encoding 헤더를 삭제하도록 지시하여 HTTP 요청 스머글링을 악용할 수 있습니다**. +hop-by-hop headers를 악용하면 프록시에 **헤더 Content-Length 또는 Transfer-Encoding을 삭제하도록 지시하여 HTTP request smuggling을 악용할 수 있다**. ``` Connection: Content-Length ``` -더 많은 **hop-by-hop 헤더에 대한 정보**는 다음을 방문하세요: +For **more information about hop-by-hop headers** visit: + {{#ref}} ../abusing-hop-by-hop-headers.md {{#endref}} -## HTTP 요청 스머글링 찾기 +## Finding HTTP Request Smuggling -HTTP 요청 스머글링 취약점을 식별하는 것은 종종 타이밍 기법을 사용하여 달성할 수 있으며, 이는 조작된 요청에 대한 서버의 응답 시간을 관찰하는 데 의존합니다. 이러한 기법은 CL.TE 및 TE.CL 취약점을 감지하는 데 특히 유용합니다. 이러한 방법 외에도 이러한 취약점을 찾는 데 사용할 수 있는 다른 전략과 도구가 있습니다: +HTTP request smuggling 취약점을 식별하는 것은 종종 타이밍 기법을 통해 가능하며, 이는 조작된 요청에 대한 서버의 응답 시간이 얼마나 걸리는지를 관찰하는 데 의존합니다. 이러한 기법은 특히 CL.TE 및 TE.CL 취약점을 탐지하는 데 유용합니다. 이 방법들 외에도 취약점을 찾기 위해 사용할 수 있는 다른 전략과 도구들이 있습니다: -### 타이밍 기법을 사용한 CL.TE 취약점 찾기 +### Finding CL.TE Vulnerabilities Using Timing Techniques -- **방법:** +- **Method:** -- 애플리케이션이 취약한 경우, 추가 데이터를 기다리게 하는 요청을 전송합니다. -- **예시:** +- 애플리케이션이 취약한 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다. +- **Example:** ``` POST / HTTP/1.1 @@ -222,20 +228,20 @@ A 0 ``` -- **관찰:** -- 프론트엔드 서버는 `Content-Length`에 따라 요청을 처리하고 메시지를 조기에 차단합니다. -- 백엔드 서버는 청크 메시지를 기대하며 도착하지 않는 다음 청크를 기다려 지연이 발생합니다. +- **Observation:** +- 프론트엔드 서버가 `Content-Length` 기준으로 요청을 처리하고 메시지를 조기에 잘라냅니다. +- 백엔드 서버는 chunked 메시지를 기대하고 다음 청크를 기다리므로 응답 지연이 발생합니다. -- **지표:** -- 응답의 타임아웃 또는 긴 지연. -- 때때로 상세한 서버 정보와 함께 백엔드 서버에서 400 Bad Request 오류를 수신합니다. +- **Indicators:** +- 타임아웃 또는 긴 응답 지연. +- 때때로 상세한 서버 정보와 함께 백엔드에서 400 Bad Request 오류 수신. -### 타이밍 기법을 사용한 TE.CL 취약점 찾기 +### Finding TE.CL Vulnerabilities Using Timing Techniques -- **방법:** +- **Method:** -- 애플리케이션이 취약한 경우, 추가 데이터를 기다리게 하는 요청을 전송합니다. -- **예시:** +- 애플리케이션이 취약한 경우 백엔드 서버가 추가 데이터를 기다리게 만드는 요청을 전송합니다. +- **Example:** ``` POST / HTTP/1.1 @@ -248,42 +254,42 @@ Content-Length: 6 X ``` -- **관찰:** -- 프론트엔드 서버는 `Transfer-Encoding`에 따라 요청을 처리하고 전체 메시지를 전달합니다. -- 백엔드 서버는 `Content-Length`에 따라 메시지를 기대하며 도착하지 않는 추가 데이터를 기다려 지연이 발생합니다. +- **Observation:** +- 프론트엔드 서버가 `Transfer-Encoding` 기준으로 요청을 처리하고 전체 메시지를 전달합니다. +- 백엔드 서버는 `Content-Length` 기준의 메시지를 기대하고 추가 데이터를 기다리므로 지연이 발생합니다. -### 취약점을 찾기 위한 다른 방법 +### Other Methods to Find Vulnerabilities -- **차별적 응답 분석:** -- 요청의 약간 변형된 버전을 전송하고 서버 응답이 예상치 못한 방식으로 다르게 나타나는지 관찰하여 구문 분석 불일치를 나타냅니다. -- **자동화 도구 사용:** -- Burp Suite의 'HTTP Request Smuggler' 확장과 같은 도구는 다양한 형태의 모호한 요청을 전송하고 응답을 분석하여 이러한 취약점을 자동으로 테스트할 수 있습니다. -- **Content-Length 변동 테스트:** -- 실제 콘텐츠 길이에 맞지 않는 다양한 `Content-Length` 값을 가진 요청을 전송하고 서버가 이러한 불일치를 처리하는 방식을 관찰합니다. -- **Transfer-Encoding 변동 테스트:** -- 난독화되거나 잘못된 `Transfer-Encoding` 헤더를 가진 요청을 전송하고 프론트엔드와 백엔드 서버가 이러한 조작에 어떻게 다르게 반응하는지 모니터링합니다. +- **Differential Response Analysis:** +- 약간씩 다른 버전의 요청을 보내고 서버 응답에 예상치 못한 차이가 있는지 관찰하여 파싱 불일치를 탐지합니다. +- **Using Automated Tools:** +- Burp Suite의 'HTTP Request Smuggler' extension과 같은 도구는 모호한 형태의 다양한 요청을 자동으로 전송하고 응답을 분석하여 이러한 취약점을 테스트할 수 있습니다. +- **Content-Length Variance Tests:** +- 실제 콘텐츠 길이와 일치하지 않는 다양한 `Content-Length` 값을 가진 요청을 보내 서버가 이러한 불일치를 어떻게 처리하는지 관찰합니다. +- **Transfer-Encoding Variance Tests:** +- 난독화되거나 손상된 `Transfer-Encoding` 헤더가 포함된 요청을 전송하고 프론트엔드와 백엔드 서버가 이러한 조작에 대해 어떻게 다르게 반응하는지 모니터링합니다. -### HTTP 요청 스머글링 취약점 테스트 +### HTTP Request Smuggling Vulnerability Testing -타이밍 기법의 효과를 확인한 후, 클라이언트 요청을 조작할 수 있는지 확인하는 것이 중요합니다. 간단한 방법은 요청을 오염시키는 것을 시도하는 것입니다. 예를 들어, `/`에 대한 요청이 404 응답을 생성하도록 합니다. 이전에 논의된 `CL.TE` 및 `TE.CL` 예시는 클라이언트의 요청을 오염시켜 404 응답을 유도하는 방법을 보여줍니다. 클라이언트는 다른 리소스에 접근하려고 합니다. +타이밍 기법의 유효성을 확인한 후에는 클라이언트 요청이 조작 가능한지 검증하는 것이 중요합니다. 간단한 방법은 요청을 포이즈닝(poisoning)하는 것을 시도하는 것으로, 예를 들어 `/`에 대한 요청이 404 응답을 반환하도록 만드는 것입니다. 앞서 [Basic Examples](#basic-examples)에서 논의한 `CL.TE` 및 `TE.CL` 예시는 클라이언트가 다른 리소스에 접근하려는 상황에서도 클라이언트의 요청을 포이즈닝하여 404 응답을 유도하는 방법을 보여줍니다. -**주요 고려사항** +**Key Considerations** -다른 요청에 간섭하여 요청 스머글링 취약점을 테스트할 때 유의해야 할 사항: +다른 요청을 방해하여 request smuggling 취약점을 테스트할 때 유의할 점: -- **구별된 네트워크 연결:** "공격" 요청과 "정상" 요청은 별도의 네트워크 연결을 통해 전송되어야 합니다. 두 요청 모두 동일한 연결을 사용하는 것은 취약점의 존재를 검증하지 않습니다. -- **일관된 URL 및 매개변수:** 두 요청 모두 동일한 URL 및 매개변수 이름을 사용하도록 합니다. 현대 애플리케이션은 종종 URL 및 매개변수에 따라 특정 백엔드 서버로 요청을 라우팅합니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아지며, 이는 성공적인 공격을 위한 전제 조건입니다. -- **타이밍 및 경합 조건:** "정상" 요청은 "공격" 요청의 간섭을 감지하기 위해 다른 동시 애플리케이션 요청과 경쟁합니다. 따라서 "공격" 요청 직후에 "정상" 요청을 전송합니다. 바쁜 애플리케이션은 취약점 확인을 위한 결론을 내리기 위해 여러 번의 시도가 필요할 수 있습니다. -- **로드 밸런싱 문제:** 로드 밸런서 역할을 하는 프론트엔드 서버는 요청을 다양한 백엔드 시스템에 분배할 수 있습니다. "공격" 요청과 "정상" 요청이 서로 다른 시스템에 도달하면 공격은 성공하지 않습니다. 이 로드 밸런싱 측면은 취약점을 확인하기 위해 여러 번의 시도를 요구할 수 있습니다. -- **의도치 않은 사용자 영향:** 공격이 다른 사용자의 요청(탐지를 위해 보낸 "정상" 요청이 아님)에 의도치 않게 영향을 미친다면, 이는 공격이 다른 애플리케이션 사용자에게 영향을 미쳤음을 나타냅니다. 지속적인 테스트는 다른 사용자에게 방해가 될 수 있으므로 신중한 접근이 필요합니다. +- **Distinct Network Connections:** "attack" 요청과 "normal" 요청은 별개의 네트워크 연결을 통해 전송해야 합니다. 동일한 연결을 사용하면 취약점 존재를 검증할 수 없습니다. +- **Consistent URL and Parameters:** 두 요청에 대해 동일한 URL과 파라미터 이름을 사용하도록 하십시오. 현대 애플리케이션은 URL과 파라미터에 따라 특정 백엔드 서버로 라우팅하는 경우가 많습니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아져 공격 성공 확률이 증가합니다. +- **Timing and Racing Conditions:** 간섭을 감지하려는 "normal" 요청은 "attack" 요청과 경쟁하므로, "attack" 요청 직후 즉시 "normal" 요청을 보내야 합니다. 트래픽이 많은 애플리케이션에서는 명확한 취약점 확인을 위해 여러 번 시도해야 할 수 있습니다. +- **Load Balancing Challenges:** 프론트엔드 서버가 로드 밸런싱을 수행하면 요청이 서로 다른 백엔드 시스템으로 분배될 수 있습니다. "attack" 요청과 "normal" 요청이 다른 시스템에 할당되면 공격은 실패합니다. 이 때문에 취약점 확인을 위해 여러 번 시도해야 할 수 있습니다. +- **Unintended User Impact:** 공격이 의도치 않게 다른 사용자의 요청(테스트용 "normal" 요청이 아닌)에 영향을 미친다면, 이는 당신의 공격이 다른 애플리케이션 사용자의 요청에 영향을 준다는 의미입니다. 지속적인 테스트는 다른 사용자를 방해할 수 있으므로 주의가 필요합니다. -## HTTP/1.1 파이프라이닝 아티팩트와 진정한 요청 스머글링 구분하기 +## Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling -연결 재사용(keep-alive) 및 파이프라이닝은 동일한 소켓에서 여러 요청을 전송하는 테스트 도구에서 "스머글링"의 환상을 쉽게 생성할 수 있습니다. 무해한 클라이언트 측 아티팩트를 실제 서버 측 비동기화와 구분하는 방법을 배우세요. +Connection reuse (keep-alive) 및 pipelining은 동일한 소켓에서 여러 요청을 보내는 테스트 도구에서 쉽게 "smuggling"의 환상을 만들어냅니다. 무해한 클라이언트 측 아티팩트와 실제 서버 측 desync를 구분하는 법을 익히세요. -### 왜 파이프라이닝이 고전적인 오탐지를 생성하는가 +### Why pipelining creates classic false positives -HTTP/1.1은 단일 TCP/TLS 연결을 재사용하고 동일한 스트림에서 요청과 응답을 연결합니다. 파이프라이닝에서 클라이언트는 여러 요청을 연속으로 전송하고 순서대로 응답을 기대합니다. 일반적인 오탐지 사례는 잘못된 CL.0 스타일 페이로드를 단일 연결에서 두 번 재전송하는 것입니다: +HTTP/1.1은 단일 TCP/TLS 연결을 재사용하고 동일한 스트림에 요청과 응답을 연속으로 붙입니다. pipelining에서는 클라이언트가 여러 요청을 연속으로 전송하고 순서대로 응답받기를 기대합니다. 흔한 false-positive 사례는 단일 연결에서 변형된 CL.0-style payload를 두 번 재전송하는 것입니다: ``` POST / HTTP/1.1 Host: hackxor.net @@ -292,7 +298,7 @@ Content_Length: 47 GET /robots.txt HTTP/1.1 X: Y ``` -응답은 다음과 같을 수 있습니다: +원본 README.md 파일의 내용을 붙여 넣어 주세요. 해당 내용을 받은 뒤, 지시에 따라 코드·태그·링크 등을 그대로 유지하면서 영어 본문만 한국어로 번역해 드리겠습니다. ``` HTTP/1.1 200 OK Content-Type: text/html @@ -306,7 +312,7 @@ Content-Type: text/plain User-agent: * Disallow: /settings ``` -서버가 잘못된 `Content_Length`를 무시했다면, FE↔BE desync가 없습니다. 재사용을 통해, 클라이언트는 실제로 이 바이트 스트림을 전송했으며, 서버는 이를 두 개의 독립적인 요청으로 파싱했습니다: +서버가 잘못된 `Content_Length`를 무시했다면 FE↔BE desync는 발생하지 않습니다. 재사용 시, 클라이언트는 실제로 다음 바이트 스트림을 전송했으며, 서버는 이를 두 개의 독립된 요청으로 파싱했습니다: ``` POST / HTTP/1.1 Host: hackxor.net @@ -320,78 +326,78 @@ Content_Length: 47 GET /robots.txt HTTP/1.1 X: Y ``` -Impact: 없음. 클라이언트를 서버 프레이밍에서 분리했습니다. +Impact: 없음. 클라이언트의 프레이밍이 서버와 비동기화되었습니다. > [!TIP] -> 재사용/파이프라인에 의존하는 Burp 모듈: `requestsPerConnection>1`인 Turbo Intruder, "HTTP/1 연결 재사용"이 있는 Intruder, "순차적으로 그룹 전송(단일 연결)" 또는 "연결 재사용 활성화"가 있는 Repeater. +> 재사용/파이프라이닝에 의존하는 Burp 모듈: Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse". -### 리트머스 테스트: 파이프라인 또는 실제 비동기화? +### Litmus tests: pipelining or real desync? -1. 재사용 비활성화 및 재테스트 -- Burp Intruder/Repeater에서 HTTP/1 재사용을 끄고 "순차적으로 그룹 전송"을 피하십시오. -- Turbo Intruder에서 `requestsPerConnection=1`로 설정하고 `pipeline=False`로 설정하십시오. -- 동작이 사라지면, 클라이언트 측 파이프라인일 가능성이 높습니다. 연결 잠금/상태 유지 대상이나 클라이언트 측 비동기화가 아닌 경우입니다. -2. HTTP/2 중첩 응답 확인 -- HTTP/2 요청을 전송하십시오. 응답 본문에 완전한 중첩 HTTP/1 응답이 포함되어 있다면, 순수 클라이언트 아티팩트가 아닌 백엔드 파싱/비동기화 버그를 증명한 것입니다. -3. 연결 잠금 프론트 엔드를 위한 부분 요청 탐색 -- 일부 프론트 엔드는 클라이언트가 자신의 연결을 재사용할 경우에만 업스트림 백엔드 연결을 재사용합니다. 부분 요청을 사용하여 클라이언트 재사용을 반영하는 프론트 엔드 동작을 감지하십시오. -- 연결 잠금 기술에 대한 PortSwigger "브라우저 기반 비동기화 공격"을 참조하십시오. -4. 상태 프로브 -- 동일한 TCP 연결에서 첫 번째 요청과 후속 요청의 차이를 찾아보십시오(첫 번째 요청 라우팅/검증). -- Burp "HTTP Request Smuggler"는 이를 자동화하는 연결 상태 프로브를 포함합니다. -5. 와이어 시각화 -- Burp "HTTP Hacker" 확장을 사용하여 재사용 및 부분 요청을 실험하는 동안 직접 연결 및 메시지 프레이밍을 검사하십시오. +1. Disable reuse and re-test +- Burp Intruder/Repeater에서 HTTP/1 reuse를 끄고 "Send group in sequence" 옵션을 피하세요. +- Turbo Intruder에서는 `requestsPerConnection=1` 및 `pipeline=False`로 설정하세요. +- 동작이 사라지면, connection-locked/stateful 대상이나 client-side desync를 다루는 경우를 제외하고는 클라이언트 측 pipelining일 가능성이 큽니다. +2. HTTP/2 nested-response check +- HTTP/2 요청을 전송하세요. 응답 본문에 완전한 nested HTTP/1 응답이 포함되어 있다면, 순수한 클라이언트 아티팩트가 아니라 백엔드 파싱/desync 버그를 증명한 것입니다. +3. Partial-requests probe for connection-locked front-ends +- 일부 FE는 클라이언트가 자신의 연결을 재사용했을 때만 업스트림 BE 연결을 재사용합니다. partial-requests를 사용해 클라이언트 재사용을 반영하는 FE 동작을 탐지하세요. +- connection-locked 기법에 대해서는 PortSwigger "Browser‑Powered Desync Attacks"를 참조하세요. +4. State probes +- 동일한 TCP 연결에서 첫 요청과 이후 요청 간의 차이(첫-요청 라우팅/검증)를 찾아보세요. +- Burp "HTTP Request Smuggler"에는 이 과정을 자동화하는 connection‑state probe가 포함되어 있습니다. +5. Visualize the wire +- Burp "HTTP Hacker" 확장을 사용하여 재사용 및 partial requests를 실험하는 동안 연결 결합(concatenation)과 메시지 프레이밍을 직접 확인하세요. -### 연결 잠금 요청 스머글링(재사용 필요) +### Connection‑locked request smuggling (reuse-required) -일부 프론트 엔드는 클라이언트가 자신의 연결을 재사용할 때만 업스트림 연결을 재사용합니다. 실제 스머글링은 존재하지만 클라이언트 측 재사용에 따라 조건부입니다. 영향을 구별하고 증명하려면: -- 서버 측 버그를 증명하십시오. -- HTTP/2 중첩 응답 확인을 사용하거나, -- 부분 요청을 사용하여 클라이언트가 재사용할 때만 프론트 엔드가 업스트림을 재사용함을 보여주십시오. -- 직접적인 사용자 간 소켓 남용이 차단되더라도 실제 영향을 보여주십시오: -- 캐시 오염: 비동기화를 통해 공유 캐시를 오염시켜 응답이 다른 사용자에게 영향을 미치게 합니다. -- 내부 헤더 노출: 프론트 엔드 주입 헤더(예: 인증/신뢰 헤더)를 반영하고 인증 우회를 pivot합니다. -- 프론트 엔드 제어 우회: 제한된 경로/메서드를 프론트 엔드를 지나 스머글링합니다. -- 호스트 헤더 남용: 호스트 라우팅 특성과 결합하여 내부 가상 호스트로 pivot합니다. -- 운영자 워크플로 -- 제어된 재사용으로 재현하십시오(Turbo Intruder `requestsPerConnection=2` 또는 Burp Repeater 탭 그룹 → "순차적으로 그룹 전송(단일 연결)"). -- 그런 다음 캐시/헤더 누출/제어 우회 원시와 연결하여 사용자 간 또는 인증 영향을 보여줍니다. +일부 front-end는 클라이언트가 자신의 연결을 재사용할 때만 업스트림 연결을 재사용합니다. 실제 smuggling은 존재하지만 클라이언트 측 재사용에 조건부입니다. 구분하고 영향을 입증하려면: +- 서버 측 버그를 증명하세요. +- HTTP/2 nested-response check를 사용하거나, +- partial-requests를 사용해 FE가 클라이언트 재사용 시에만 업스트림을 재사용함을 보여주세요. +- 직접적인 교차 사용자 소켓 남용이 차단되더라도 실제 영향을 보여주세요: + - Cache poisoning: desync를 통해 공유 캐시를 오염시켜 응답이 다른 사용자에 영향을 주도록 함. + - Internal header disclosure: FE가 주입한 헤더(예: auth/trust 헤더)를 반사하고 이를 통해 권한 우회로 전환. + - Bypass FE controls: 프론트엔드를 통과해 제한된 경로/메서드를 smuggle. + - Host-header abuse: 호스트 라우팅 특이점을 결합해 내부 vhost로 전환. +- 운영자 워크플로우 + - 제어된 재사용으로 재현하세요 (Turbo Intruder `requestsPerConnection=2`, 또는 Burp Repeater 탭 그룹 → "Send group in sequence (single connection)"). + - 그런 다음 cache/header-leak/control-bypass primitives로 연결(chain)하고 교차 사용자 또는 권한 영향(impact)을 입증하세요. -> 연결 상태 공격도 참조하십시오. 이는 밀접하게 관련되어 있지만 기술적으로 스머글링은 아닙니다: +> See also connection‑state attacks, which are closely related but not technically smuggling: > >{{#ref}} >../http-connection-request-smuggling.md >{{#endref}} -### 클라이언트 측 비동기화 제약 +### Client‑side desync constraints -브라우저 기반/클라이언트 측 비동기화를 목표로 하는 경우, 악의적인 요청은 브라우저를 통해 교차 출처로 전송 가능해야 합니다. 헤더 난독화 트릭은 작동하지 않습니다. 탐색/가져오기를 통해 도달할 수 있는 원시에 집중한 다음, 캐시 오염, 헤더 노출 또는 프론트 엔드 제어 우회로 pivot하십시오. 하류 구성 요소가 응답을 반영하거나 캐시하는 경우입니다. +브라우저 기반/browser-powered 또는 client-side desync를 목표로 하는 경우, 악성 요청은 브라우저가 cross-origin으로 보낼 수 있어야 합니다. Header obfuscation 트릭은 작동하지 않습니다. navigation/fetch로 도달 가능한 primitives에 집중한 뒤, downstream 컴포넌트가 응답을 반사하거나 캐시할 때 cache poisoning, header disclosure, 또는 front-end control bypass로 전환하세요. -배경 및 종단 간 워크플로에 대한 정보: +For background and end-to-end workflows: {{#ref}} browser-http-request-smuggling.md {{#endref}} -### 결정에 도움이 되는 도구 +### Tooling to help decide -- HTTP Hacker (Burp BApp Store): 저수준 HTTP 동작 및 소켓 연결을 노출합니다. -- "스머글링 또는 파이프라인?" Burp Repeater 사용자 정의 작업: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda -- Turbo Intruder: `requestsPerConnection`을 통해 연결 재사용에 대한 정밀한 제어를 제공합니다. -- Burp HTTP Request Smuggler: 첫 번째 요청 라우팅/검증을 감지하는 연결 상태 프로브를 포함합니다. +- HTTP Hacker (Burp BApp Store): 저수준 HTTP 동작과 소켓 연결(concatenation)을 노출합니다. +- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda +- Turbo Intruder: `requestsPerConnection`을 통한 연결 재사용 제어가 정밀합니다. +- Burp HTTP Request Smuggler: 첫-요청 라우팅/검증을 찾아내는 connection‑state probe가 포함되어 있습니다. > [!NOTE] -> 서버 측 비동기화를 증명하고 구체적인 영향을 연결할 수 없는 한 재사용 전용 효과를 비문제로 간주하십시오(오염된 캐시 아티팩트, 권한 우회를 가능하게 하는 내부 헤더 누출, 우회된 프론트 엔드 제어 등). +> 재사용 전용 효과는 서버 측 desync를 증명하고 구체적인 영향(예: 오염된 캐시 아티팩트, 내부 헤더 노출로 인한 권한 우회 가능성, 우회된 FE 제어 등)을 입증하지 못하면 문제로 취급하지 마세요. -## HTTP Request Smuggling 남용 +## Abusing HTTP Request Smuggling -### HTTP Request Smuggling을 통한 프론트 엔드 보안 우회 +### Circumventing Front-End Security via HTTP Request Smuggling -때때로 프론트 엔드 프록시는 보안 조치를 시행하여 들어오는 요청을 면밀히 조사합니다. 그러나 이러한 조치는 HTTP Request Smuggling을 이용하여 우회할 수 있으며, 이를 통해 제한된 엔드포인트에 대한 무단 액세스를 허용합니다. 예를 들어, `/admin`에 접근하는 것은 외부에서 금지될 수 있으며, 프론트 엔드 프록시는 이러한 시도를 적극적으로 차단합니다. 그럼에도 불구하고 이 프록시는 스머글링된 HTTP 요청 내의 내장 요청을 검사하지 않을 수 있어 이러한 제한을 우회할 수 있는 허점을 남깁니다. +때때로 front-end 프록시는 들어오는 요청을 검사하여 보안 조치를 시행합니다. 하지만 HTTP Request Smuggling을 악용하면 이러한 조치를 우회하여 권한 없는 접근을 허용할 수 있습니다. 예를 들어, `/admin`에 대한 접근은 외부에서 금지되어 front-end 프록시가 적극적으로 차단할 수 있습니다. 그럼에도 불구하고 이 프록시는 smuggled HTTP 요청 내에 포함된 요청을 제대로 검사하지 않아 이러한 제한을 우회할 수 있는 구멍을 남길 수 있습니다. -다음은 HTTP Request Smuggling을 사용하여 프론트 엔드 보안 제어를 우회하는 방법을 보여주는 예입니다. 특히 일반적으로 프론트 엔드 프록시로 보호되는 `/admin` 경로를 목표로 합니다: +다음 예시는 HTTP Request Smuggling을 사용해 front-end 보안 제어를 우회하는 방법을 보여주며, 특히 일반적으로 front-end 프록시가 보호하는 `/admin` 경로를 대상으로 합니다: -**CL.TE 예** +**CL.TE 예시** ``` POST / HTTP/1.1 Host: [redacted].web-security-academy.net @@ -408,9 +414,10 @@ Content-Length: 10 x= ``` -CL.TE 공격에서는 초기 요청에 `Content-Length` 헤더가 사용되고, 이후에 포함된 요청은 `Transfer-Encoding: chunked` 헤더를 활용합니다. 프론트엔드 프록시는 초기 `POST` 요청을 처리하지만 포함된 `GET /admin` 요청을 검사하지 않아 `/admin` 경로에 대한 무단 접근을 허용합니다. +CL.TE 공격에서는 초기 요청에 `Content-Length` 헤더를 사용하고, 이후 포함된 요청은 `Transfer-Encoding: chunked` 헤더를 사용합니다. +front-end proxy는 초기 `POST` 요청을 처리하지만 포함된 `GET /admin` 요청을 검사하지 않아 `/admin` 경로에 대한 무단 접근을 허용합니다. -**TE.CL 예제** +**TE.CL 예시** ``` POST / HTTP/1.1 Host: [redacted].web-security-academy.net @@ -426,13 +433,13 @@ a=x 0 ``` -반대로, TE.CL 공격에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하고, 이후에 포함된 요청은 `Content-Length` 헤더를 기반으로 처리됩니다. CL.TE 공격과 유사하게, 프론트엔드 프록시는 밀반입된 `GET /admin` 요청을 간과하여, 의도치 않게 제한된 `/admin` 경로에 대한 접근을 허용합니다. +반대로, TE.CL attack에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하고, 이어서 포함된 요청은 `Content-Length` 헤더를 기준으로 처리됩니다. CL.TE attack과 마찬가지로, front-end proxy는 스머글된 `GET /admin` 요청을 간과하여 제한된 `/admin` 경로에 의도치 않게 접근을 허용합니다. -### Revealing front-end request rewriting +### 프론트엔드 요청 재작성 드러내기 -응용 프로그램은 종종 **프론트엔드 서버**를 사용하여 들어오는 요청을 수정한 후 백엔드 서버에 전달합니다. 일반적인 수정 사항은 클라이언트의 IP를 백엔드에 전달하기 위해 `X-Forwarded-For: `와 같은 헤더를 추가하는 것입니다. 이러한 수정 사항을 이해하는 것은 **보호 우회** 또는 **숨겨진 정보나 엔드포인트를 드러내는 방법**을 밝혀낼 수 있기 때문에 중요할 수 있습니다. +Applications often employ a **프론트엔드 서버** to modify incoming requests before passing them to the 백엔드 서버. A typical modification involves adding headers, such as `X-Forwarded-For: `, to relay the client's IP to the 백엔드. Understanding these modifications can be crucial, as it might reveal ways to **보호 우회** 또는 **숨겨진 정보나 엔드포인트 발견**. -프록시가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에서 에코하는 POST 매개변수를 찾습니다. 그런 다음, 이 매개변수를 마지막에 사용하여 다음과 유사한 요청을 작성합니다: +프록시가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에 에코하는 POST 파라미터를 찾으세요. 그런 다음, 해당 파라미터를 마지막에 사용하도록 요청을 작성하세요. 예시는 다음과 같습니다: ``` POST / HTTP/1.1 Host: vulnerable-website.com @@ -449,19 +456,27 @@ Content-Length: 100 search= ``` -이 구조에서 후속 요청 구성 요소는 `search=` 뒤에 추가되며, 이는 응답에 반영되는 매개변수입니다. 이 반영은 후속 요청의 헤더를 노출시킵니다. +In this structure, subsequent request components are appended after `search=`, which is the parameter reflected in the response. This reflection will expose the headers of the subsequent request. -중요한 것은 중첩 요청의 `Content-Length` 헤더를 실제 콘텐츠 길이에 맞추는 것입니다. 작은 값으로 시작하고 점진적으로 증가시키는 것이 좋습니다. 너무 낮은 값은 반영된 데이터를 잘라내고, 너무 높은 값은 요청이 오류를 발생시킬 수 있습니다. +이 구조에서는 이후의 요청 구성 요소들이 `search=` 뒤에 이어붙여지며, 이 파라미터가 응답에 반영됩니다. 이 반영은 이후 요청의 헤더들을 노출시킵니다. -이 기술은 TE.CL 취약점의 맥락에서도 적용 가능하지만, 요청은 `search=\r\n0`으로 종료되어야 합니다. 개행 문자와 관계없이 값은 검색 매개변수에 추가됩니다. +It's important to align the `Content-Length` header of the nested request with the actual content length. Starting with a small value and incrementing gradually is advisable, as too low a value will truncate the reflected data, while too high a value can cause the request to error out. -이 방법은 주로 프론트엔드 프록시가 수행한 요청 수정 사항을 이해하는 데 사용되며, 본질적으로 자가 조사 역할을 합니다. +`Content-Length` 헤더를 중첩된 요청의 실제 콘텐츠 길이에 맞추는 것이 중요합니다. 너무 낮으면 반영된 데이터가 잘려 나오고, 너무 높으면 요청이 오류를 일으킬 수 있으므로, 작은 값부터 시작해 점차 증가시키는 것이 권장됩니다. -### 다른 사용자의 요청 캡처하기 +This technique is also applicable in the context of a TE.CL vulnerability, but the request should terminate with `search=\r\n0`. Regardless of the newline characters, the values will append to the search parameter. -POST 작업 중 매개변수의 값으로 특정 요청을 추가함으로써 다음 사용자의 요청을 캡처하는 것이 가능합니다. 다음과 같이 이를 수행할 수 있습니다: +이 기법은 TE.CL 취약점 상황에서도 적용할 수 있으나, 요청은 `search=\r\n0`으로 종료되어야 합니다. 줄바꿈 문자와 관계없이 값들은 `search` 파라미터에 이어붙여집니다. -다음 요청을 매개변수의 값으로 추가하면 후속 클라이언트의 요청을 저장할 수 있습니다: +This method primarily serves to understand the request modifications made by the front-end proxy, essentially performing a self-directed investigation. + +이 방법은 주로 프론트엔드 프록시가 수행하는 요청 수정사항을 이해하는 데 사용되며, 본질적으로 자체 조사를 수행합니다. + +### Capturing other users' requests + +POST 작업 중 파라미터의 값으로 특정 요청을 이어붙이면 다음 사용자의 요청을 캡처할 수 있습니다. 방법은 다음과 같습니다: + +By appending the following request as the value of a parameter, you can store the subsequent client's request: ``` POST / HTTP/1.1 Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net @@ -481,20 +496,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment= ``` -이 시나리오에서 **comment parameter**는 공개적으로 접근 가능한 페이지의 게시물 댓글 섹션 내의 내용을 저장하기 위해 설계되었습니다. 따라서 이후 요청의 내용은 댓글로 나타납니다. +In this scenario, the **comment parameter** is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment. -그러나 이 기술에는 한계가 있습니다. 일반적으로, 이는 밀반입된 요청에서 사용된 매개변수 구분자까지의 데이터만 캡처합니다. URL 인코딩된 양식 제출의 경우, 이 구분자는 `&` 문자입니다. 이는 피해자 사용자의 요청에서 캡처된 내용이 첫 번째 `&`에서 멈춘다는 것을 의미하며, 이는 쿼리 문자열의 일부일 수도 있습니다. +However, this technique has limitations. Generally, it captures data only up to the parameter delimiter used in the smuggled request. For URL-encoded form submissions, this delimiter is the `&` character. This means the captured content from the victim user's request will stop at the first `&`, which may even be part of the query string. -또한, 이 접근 방식은 TE.CL 취약점에서도 유효하다는 점에 유의할 필요가 있습니다. 이러한 경우, 요청은 `search=\r\n0`으로 끝나야 합니다. 줄 바꿈 문자와 관계없이 값은 검색 매개변수에 추가됩니다. +Additionally, it's worth noting that this approach is also viable with a TE.CL vulnerability. In such cases, the request should conclude with `search=\r\n0`. Regardless of newline characters, the values will be appended to the search parameter. -### HTTP 요청 밀반입을 사용하여 반사된 XSS 공격하기 +### Using HTTP request smuggling to exploit reflected XSS -HTTP Request Smuggling은 **Reflected XSS**에 취약한 웹 페이지를 공격하는 데 활용될 수 있으며, 상당한 이점을 제공합니다: +HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages: -- 대상 사용자와의 상호작용이 **필요하지 않습니다**. -- HTTP 요청 헤더와 같이 **일반적으로 접근할 수 없는** 요청의 일부에서 XSS를 악용할 수 있습니다. +- Interaction with the target users is **not required**. +- Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers. -사용자 에이전트 헤더를 통해 웹사이트가 반사된 XSS에 취약한 경우, 다음 페이로드는 이 취약점을 악용하는 방법을 보여줍니다: +In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability: ``` POST / HTTP/1.1 Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net @@ -515,26 +530,26 @@ Content-Type: application/x-www-form-urlencoded A= ``` -이 페이로드는 취약점을 악용하기 위해 다음과 같이 구조화되어 있습니다: +이 페이로드는 다음과 같이 취약점을 악용하도록 구성되어 있습니다: -1. `Transfer-Encoding: chunked` 헤더가 있는 일반적인 `POST` 요청을 시작하여 밀반입의 시작을 나타냅니다. -2. 이어서 `0`을 사용하여 청크된 메시지 본문의 끝을 표시합니다. -3. 그런 다음, `User-Agent` 헤더에 `` 스크립트를 주입한 밀반입된 `GET` 요청이 도입되어, 서버가 이 후속 요청을 처리할 때 XSS가 트리거됩니다. +1. 겉으로는 일반적인 `POST` 요청을 시작하고, smuggling 시작을 나타내기 위해 `Transfer-Encoding: chunked` 헤더를 사용합니다. +2. 이어서 청크된 메시지 본문의 끝을 표시하는 `0`을 보냅니다. +3. 그런 다음 smuggled된 `GET` 요청이 도입되며, 여기서 `User-Agent` 헤더에 `` 같은 스크립트를 주입하여 서버가 이 후속 요청을 처리할 때 XSS를 유발합니다. -밀반입을 통해 `User-Agent`를 조작함으로써, 페이로드는 정상 요청 제약을 우회하여 비표준이지만 효과적인 방식으로 반사된 XSS 취약점을 악용합니다. +`User-Agent`를 smuggling으로 조작함으로써 페이로드는 정상적인 요청 제약을 우회하여 비표준적이지만 효과적인 방식으로 Reflected XSS 취약점을 악용합니다. #### HTTP/0.9 > [!CAUTION] -> 사용자 콘텐츠가 **`Content-type`**이 **`text/plain`**인 응답에 반영되는 경우 XSS 실행이 방지됩니다. 서버가 **HTTP/0.9를 지원하는 경우 이를 우회할 수 있을지도 모릅니다**! +> 사용자 입력이 **`Content-type`**이 **`text/plain`**과 같은 응답에 반영되어 XSS 실행이 차단되는 경우가 있습니다. 서버가 **HTTP/0.9를 지원한다면 이를 우회할 수 있을 가능성**이 있습니다! -HTTP/0.9 버전은 1.0 이전의 버전으로, **GET** 동사만 사용하며 **헤더**로 응답하지 않고 본체만 응답합니다. +HTTP/0.9 버전은 이전에 1.0보다 앞선 버전으로 **GET** 동사만 사용하며 **headers**를 반환하지 않고 본문만 반환합니다. -[**이 글**](https://mizu.re/post/twisty-python)에서는 요청 밀반입과 **사용자의 입력에 응답하는 취약한 엔드포인트**를 이용하여 HTTP/0.9로 요청을 밀반입하는 방식으로 악용되었습니다. 응답에 반영될 매개변수는 **유효한 실행 가능한 JS 코드가 포함된 가짜 HTTP/1.1 응답(헤더와 본체 포함)**을 포함하므로 응답은 `Content-Type`이 `text/html`인 유효한 실행 가능한 JS 코드를 포함하게 됩니다. +[**this writeup**](https://mizu.re/post/twisty-python)에서, 이것은 request smuggling과 **사용자 입력을 그대로 응답하는 취약한 엔드포인트**를 이용해 HTTP/0.9로 요청을 smuggle하는 방식으로 남용되었습니다. 응답에 반영될 파라미터는 **가짜 HTTP/1.1 응답(헤더와 본문 포함)**을 담고 있었기 때문에, 최종 응답은 `Content-Type`이 `text/html`인 유효한 실행 가능한 JS 코드를 포함하게 됩니다. -### HTTP 요청 밀반입을 통한 사이트 내 리디렉션 악용 +### Exploiting On-site Redirects with HTTP Request Smuggling -응용 프로그램은 종종 리디렉션 URL의 `Host` 헤더에서 호스트 이름을 사용하여 한 URL에서 다른 URL로 리디렉션합니다. 이는 Apache 및 IIS와 같은 웹 서버에서 일반적입니다. 예를 들어, 후행 슬래시 없이 폴더를 요청하면 슬래시를 포함하도록 리디렉션됩니다: +애플리케이션은 종종 리다이렉트 URL에 `Host` 헤더의 호스트명을 사용하여 한 URL에서 다른 URL로 리다이렉트합니다. 이는 Apache나 IIS 같은 웹 서버에서 흔한 동작입니다. 예를 들어, 슬래시가 없는 폴더를 요청하면 슬래시를 포함하도록 리다이렉트됩니다: ``` GET /home HTTP/1.1 Host: normal-website.com @@ -544,7 +559,7 @@ Host: normal-website.com HTTP/1.1 301 Moved Permanently Location: https://normal-website.com/home/ ``` -이 행동은 겉보기에는 무해해 보이지만, HTTP request smuggling을 사용하여 사용자를 외부 사이트로 리디렉션하는 데 조작될 수 있습니다. 예를 들어: +겉으로 보기엔 무해해 보이지만, 이 동작은 HTTP request smuggling을 사용하여 사용자를 외부 사이트로 리다이렉트하도록 조작될 수 있습니다. 예를 들어: ``` POST / HTTP/1.1 Host: vulnerable-website.com @@ -558,7 +573,7 @@ GET /home HTTP/1.1 Host: attacker-website.com Foo: X ``` -이 스머글된 요청은 다음에 처리되는 사용자 요청이 공격자가 제어하는 웹사이트로 리디렉션될 수 있습니다: +이 smuggled request는 다음에 처리되는 사용자 요청을 attacker-controlled website로 리디렉트할 수 있습니다: ``` GET /home HTTP/1.1 Host: attacker-website.com @@ -570,17 +585,17 @@ Host: vulnerable-website.com HTTP/1.1 301 Moved Permanently Location: https://attacker-website.com/home/ ``` -이 시나리오에서는 사용자의 JavaScript 파일 요청이 가로채집니다. 공격자는 응답으로 악성 JavaScript를 제공하여 사용자를 손상시킬 수 있습니다. +In this scenario, a user's request for a JavaScript file is hijacked. The attacker can potentially compromise the user by serving malicious JavaScript in response. -### HTTP 요청 스머글링을 통한 웹 캐시 오염 활용 +### Exploiting Web Cache Poisoning via HTTP Request Smuggling -웹 캐시 오염은 **프론트엔드 인프라의 콘텐츠를 캐시**하는 어떤 구성 요소라도 실행될 수 있으며, 일반적으로 성능 향상을 위해 사용됩니다. 서버의 응답을 조작함으로써 **캐시를 오염**시킬 수 있습니다. +Web cache poisoning는 일반적으로 성능을 향상시키기 위해 **프론트엔드 인프라가 콘텐츠를 캐시하는** 어떤 구성 요소가 있는 경우 실행될 수 있습니다. 서버의 응답을 조작함으로써 **poison the cache**하는 것이 가능합니다. -이전에 서버 응답을 변경하여 404 오류를 반환하는 방법을 관찰했습니다 (참조: [Basic Examples](#basic-examples)). 유사하게, 서버를 속여 `/static/include.js` 요청에 대한 응답으로 `/index.html` 콘텐츠를 제공하도록 할 수 있습니다. 결과적으로, `/static/include.js` 콘텐츠는 `/index.html`의 내용으로 캐시에서 대체되어 사용자가 `/static/include.js`에 접근할 수 없게 되어 서비스 거부(DoS)로 이어질 수 있습니다. +앞서 우리는 서버 응답이 404 오류를 반환하도록 어떻게 변경될 수 있는지 관찰했습니다(참조: [Basic Examples](#basic-examples)). 마찬가지로, 서버를 속여 `/static/include.js` 요청에 대해 `/index.html` 콘텐츠를 반환하도록 만들 수 있습니다. 그 결과 `/static/include.js`의 콘텐츠가 캐시에서 `/index.html`의 내용으로 대체되어 사용자가 `/static/include.js`에 접근할 수 없게 되고, 이는 잠재적으로 Denial of Service (DoS)로 이어질 수 있습니다. -이 기술은 **오픈 리다이렉트 취약점**이 발견되거나 **오픈 리다이렉트로의 사이트 내 리다이렉트**가 있을 경우 특히 강력해집니다. 이러한 취약점을 이용하여 공격자가 제어하는 스크립트로 `/static/include.js`의 캐시된 콘텐츠를 대체할 수 있으며, 이는 업데이트된 `/static/include.js`를 요청하는 모든 클라이언트에 대한 광범위한 크로스 사이트 스크립팅(XSS) 공격을 가능하게 합니다. +이 기술은 **Open Redirect vulnerability**가 발견되거나 사이트 내에서 **on-site redirect to an open redirect**가 존재하는 경우 특히 강력해집니다. 이러한 취약점을 악용하면 `/static/include.js`의 캐시된 콘텐츠를 공격자가 제어하는 스크립트로 대체할 수 있으며, 결과적으로 업데이트된 `/static/include.js`를 요청하는 모든 클라이언트에 대해 대규모 Cross-Site Scripting (XSS) 공격을 가능하게 합니다. -아래는 **사이트 내 리다이렉트와 오픈 리다이렉트를 결합한 캐시 오염 활용**의 예시입니다. 목표는 공격자가 제어하는 JavaScript 코드를 제공하기 위해 `/static/include.js`의 캐시 콘텐츠를 변경하는 것입니다: +아래는 **cache poisoning combined with an on-site redirect to open redirect**을 이용한 공격의 예시입니다. 목표는 `/static/include.js`의 캐시 콘텐츠를 변경하여 공격자가 제어하는 JavaScript 코드를 제공하게 하는 것입니다: ``` POST / HTTP/1.1 Host: vulnerable.net @@ -598,20 +613,20 @@ Content-Length: 10 x=1 ``` -내장된 요청이 `/post/next?postId=3`를 타겟팅하고 있음을 주목하세요. 이 요청은 **Host header value**를 사용하여 도메인을 결정하며 `/post?postId=4`로 리디렉션됩니다. **Host header**를 변경함으로써 공격자는 요청을 자신의 도메인으로 리디렉션할 수 있습니다 (**on-site redirect to open redirect**). +Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**). -성공적인 **socket poisoning** 후, `/static/include.js`에 대한 **GET request**가 시작되어야 합니다. 이 요청은 이전의 **on-site redirect to open redirect** 요청에 의해 오염되어 공격자가 제어하는 스크립트의 내용을 가져옵니다. +성공적인 **socket poisoning** 후, `/static/include.js`에 대한 **GET request**를 시작해야 한다. 이 요청은 이전의 **on-site redirect to open redirect** 요청에 의해 오염되어 공격자가 제어하는 스크립트의 내용을 가져온다. -그 후, `/static/include.js`에 대한 모든 요청은 공격자의 스크립트의 캐시된 내용을 제공하여 광범위한 XSS 공격을 효과적으로 시작합니다. +그 결과, 이후 `/static/include.js`에 대한 모든 요청은 공격자가 만든 스크립트의 캐시된 콘텐츠를 제공하게 되어, 사실상 광범위한 XSS 공격을 개시하게 된다. ### Using HTTP request smuggling to perform web cache deception -> **웹 캐시 오염과 웹 캐시 기만의 차이점은 무엇인가요?** +> **web cache poisoning**과 **web cache deception**의 차이점은 무엇인가? > -> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 악성 콘텐츠를 캐시에 저장하도록 유도하고, 이 콘텐츠가 다른 애플리케이션 사용자에게 캐시에서 제공됩니다. -> - **웹 캐시 기만**에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 유도하고, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다. +> - **web cache poisoning**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하고, 이 콘텐츠가 캐시에서 다른 애플리케이션 사용자들에게 제공된다. +> - **web cache deception**에서는 공격자가 다른 사용자의 민감한 콘텐츠가 캐시에 저장되게 만든 뒤, 공격자가 그 콘텐츠를 캐시에서 가져온다. -공격자는 민감한 사용자 특정 콘텐츠를 가져오는 밀반입 요청을 작성합니다. 다음 예를 고려하세요: +공격자는 민감한 사용자별 콘텐츠를 가져오는 smuggled request를 제작한다. 다음 예를 보자: ```markdown `POST / HTTP/1.1`\ `Host: vulnerable-website.com`\ @@ -622,17 +637,18 @@ x=1 `GET /private/messages HTTP/1.1`\ `Foo: X` ``` -이 스머글 요청이 정적 콘텐츠(예: `/someimage.png`)를 위한 캐시 항목을 오염시키면, 피해자의 `/private/messages`의 민감한 데이터가 정적 콘텐츠의 캐시 항목 아래에 캐시될 수 있습니다. 결과적으로, 공격자는 이러한 캐시된 민감한 데이터를 검색할 수 있습니다. +If this smuggled request가 정적 콘텐츠(예: `/someimage.png`)용으로 의도된 캐시 항목을 오염시키면, 피해자의 `/private/messages`에 있는 민감한 데이터가 정적 콘텐츠의 캐시 항목에 캐시될 수 있습니다. 결과적으로 공격자는 이 캐시된 민감한 데이터를 획득할 수 있습니다. -### HTTP 요청 스머글링을 통한 TRACE 남용 +### TRACE를 HTTP Request Smuggling을 통해 악용하기 -[**이 게시물**](https://portswigger.net/research/trace-desync-attack)에서는 서버에 TRACE 메서드가 활성화되어 있다면 HTTP 요청 스머글링으로 이를 남용할 수 있을 가능성이 있다고 제안합니다. 이는 이 메서드가 서버에 전송된 모든 헤더를 응답 본문의 일부로 반영하기 때문입니다. 예를 들어: +[**In this post**](https://portswigger.net/research/trace-desync-attack)에서는 서버에 TRACE 메서드가 활성화되어 있으면 HTTP Request Smuggling으로 이를 악용할 수 있다고 제안합니다. 이는 이 메서드가 서버로 전송된 모든 헤더를 응답 본문의 일부로 반사하기 때문입니다. 예를 들면: ``` TRACE / HTTP/1.1 Host: example.com XSS: ``` -I'm ready to assist you with the translation. Please provide the text you would like me to translate. +번역할 src/pentesting-web/http-request-smuggling/README.md의 내용을 여기에 붙여넣어 주세요. +코드 블록, 태그({#...}), 링크/경로, 기술명(예: http-request-smuggling), 일반적인 해킹 용어는 번역하지 않습니다. 파일이 크면 여러 메시지로 나눠서 보내셔도 됩니다. ``` HTTP/1.1 200 OK Content-Type: message/http @@ -643,17 +659,17 @@ Host: vulnerable.com XSS: X-Forwarded-For: xxx.xxx.xxx.xxx ``` -이 동작을 악용하는 예는 **먼저 HEAD 요청을 밀어넣는 것**입니다. 이 요청은 GET 요청의 **헤더**만 응답받게 됩니다 (**`Content-Type`** 포함). 그리고 **HEAD 요청 직후에 TRACE 요청을 밀어넣는 것**으로, 이는 **전송된 데이터를 반영하게 됩니다**.\ -HEAD 응답에는 `Content-Length` 헤더가 포함되므로, **TRACE 요청의 응답은 HEAD 응답의 본문으로 처리되어 임의의 데이터를 반영하게 됩니다**.\ -이 응답은 연결을 통해 다음 요청으로 전송되므로, 예를 들어 **임의의 JS 코드를 주입하기 위해 캐시된 JS 파일에서 사용될 수 있습니다**. +이 동작을 악용하는 한 예는 **먼저 HEAD request를 smuggle** 하는 것이다. 이 요청에는 GET 요청의 **headers**만 응답되며(**`Content-Type`** 포함). 그리고 HEAD 바로 뒤에 **TRACE request를 smuggle** 하면, 이 요청은 보낸 데이터를 **반사**한다.\ +HEAD 응답에 `Content-Length` 헤더가 포함되어 있기 때문에, **TRACE 요청의 응답은 HEAD 응답의 바디로 간주되어 임의의 데이터를 반영하게 된다**.\ +이 응답은 연결을 통해 다음 요청으로 전달되며, 예를 들어 캐시된 JS 파일에 사용되어 임의의 JS 코드를 주입하는 데 **사용될 수 있다**. -### HTTP 응답 분할을 통한 TRACE 악용 +### TRACE를 통한 HTTP Response Splitting 악용 -[**이 게시물**](https://portswigger.net/research/trace-desync-attack)을 계속 따라가는 것이 TRACE 메서드를 악용하는 또 다른 방법을 제안합니다. 언급된 바와 같이, HEAD 요청과 TRACE 요청을 밀어넣으면 HEAD 요청에 대한 응답에서 **일부 반영된 데이터를 제어할 수 있습니다**. HEAD 요청의 본문 길이는 기본적으로 Content-Length 헤더에 표시되며, TRACE 요청에 대한 응답으로 형성됩니다. +또 다른 TRACE 악용 방법은 [**이 글**](https://portswigger.net/research/trace-desync-attack)을 참고하는 것을 권장한다. 앞서 언급한 것처럼, HEAD request와 TRACE request를 smuggle하면 HEAD 응답에서 **일부 반사된 데이터를 제어할 수 있다**. HEAD 응답의 바디 길이는 기본적으로 `Content-Length` 헤더로 표시되며, 그 내용은 TRACE 요청에 대한 응답으로 구성된다. -따라서 새로운 아이디어는 이 Content-Length와 TRACE 응답에서 제공된 데이터를 알고 있을 때, TRACE 응답이 Content-Length의 마지막 바이트 이후에 유효한 HTTP 응답을 포함하도록 만들어 공격자가 다음 응답에 대한 요청을 완전히 제어할 수 있게 하는 것입니다 (이는 캐시 오염을 수행하는 데 사용될 수 있습니다). +따라서, 이 `Content-Length`와 TRACE 응답에서 제공되는 데이터를 알고 있다면, TRACE 응답이 `Content-Length`의 마지막 바이트 뒤에 유효한 HTTP 응답을 포함하도록 만들 수 있고, 이를 통해 공격자는 다음 응답에 대한 요청을 완전히 제어할 수 있다(이는 cache poisoning 수행에 이용될 수 있다). -예: +Example: ``` GET / HTTP/1.1 Host: example.com @@ -672,7 +688,7 @@ Content-Length: 44\r\n \r\n ``` -이 응답을 생성합니다 (HEAD 응답에 Content-Length가 있어 TRACE 응답이 HEAD 본문의 일부가 되고, HEAD Content-Length가 끝나면 유효한 HTTP 응답이 밀반입됩니다): +다음과 같은 응답을 생성합니다 (HEAD 응답이 Content-Length를 갖고 있어 TRACE 응답을 HEAD 본문의 일부로 만들며, HEAD Content-Length가 끝나면 유효한 HTTP 응답이 스머글됩니다): ``` HTTP/1.1 200 OK Content-Type: text/html @@ -693,36 +709,36 @@ Content-Length: 50 ``` -### HTTP 요청 스머글링을 HTTP 응답 비동기화로 무기화하기 +### HTTP Response Desynchronisation을 이용한 HTTP Request Smuggling 무기화 -HTTP 요청 스머글링 취약점을 발견했지만 이를 어떻게 악용할지 모르겠다면, 다른 악용 방법을 시도해 보세요: +HTTP Request Smuggling 취약점을 발견했지만 어떻게 익스플로잇할지 모르겠나요? 다음 다른 익스플로잇 방법들을 시도해보세요: {{#ref}} ../http-response-smuggling-desync.md {{#endref}} -### 기타 HTTP 요청 스머글링 기술 +### 기타 HTTP Request Smuggling 기법 -- 브라우저 HTTP 요청 스머글링 (클라이언트 측) +- Browser HTTP Request Smuggling (Client Side) {{#ref}} browser-http-request-smuggling.md {{#endref}} -- HTTP/2 다운그레이드에서의 요청 스머글링 +- Request Smuggling in HTTP/2 Downgrades {{#ref}} request-smuggling-in-http-2-downgrades.md {{#endref}} -## 터보 침입자 스크립트 +## Turbo intruder 스크립트 ### CL.TE -From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor) +출처: [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor) ```python def queueRequests(target, wordlists): @@ -763,7 +779,7 @@ table.add(req) ``` ### TE.CL -From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover) +출처: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover) ```python def queueRequests(target, wordlists): engine = RequestEngine(endpoint=target.endpoint, @@ -807,14 +823,14 @@ table.add(req) ``` ## 도구 -- HTTP Hacker (Burp BApp Store) – 연결/프레이밍 및 저수준 HTTP 동작 시각화 +- HTTP Hacker (Burp BApp Store) – 연결/프레이밍 및 저수준 HTTP 동작을 시각화 - https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?" - [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling) - [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler) - [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py) - [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler) - [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz) -- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 이 도구는 이상한 요청 스머글링 불일치를 찾는 데 유용한 문법 기반 HTTP 퍼저입니다. +- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): 이 도구는 문법 기반의 HTTP Fuzzer로, 이상한 request smuggling 불일치를 찾는 데 유용합니다. ## 참고자료 @@ -827,10 +843,10 @@ table.add(req) - [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/) - [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack) - [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/) -- 잘못된 잘못된 긍정 경고에 주의하세요: HTTP 파이프라이닝과 요청 스머글링을 구별하는 방법 – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling) +- 거짓-거짓 양성에 주의: HTTP pipelining과 request smuggling을 구별하는 방법 – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling) - [https://http1mustdie.com/](https://http1mustdie.com/) -- 브라우저 기반의 비동기 공격 – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks) -- PortSwigger Academy – 클라이언트 측 비동기 – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) +- Browser‑Powered Desync Attacks – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks) +- PortSwigger Academy – client‑side desync – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/proxy-waf-protections-bypass.md b/src/pentesting-web/proxy-waf-protections-bypass.md index ad647d935..1a190b902 100644 --- a/src/pentesting-web/proxy-waf-protections-bypass.md +++ b/src/pentesting-web/proxy-waf-protections-bypass.md @@ -3,11 +3,11 @@ {{#include ../banners/hacktricks-training.md}} -## 경로 조작을 통한 Nginx ACL 규칙 우회 +## Bypass Nginx ACL Rules with Pathname Manipulation -기술 [이 연구에서](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies). +기법은 [이 연구](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)에서 가져옴. -Nginx 규칙 예: +Nginx 규칙 예시: ```plaintext location = /admin { deny all; @@ -17,11 +17,11 @@ location = /admin/ { deny all; } ``` -Nginx는 우회 방지를 위해 경로 정규화를 수행한 후 이를 확인합니다. 그러나 백엔드 서버가 Nginx가 제거하지 않는 문자를 제거하는 다른 정규화를 수행하는 경우, 이 방어를 우회할 수 있을 가능성이 있습니다. +우회를 방지하기 위해 Nginx는 검사하기 전에 경로 정규화(path normalization)를 수행합니다. 그러나 백엔드 서버가 다른 정규화(nginx가 제거하지 않는 문자를 제거하는 등)를 수행하면 이 방어를 우회할 수 있습니다. ### **NodeJS - Express** -| Nginx Version | **Node.js Bypass Characters** | +| Nginx 버전 | **Node.js Bypass Characters** | | ------------- | ----------------------------- | | 1.22.0 | `\xA0` | | 1.21.6 | `\xA0` | @@ -31,7 +31,7 @@ Nginx는 우회 방지를 위해 경로 정규화를 수행한 후 이를 확인 ### **Flask** -| Nginx Version | **Flask Bypass Characters** | +| Nginx 버전 | **Flask Bypass Characters** | | ------------- | -------------------------------------------------------------- | | 1.22.0 | `\x85`, `\xA0` | | 1.21.6 | `\x85`, `\xA0` | @@ -41,7 +41,7 @@ Nginx는 우회 방지를 위해 경로 정규화를 수행한 후 이를 확인 ### **Spring Boot** -| Nginx Version | **Spring Boot Bypass Characters** | +| Nginx 버전 | **Spring Boot Bypass Characters** | | ------------- | --------------------------------- | | 1.22.0 | `;` | | 1.21.6 | `;` | @@ -62,7 +62,7 @@ include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.1-fpm.sock; } ``` -Nginx는 `/admin.php`에 대한 접근을 차단하도록 구성되어 있지만, `/admin.php/index.php`에 접근함으로써 이를 우회할 수 있습니다. +Nginx는 `/admin.php`에 대한 접근을 차단하도록 구성되어 있지만 `/admin.php/index.php`에 접근하면 이를 우회할 수 있습니다. ### 방지 방법 ```plaintext @@ -74,20 +74,20 @@ deny all; ### 경로 혼동 -[**이 게시물**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)에서는 ModSecurity v3(3.0.12까지)가 접근된 경로(매개변수 시작까지)를 포함해야 하는 `REQUEST_FILENAME` 변수를 **부적절하게 구현했다**고 설명합니다. 이는 경로를 얻기 위해 URL 디코드를 수행했기 때문입니다.\ -따라서 mod security에서 `http://example.com/foo%3f';alert(1);foo=`와 같은 요청은 경로가 단지 `/foo`라고 가정합니다. 왜냐하면 `%3f`가 `?`로 변환되어 URL 경로가 끝나기 때문입니다. 하지만 실제로 서버가 받는 경로는 `/foo%3f';alert(1);foo=`입니다. +[**In this post**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)에서는 ModSecurity v3 (3.0.12까지)가 접근한 경로(파라미터 시작 전까지)를 포함해야 할 `REQUEST_FILENAME` 변수를 **부적절하게 구현**했다고 설명합니다. 이는 경로를 얻기 위해 URL 디코드를 수행했기 때문입니다.\ +따라서 `http://example.com/foo%3f';alert(1);foo=` 같은 요청은 mod security에서는 `%3f`가 `?`로 변환되어 URL 경로를 종료한다고 보고 경로를 `/foo`로 간주하지만, 실제로 서버가 받는 경로는 `/foo%3f';alert(1);foo=`입니다. -변수 `REQUEST_BASENAME`과 `PATH_INFO`도 이 버그의 영향을 받았습니다. +`REQUEST_BASENAME`과 `PATH_INFO` 변수도 이 버그의 영향을 받았습니다. -Mod Security 버전 2에서도 비슷한 일이 발생하여 특정 확장자(예: `.bak`)와 관련된 파일에 대한 접근을 방지하는 보호를 우회할 수 있었습니다. 이는 점을 `%2e`로 URL 인코딩하여 전송함으로써 가능했습니다. 예를 들어: `https://example.com/backup%2ebak`. +비슷한 문제가 Mod Security 버전 2에서도 발생했는데, 백업 파일과 관련된 특정 확장자(예: `.bak`)에 대한 접근을 차단하는 보호를 우회할 수 있었고, 이는 점을 `%2e`로 URL 인코딩하여 전송하면 가능했습니다. 예: `https://example.com/backup%2ebak`. ## AWS WAF ACL 우회 -### 잘못된 헤더 +### 잘못된 Header -[이 연구](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)에서는 AWS가 제대로 파싱하지 못한 "잘못된" 헤더를 전송함으로써 HTTP 헤더에 적용된 AWS WAF 규칙을 우회할 수 있었다고 언급합니다. 하지만 백엔드 서버는 이를 파싱할 수 있었습니다. +[This research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)에서는 AWS가 제대로 파싱하지 못했지만 backend server는 파싱한 "malformed" header를 전송함으로써 HTTP headers에 적용된 AWS WAF 규칙을 우회할 수 있었음을 언급합니다. -예를 들어, X-Query 헤더에 SQL 인젝션을 포함한 다음 요청을 전송합니다: +예를 들어, 헤더 X-Query에 SQL injection을 넣어 다음과 같은 요청을 보내는 경우: ```http GET / HTTP/1.1\r\n Host: target.com\r\n @@ -96,49 +96,50 @@ X-Query: Value\r\n Connection: close\r\n \r\n ``` -AWS WAF를 우회할 수 있었던 이유는 다음 줄이 헤더의 값의 일부라는 것을 이해하지 못했기 때문이며, NODEJS 서버는 이를 이해했습니다(이 문제는 수정되었습니다). +It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed). ## 일반적인 WAF 우회 -### 요청 크기 제한 +### Request Size Limits -일반적으로 WAF는 요청을 확인하기 위한 특정 길이 제한이 있으며, POST/PUT/PATCH 요청이 이를 초과하면 WAF는 요청을 확인하지 않습니다. +Commonly WAFs have a certain length limit of requests to check and if a POST/PUT/PATCH request is over it, the WAF won't check the request. -- AWS WAF의 경우 [**문서를 확인할 수 있습니다**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:** +- For AWS WAF, you can [**check the documentation**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:** -
Application Load Balancer 및 AWS AppSync 보호를 위해 검사할 수 있는 웹 요청 본문의 최대 크기8 KB
CloudFront, API Gateway, Amazon Cognito, App Runner 및 Verified Access 보호를 위해 검사할 수 있는 웹 요청 본문의 최대 크기**64 KB
+
Application Load Balancer 및 AWS AppSync 보호에서 검사할 수 있는 웹 요청 본문 최대 크기8 KB
CloudFront, API Gateway, Amazon Cognito, App Runner 및 Verified Access 보호에서 검사할 수 있는 웹 요청 본문 최대 크기**64 KB
-- [**Azure 문서**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**에서:** +- From [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:** -Core Rule Set 3.1(또는 그 이하)의 이전 웹 애플리케이션 방화벽은 요청 본문 검사를 끄면 **128 KB**보다 큰 메시지를 허용하지만, 이러한 메시지는 취약점 검사를 받지 않습니다. 최신 버전(Core Rule Set 3.2 이상)에서는 최대 요청 본한 제한을 비활성화하여 동일한 작업을 수행할 수 있습니다. 요청이 크기 제한을 초과하면: +Older Web Application Firewalls with Core Rule Set 3.1 (or lower) allow messages larger than **128 KB** by turning off request body inspection, but these messages won't be checked for vulnerabilities. For newer versions (Core Rule Set 3.2 or newer), the same can be done by disabling the maximum request body limit. When a request exceeds the size limit: -**차단 모드**: 요청을 기록하고 차단합니다.\ -**탐지 모드**: 제한까지 검사하고 나머지는 무시하며, `Content-Length`가 제한을 초과하면 기록합니다. +If p**revention mode**: 요청을 기록하고 차단합니다.\ +If **detection mode**: 제한까지 검사하고 나머지는 무시하며, `Content-Length`가 제한을 초과하면 로그를 남깁니다. -- [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**에서:** +- From [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:** -기본적으로 WAF는 요청의 처음 8KB만 검사합니다. 고급 메타데이터를 추가하여 제한을 128KB까지 늘릴 수 있습니다. +By default, the WAF inspects only the first 8KB of a request. It can increase the limit up to 128KB by adding Advanced Metadata. -- [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**에서:** +- From [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:** -최대 128KB까지. +Up to 128KB. -### 정적 자산 검사 간극 (.js GETs) +### Static assets inspection gaps (.js GETs) -일부 CDN/WAF 스택은 정적 자산에 대한 GET 요청에 대해 약하거나 전혀 콘텐츠 검사를 적용하지 않으며(예: `.js`로 끝나는 경로), 여전히 속도 제한 및 IP 평판과 같은 전역 규칙을 적용합니다. 정적 확장의 자동 캐싱과 결합하면, 이는 후속 HTML 응답에 영향을 미치는 악성 변형을 전달하거나 씨앗을 뿌리는 데 악용될 수 있습니다. +Some CDN/WAF stacks apply weak or no content inspection to GET requests for static assets (for example paths ending with `.js`), while still applying global rules like rate limiting and IP reputation. Combined with auto-caching of static extensions, this can be abused to deliver or seed malicious variants that affect subsequent HTML responses. -실용적인 사용 사례: +Practical use cases: -- 콘텐츠 검사를 피하기 위해 `.js` 경로에 GET 요청을 보낼 때 신뢰할 수 없는 헤더(예: `User-Agent`)에 페이로드를 전송한 후, 즉시 메인 HTML을 요청하여 캐시된 변형에 영향을 미칩니다. -- 새롭고 깨끗한 IP를 사용합니다; IP가 플래그가 지정되면 라우팅 변경으로 인해 기술이 신뢰할 수 없게 될 수 있습니다. -- Burp Repeater에서 "병렬로 그룹 전송" (단일 패킷 스타일)을 사용하여 두 요청(`.js` 다음 HTML)을 동일한 프론트엔드 경로를 통해 경합시킵니다. +- Send payloads in untrusted headers (e.g., `User-Agent`) on a GET to a `.js` path to avoid content inspection, then immediately request the main HTML to influence the cached variant. +- Use a fresh/clean IP; once an IP is flagged, routing changes can make the technique unreliable. +- In Burp Repeater, use "Send group in parallel" (single-packet style) to race the two requests (`.js` then HTML) through the same front-end path. -이것은 헤더 반사 캐시 오염과 잘 결합됩니다. 참조: +This pairs well with header-reflection cache poisoning. See: -- {{#ref}} +{{#ref}} cache-deception/README.md {{#endref}} -- [공개 BBP에서 0-클릭 계정 탈취를 발견하고 이를 활용하여 관리자 수준 기능에 접근한 방법](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/) + +- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/) ### 난독화 ```bash @@ -148,9 +149,9 @@ cache-deception/README.md # Path blacklist bypass - Tomcat /path1/path2/ == ;/path1;foo/path2;bar/; ``` -### 유니코드 호환성 +### Unicode 호환성 -유니코드 정규화의 구현에 따라 (자세한 정보는 [여기](https://jlajara.gitlab.io/Bypass_WAF_Unicode)에서 확인), 유니코드 호환성을 공유하는 문자들은 WAF를 우회하고 의도된 페이로드로 실행될 수 있습니다. 호환 가능한 문자는 [여기](https://www.compart.com/en/unicode)에서 찾을 수 있습니다. +Unicode 정규화의 구현 방식에 따라 (자세한 내용은 [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), 호환되는 Unicode 문자들이 WAF를 우회하여 의도한 payload로 실행될 수 있습니다. 호환 가능한 문자는 [here](https://www.compart.com/en/unicode)에서 확인할 수 있습니다. #### 예시 ```bash @@ -158,45 +159,55 @@ cache-deception/README.md # to the XSS payload on the right <img src⁼p onerror⁼'prompt⁽1⁾'﹥ --> <img src=p onerror='prompt(1)'> ``` -### 컨텍스트 WAF 우회하기 위한 인코딩 +### Bypass Contextual WAFs with encodings -[**이 블로그 포스트**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)에서 언급된 바와 같이, 사용자 입력의 컨텍스트를 유지할 수 있는 WAF를 우회하기 위해 WAF 기술을 악용하여 실제로 사용자 입력을 정규화할 수 있습니다. +As mentioned in [**this blog post**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), In order to bypass WAFs able to maintain a context of the user input we could abuse the WAF techniques to actually normalize the users input. -예를 들어, 포스트에서는 **Akamai가 사용자 입력을 10번 URL 디코딩했다**고 언급합니다. 따라서 `/onfocus`로 인식되며, **태그가 닫혔기 때문에 괜찮다고 생각할 수 있습니다**. 그러나 애플리케이션이 입력을 10번 URL 디코딩하지 않는 한, 피해자는 `/onfocus`로 보일 수 있는데, 이는 **태그가 닫혔다고 판단될 수도 있다**는 뜻이다. 그러나 애플리케이션이 입력을 10번 URL 디코드하지 않는 한, 실제 피해자는 `` - Imperva:`imperva.com/?x=` - AWS/Cloudfront:`docs.aws.amazon.com/?x=` - Cloudflare:`cloudflare.com/?x=` -또한, **일부 WAF가 사용자 입력의 컨텍스트를 이해하는 방식에 따라** 이를 악용할 수 있는 가능성이 있다고 언급됩니다. 블로그에서 제안된 예시는 Akamai가 `/*`와 `*/` 사이에 무엇이든 넣는 것을 허용했다는 것입니다(이는 일반적으로 주석으로 사용되기 때문일 수 있습니다). 따라서 `/*'or sleep(5)-- -*/`와 같은 SQL 인젝션은 포착되지 않으며, `/*`가 인젝션의 시작 문자열이고 `*/`가 주석 처리되기 때문에 유효합니다. +It's also mentioned that depending on **how some WAFs understand the context** of the user input, it might be possible to abuse it. The proposed example in the blog is that Akamai allow(ed) to put anything between `/*` and `*/` (potentially because this is commonly used as comments. Therefore, a SQLinjection such as `/*'or sleep(5)-- -*/` won't be caught and will be valid as `/*` is the starting string of the injection and `*/` is commented. -이러한 종류의 컨텍스트 문제는 WAF가 악용할 것으로 예상하는 것 외의 다른 취약점을 **악용하는 데에도 사용될 수 있습니다**(예: 이는 XSS 공격을 악용하는 데에도 사용될 수 있습니다). +어떤 WAF가 사용자 입력의 컨텍스트를 **어떻게 해석하는가에 따라** 이를 악용할 수 있다는 점도 언급되어 있다. 블로그의 예로 Akamai는 주석으로 흔히 사용되는 이유로 `/*`와 `*/` 사이에 어떤 내용이든 허용(또는 무시)했다고 한다. 따라서 `/*'or sleep(5)-- -*/` 같은 SQLinjection은 차단되지 않을 수 있는데, 이는 `/*`가 인젝션의 시작 문자열로 인식되고 `*/`는 주석 처리되기 때문이다. -### H2C 스머글링 +These kind of context problems can also be used to **abuse other vulnerabilities than the one expected** to be exploited by the WAF (e.g. this could also be used to exploit a XSS). + +이러한 컨텍스트 문제들은 WAF가 의도한 취약점 외의 다른 취약점(예: XSS)을 **악용하는 데에도** 사용될 수 있다. + +### H2C Smuggling {{#ref}} h2c-smuggling.md {{#endref}} -### IP 회전 +### IP Rotation -- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): ffuf와 함께 사용할 API 게이트웨이 URL 생성 -- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): fireprox와 유사 -- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): API 게이트웨이 IP를 사용하는 Burp Suite 플러그인 -- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 입력 파일 크기와 분할 계수에 따라 동적으로 결정된 수의 컨테이너 인스턴스가 활성화되며, 입력은 병렬 실행을 위해 청크로 분할됩니다. 예를 들어, 10,000줄 입력 파일에서 100줄의 분할 계수로 100개의 인스턴스가 100개의 청크를 처리합니다. +- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Generate an API gateway URL to by used with ffuf + - ffuf와 함께 사용하기 위한 API gateway URL을 생성한다. +- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Similar to fireprox + - fireprox와 유사하다. +- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Burp Suite plugin that uses API gateway IPs + - API gateway IP들을 사용하는 Burp Suite 플러그인. +- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): A dynamically determined number of container instances are activated based on the input file size and split factor, with the input split into chunks for parallel execution, such as 100 instances processing 100 chunks from a 10,000-line input file with a split factor of 100 lines. + - 입력 파일 크기와 split factor에 따라 동적으로 컨테이너 인스턴스 수를 활성화하고, 입력을 병렬 처리를 위해 청크로 분할한다. 예를 들어 split factor가 100라인일 때 10,000라인 입력 파일은 100개의 청크로 나뉘고 100개의 인스턴스가 병렬로 처리한다. - [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) -### 정규 표현식 우회 +### Regex Bypasses -정규 표현식 필터를 우회하기 위해 다양한 기술을 사용할 수 있습니다. 예를 들어 대소문자 교차, 줄 바꿈 추가, 페이로드 인코딩 등이 있습니다. 다양한 우회 방법에 대한 자료는 [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads)와 [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html)에서 찾을 수 있습니다. 아래의 예시는 [이 기사](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)에서 가져온 것입니다. +Different techniques can be used to bypass the regex filters on the firewalls. Examples include alternating case, adding line breaks, and encoding payloads. Resources for the various bypasses can be found at [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) and [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). The examples below were pulled from [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2). + +방화벽의 regex 필터를 우회하기 위해 다양한 기법을 사용할 수 있다. 예로는 대소문자 교체(alternating case), 줄바꿈 추가, payloads 인코딩 등이 있다. 여러 우회 기법 자료는 [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads)와 [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html)에서 찾을 수 있다. 아래 예제들은 [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)에서 가져온 것이다. ```bash #changing the case of the tag < #prepending an additional "<" @@ -219,7 +230,7 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri ``` ## 도구 -- [**nowafpls**](https://github.com/assetnote/nowafpls): 길이를 통해 WAF를 우회하기 위해 요청에 쓰레기 데이터를 추가하는 Burp 플러그인 +- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp 플러그인으로 요청에 불필요한 데이터를 추가하여 길이 기반으로 WAFs를 우회합니다 ## 참고자료 diff --git a/src/pentesting-web/xs-search/cookie-bomb-+-onerror-xs-leak.md b/src/pentesting-web/xs-search/cookie-bomb-+-onerror-xs-leak.md index 47ec68ee8..191bf4e30 100644 --- a/src/pentesting-web/xs-search/cookie-bomb-+-onerror-xs-leak.md +++ b/src/pentesting-web/xs-search/cookie-bomb-+-onerror-xs-leak.md @@ -2,7 +2,24 @@ {{#include ../../banners/hacktricks-training.md}} -다음 **스크립트**는 [**여기**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/)에서 가져온 것으로, 사용자가 **임의의 양의 쿠키를 삽입**할 수 있는 기능을 악용하고, 진짜 응답이 거짓 응답보다 더 클 것이라는 것을 알고 파일을 스크립트로 로드합니다. 성공하면 응답은 리디렉션이며 결과 URL이 더 길어져서 **서버에서 처리하기에는 너무 커서 오류 HTTP 상태 코드를 반환합니다**. 검색이 실패하면 URL이 짧기 때문에 아무 일도 일어나지 않습니다. +이 기법은 다음을 결합합니다: +- Cookie bombing: 대상 오리진에 대해 피해자 브라우저에 많은/큰 쿠키를 채워 이후 요청이 서버/요청 한도(요청 헤더 크기, 리다이렉트 시 URL 크기 등)에 도달하도록 만듭니다. +- Error-event oracle: 교차 출처 엔드포인트를 ``` +왜 popup (window.open)? +- 최신 브라우저들은 점점 third-party cookies를 차단합니다. 대상에 대해 top-level window를 열면 cookies가 first‑party가 되어 대상의 Set-Cookie 응답이 유지됩니다. 이로 인해 third‑party cookie restrictions가 있어도 cookie-bomb 단계가 가능해집니다. + +Generic probing helper +이미 target origin (first-party)에 많은 cookies를 설정할 방법이 있다면, 이 minimal oracle을 재사용하여 성공/실패가 다른 네트워크 결과(status/MIME/redirect)를 초래하는 모든 endpoint에 대해 사용할 수 있습니다: +```js +function probeError(url) { +return new Promise((resolve) => { +const s = document.createElement('script'); +s.src = url; +s.onload = () => resolve(false); // loaded successfully +s.onerror = () => resolve(true); // failed (e.g., 4xx/5xx, wrong MIME, blocked) +document.head.appendChild(s); +}); +} +``` +Tips to build the oracle +- Force the “positive” state to be heavier: 조건이 참일 때만 추가 redirect를 체인하거나, redirect URL이 제한 없는 사용자 입력을 반영하도록 만들어 추측한 prefix와 함께 길어지게 하세요. +- Inflate headers: 일관된 오류가 “heavy” 경로에서 관찰될 때까지 cookie bombing을 반복하세요. 서버는 일반적으로 헤더 크기에 상한을 두며, 많은 쿠키가 있을 때 더 빨리 실패합니다. +- Stabilize: 여러 병렬 cookie set 작업을 실행하고 반복적으로 프로브하여 타이밍 및 캐싱 잡음을 평균화하세요. + +Related XS-Search tricks +- URL length based oracles (no cookies needed)는 매우 긴 요청 대상(request target)을 강제할 수 있을 때 결합하거나 대신 사용할 수 있습니다: + +{{#ref}} +url-max-length-client-side.md +{{#endref}} + +Defenses and hardening +- Make success/failure responses indistinguishable: +- 조건부 redirects나 상태 간 응답 크기의 큰 차이를 피하세요. 상태와 관계없이 동일한 상태 코드, 동일한 Content-Type, 유사한 본문 길이를 반환하세요. +- Block cross-site subresource probes: +- SameSite cookies: 민감한 쿠키는 SameSite=Lax 또는 Strict로 설정하여