> For the complete documentation index, see [llms.txt](https://help.aikido.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.aikido.dev/docs/docs-ja/zen-firewall/zen-features/idor-protection-with-zen-firewall.md).

# Zen Firewall による IDOR 保護

IDORとは、Insecure Direct Object Reference（安全でない直接オブジェクト参照）の略です。これはアクセス制御の不具合の一種で、データベースクエリが適切にスコープされていないために、あるアカウントが別のアカウントのデータにアクセスできてしまうものです。

マルチテナントのSaaSアプリケーションでは、データは通常、tenant\_id、account\_id、organization\_id などの列で分離されます。クエリがその列でのフィルタリングを忘れたり、誤った値を使ったりすると、アカウント間でデータが漏れる可能性があります。

Zen Firewall の IDOR 保護は、実行時に SQL クエリを解析し、テナントのスコープを自動的に強制します。クエリが安全でない場合、Zen は即座にエラーを返します。

これにより、本番障害の後ではなく、開発やテストの段階でマルチテナントの分離バグを検出できます。

脆弱性そのものの詳しい説明については、次のブログ記事を参照してください： [IDORの脆弱性を解説](https://www.aikido.dev/blog/idor-vulnerability-explained)

## 対応データベース

{% tabs %}
{% tab title="NodeJS" %}
現在対応しているドライバ：

* mysql および mysql2 経由の MySQL
* pg 経由の PostgreSQL
* SQLite（better-sqlite3 および node:sqlite パッケージ経由）

内部でこれらのドライバを使用する任意の ORM やクエリビルダーが対応しています。たとえば Drizzle、Knex、Sequelize、TypeORM です。

Prisma のように独自のクエリエンジンを使う ORM は、対応ドライバアダプターを使用するよう設定されていない限り対応していません。

{% hint style="info" %}
ESM を使用している場合は、 [ESM の注意点](https://github.com/AikidoSec/firewall-node/blob/main/docs/esm.md)を確認してください。インストルメントされていない ESM のサブ依存関係内のクエリは、Zen ではチェックできません。
{% endhint %}
{% endtab %}
{% endtabs %}

## 制限事項

* [NodeJS](https://github.com/AikidoSec/firewall-node/blob/main/docs/idor-protection.md#limitations)

## Zen が防止するもの

有効にすると、Zen は各関連クエリが次を満たすことを検証します：

* SELECT、UPDATE、DELETE で正しいテナント列をフィルタリングしている
* 正しいテナント ID 値を使用している
* すべての INSERT にテナント列が含まれている
* INSERT でテナント列が正しいテナント ID に設定されている<br>

Zen がブロックする問題の例：

* テナントフィルタのない SELECT により、あるアカウントが別のアカウントのデータを読み取れてしまう
* テナントのスコープがない UPDATE または DELETE
* テナント列を省略した INSERT
* 誤ったテナント ID を設定する INSERT

{% hint style="warning" %}
IDOR 保護は、ブロックモードでも検出モードでも、違反時には常に Error を投げます。テナントフィルタの欠如は外部からの攻撃ではなく、開発者のバグです。
{% endhint %}

## 仕組み

Zen は対応しているデータベースドライバをインストルメントし、実行時に SQL クエリを検査します。各リクエストで、アクティブなテナント ID を設定します。その後 Zen は、すべての関連クエリが次を満たすことを検証します：

1. 設定されたテナント列を参照している。
2. リクエストに対して設定されたものと同じテナント ID を使用している。

クエリがこれらの条件を満たさない場合、Zen はエラーを投げて実行を防ぎます。

## セットアップ

{% stepper %}
{% step %}
**起動時に IDOR 保護を有効にする**

アプリケーションの起動時に IDOR 保護を有効にする

{% tabs %}
{% tab title="NodeJS" %}

```js
import Zen from "@aikidosec/firewall";

Zen.enableIdorProtection({
  tenantColumnName: "tenant_id",
  excludedTables: ["users"],
});
```

設定オプション：

* `tenantColumnName`

  テーブル内でテナントを識別する列。たとえば tenant\_id、account\_id、organization\_id です。
* `excludedTables`

  単一テナントにスコープされていないため、チェック対象にすべきでないテーブル。たとえば、すべてのテナントのユーザーを含む共有 users テーブルです。
  {% endtab %}
  {% endtabs %}
  {% endstep %}

{% step %}
**リクエストごとにテナント ID を設定する**

IDOR 保護が有効な場合、すべてのリクエストにテナント ID が必要です。

setTenantId はリクエスト処理の早い段階、通常は認証後のミドルウェアで呼び出してください。

{% tabs %}
{% tab title="NodeJS" %}

```js
import Zen from "@aikidosec/firewall";

app.use((req, res, next) => {
  // 認証レイヤーからテナント ID を取得する
  Zen.setTenantId(req.user.organizationId);

  next();
});
```

{% hint style="warning" %}
リクエストに対して setTenantId が呼び出されない場合、SQL クエリが実行されたときに Zen は Error を投げます。
{% endhint %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**特定のクエリで IDOR チェックをバイパスする**

一部のクエリは意図的にグローバルです。たとえば、テナント横断の分析や社内管理レポートです。

特定のコードブロックで IDOR チェックをスキップするには、withoutIdorProtection を使用します：

```js
import Zen from "@aikidosec/firewall";

const result = await Zen.withoutIdorProtection(async () => {
  return await db.query(
    "SELECT count(*) FROM agents WHERE status = 'running'"
  );
});
```

コールバック内で実行されたクエリのみが IDOR 検証の対象外になります。

これは慎重に使い、テナント横断アクセスが明示的に必要な場合にのみ使用してください。
{% endstep %}
{% endstepper %}

## トラブルシューティング

### テナントフィルタがありません

```
Zen IDOR 保護: テーブル 'orders' のクエリに列 'tenant_id' のフィルタがありません
```

このクエリは、設定されたテナント列でフィルタしていません。これは SELECT、UPDATE、DELETE に適用されます。

例:

```
SELECT * FROM orders WHERE status = 'active';
```

tenant\_id でフィルタする条件を追加してください。

### テナント ID の値が誤っています

```
Zen IDOR 保護: テーブル 'orders' のクエリは 'tenant_id' を値 '456' でフィルタしていますが、テナント ID は '123' です
```

クエリはテナント列でフィルタしていますが、その値が以下で設定されたテナント ID と一致していません `setTenantId`.<br>

すべてのクエリが現在のリクエストコンテキストのテナント ID を使用するようにしてください。

### INSERT にテナント列がありません

```
Zen IDOR 保護: テーブル 'orders' への INSERT に列 'tenant_id' がありません
```

すべての INSERT にはテナント列を含める必要があります。

#### INSERT のテナント ID が誤っています

```
Zen IDOR 保護: テーブル 'orders' への INSERT は 'tenant_id' を '456' に設定していますが、テナント ID は '123' です
```

INSERT にはテナント列が含まれていますが、その値がアクティブなテナント ID と一致していません。

### \`setTenantId\` の呼び出しがありません

```
Zen IDOR 保護: このリクエストでは setTenantId() が呼び出されていません。IDOR 保護が有効な場合、すべてのリクエストにテナント ID が必要です。
```

データベースクエリが実行される前に、すべてのリクエストで setTenantId が呼び出されていることを確認してください。

## 常に許可される文

Zen がチェックするのは、行データを読み取るか変更する文のみです：

* SELECT
* INSERT
* UPDATE
* DELETE

次のものは認識され、IDOR エラーを発生させることはありません：

* CREATE TABLE、ALTER TABLE、DROP TABLE などの DDL 文
* SET、SHOW などのセッションコマンド
* BEGIN、COMMIT、ROLLBACK などのトランザクション文


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://help.aikido.dev/docs/docs-ja/zen-firewall/zen-features/idor-protection-with-zen-firewall.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
