1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle SQL FirewallをADBで試す

1
Posted at

はじめに

Oracle SQL Firewallを使うと、「このDBユーザーは普段どのようなSQLを実行するか」を学習し、その許可リストにないSQLを検知・遮断できます。

この記事では、Autonomous AI Database(以下、ADB)に専用の検証ユーザーを作成し、学習 → 許可リスト生成 → 監視 → 遮断 → 許可SQL追加を実際に試しました。さらに、SQLの条件値を変えたとき、バインド変数を使ったとき、接続元の条件を外れたときの動作も確認します。

検証日は2026年10月23日です。掲載している商品データはすべて架空です。実際の接続先・IPアドレス・個人のOSユーザー名・鍵・パスワードは掲載していません。<GENERATED_PASSWORD> などは公開用の置換表記です。

1. SQL Firewallとは

SQL Firewallは、Oracle Databaseの内部でSQLや接続の条件を確認するセキュリティ機能です。DBユーザーごとの許可リストを使い、普段と異なるSQLや想定外の接続を検知・遮断します。Oracle公式:SQL Firewallについて

たとえば、商品検索だけをするアプリが次のSQLを使っているとします。

SELECT product_id, product_name
FROM products
WHERE product_id = 1;

このSQLを学習しておけば、アプリが使うSQLの形を許可リストに登録できます。今回の検証では、ここに OR 1=1 を足したSQLや、未学習のUPDATEを遮断できました。

通常の権限管理との関係も押さえておきます。

仕組み 今回の例
DBの権限 自分が所有する商品テーブルをSELECT・UPDATEできる
SQL Firewall その権限があっても、許可リストにないSQLの実行を制限する

SQL Firewallで許可したからといって、テーブルへの権限が新しく付与されるわけではありません。今回は先にUPDATEが実行できることを確認し、その後Firewallによって拒否されることを試しています。

制御する対象は2種類

対象 内容
SQL 実行してよいSQL文
接続コンテキスト 接続元IPアドレス、OSユーザー名、クライアントのプログラム名

設定では、SQLだけを見る ENFORCE_SQL、接続条件だけを見る ENFORCE_CONTEXT、両方を見る ENFORCE_ALL を選べます。また、block => FALSE なら違反を記録して処理を続け、TRUE なら遮断します。Oracle公式:設定手順

SQL Firewallを使える条件

SQL Firewallは、クラウドやADBだけの機能ではありません。 Oracle Database自体に組み込まれており、対応するバージョン・エディション・ライセンスがあれば、オンプレミスのデータベースでも利用できます。Oracle公式ガイドでは、オンプレミスとクラウドに加えて、Data GuardやRACの構成でも利用できると説明されています。Oracle公式:対応する配置環境

利用前には、次の条件を確認します。

確認項目 条件・考え方
DBバージョン Oracle Database 23aiで追加された機能で、Oracle AI Database 26aiでも利用可能です。19c・21cのDB内蔵機能としては利用できません
配置場所 ADBに限定されず、オンプレミスの対応DBでも利用できます。ただし、配置場所だけで利用可否が決まるわけではなく、下記の提供形態・ライセンス条件も確認します
エディション・ライセンス Enterprise Editionでは、Oracle Database Vaultオプション、またはOracle Audit Vault and Database Firewallに含まれるSQL Firewallの利用権が必要です。「Enterprise Editionなら追加条件なしで使える」という意味ではありません
管理権限 設定を行うユーザーに SQL_FIREWALL_ADMIN ロールが必要です。保護されるアプリ用ユーザーへこの管理ロールを付与する必要はありません
有効化と学習 機能を有効化したうえで、対象ユーザーの通常SQLを学習し、許可リストを生成・有効化します。対応DBを用意しただけで自動的に遮断が始まるわけではありません

23aiでの機能追加はOracle Database 23ai新機能ガイド、管理権限はSQL Firewallの権限ガイドを参照してください。

提供形態ごとの目安は次のとおりです。2026年10月23日時点の公式資料に基づきます。

提供形態 SQL Firewallの利用可否・条件
Oracle AI Database Free 利用可能。公式の機能表では Y とされています。Freeの利用条件とリソース制限に従います
オンプレミスのEnterprise Edition 利用可能。ただし、上記のDatabase VaultまたはAudit Vault and Database Firewallによる利用権が必要です
Standard Edition 2 対象外。公式の機能表では N とされています
OCI Base Database Service Standard Editionおよび通常のEnterprise Editionは対象外。Enterprise Edition High Performance / Extreme Performanceは利用可能です
OCI Exadata Database Service 公式の機能表では利用可能です
Autonomous AI Database 対応する26ai環境で利用できます。この記事では、このADB環境で実測しています

エディション・サービス別の条件はOracle公式のライセンス情報(Security表)、ADBでの提供はセキュリティ機能の概要で確認できます。ライセンス表のSQL Firewall行には、クラウドについて Only available in OCI という注記もあるため、「任意のクラウド上のOracle DBで同じ条件で使える」とは解釈しないでください。

また、ここで扱うDB内蔵の SQL Firewall と、別製品の Oracle Audit Vault and Database Firewall は区別します。後者を導入する場合の対応DBバージョンや構成条件は、この記事のDB内蔵SQL Firewallの条件とは別です。

2. 今回の環境と検証計画

項目 実測・構成
データベース Autonomous AI Database / Oracle AI Database 26ai
DBが返したバージョン 23.26.4.1.0
実行場所 作業用Linuxサーバー
Python 3.9.25
接続ドライバー python-oracledb 3.4.1、Thinモード
DB接続 ウォレットを使うmTLS接続
管理操作 ADMIN。SQL_FIREWALL_ADMIN ロール保有を確認
保護対象 SQLFW_LAB_20261023
比較対象 SQLFW_CONTROL_20261023
データ 各専用スキーマに商品2行

製品名は26aiですが、今回のDBが返す内部バージョン文字列は 23.26.4.1.0 でした。

管理操作とアプリのSQLを分けることが、この検証のポイントです。

検証は次の順で進めました。

  1. DBバージョン・管理ロール・既存設定を確認する。
  2. 専用ユーザー2名と架空データを作る。
  3. 通常のSELECTを学習し、許可リストを生成する。
  4. 監視モードで未学習SQLと違反ログを確認する。
  5. 遮断モードでSQLの形・条件値・バインド変数を比較する。
  6. 正規SQLを追加学習し、許可リストを更新する。
  7. 接続条件を変更し、既存接続と新規接続を比較する。
  8. 専用ポリシーを停止し、ユーザーをロックして元の設定へ戻す。

既存システムのスキーマにはDDL・DML・権限変更を行っていません。専用ユーザーには CREATE SESSION と CREATE TABLE だけを付与し、各自のテーブルを使います。

3. コマンドの実行方法

作業用サーバーで実行した環境準備コマンドは次のとおりです。

umask 077
python3 -m venv /tmp/sqlfw-lab-20261023
/tmp/sqlfw-lab-20261023/bin/python -m pip --disable-pip-version-check install --quiet oracledb==3.4.1
/tmp/sqlfw-lab-20261023/bin/python -c "import oracledb; print(oracledb.__version__)"

結果:

3.4.1

DB操作はPythonからSQL・PL/SQLを実行しました。実際のリモート実行コマンドは次の形です。プログラムと秘密の接続設定をSSHの標準入力で渡しています。

/tmp/sqlfw-lab-20261023/bin/python -u -

ウォレットはアクセス権を制限した一時ディレクトリに配置し、処理終了時に削除しました。パスワードをコマンドの引数へ書き込む方法は使っていません。

以下のSQLは、このPython処理で実行したものを読みやすく改行しています。SQL*Plusの画面を再現したものではありません。DDL・PL/SQLの「成功」はドライバーが例外なしで完了したこと、SELECTの表は実際の取得行、エラー番号はドライバーが返したOracleエラー番号を示します。

4. 事前確認と専用ユーザーの準備

開始前の状態

管理接続で実行:

SELECT banner_full FROM v$version;

SELECT role FROM session_roles
WHERE role = 'SQL_FIREWALL_ADMIN';

SELECT status, exclude_jobs FROM dba_sql_firewall_status;

SELECT COUNT(*) FROM dba_sql_firewall_allow_lists;
SELECT COUNT(*) FROM dba_sql_firewall_captures;

SELECT COUNT(*) FROM dba_users
WHERE username IN ('SQLFW_LAB_20261023', 'SQLFW_CONTROL_20261023');

結果:

Oracle AI Database 26ai Enterprise Edition Release 23.26.4.1.0 - Production
Version 23.26.4.1.0

ROLE                : SQL_FIREWALL_ADMIN
STATUS              : DISABLED
EXCLUDE_JOBS        : Y
既存の許可リスト数  : 0
既存のキャプチャ数  : 0
専用ユーザーの重複数: 0

EXCLUDE_JOBS=Y はOracle Schedulerのジョブを対象外とする設定です。今回は変更していません。

全体設定が無効で既存のキャプチャ・許可リストが0件であることを確認してから、有効化しました。

BEGIN DBMS_SQL_FIREWALL.ENABLE; END;

結果:成功。

これはDB全体の機能を有効にする操作です。各ユーザーを保護するには、そのユーザーの許可リストを別途有効化します。

ユーザーと商品テーブルを作る

管理接続で実行:

CREATE USER SQLFW_LAB_20261023
  IDENTIFIED BY "<GENERATED_PASSWORD>" QUOTA 5M ON DATA;
GRANT CREATE SESSION, CREATE TABLE TO SQLFW_LAB_20261023;

CREATE USER SQLFW_CONTROL_20261023
  IDENTIFIED BY "<GENERATED_PASSWORD>" QUOTA 5M ON DATA;
GRANT CREATE SESSION, CREATE TABLE TO SQLFW_CONTROL_20261023;

結果:4文とも成功。パスワードは実行時にそれぞれ生成した値です。

次のSQLを、検証ユーザーと比較ユーザーの両方の接続で実行しました。

CREATE TABLE products (
  product_id NUMBER PRIMARY KEY,
  product_name VARCHAR2(30),
  price NUMBER
);

INSERT INTO products VALUES (1, 'Notebook', 300);
INSERT INTO products VALUES (2, 'Pen', 100);
COMMIT;

結果:テーブル作成成功、各INSERTは1行、COMMIT成功。それぞれのスキーマに独立した同名テーブルができます。

Firewall適用前には実行できることを確かめる

検証ユーザーで実行:

SELECT product_id, product_name, price
FROM products ORDER BY product_id;
PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100
SELECT product_id, product_name
FROM products WHERE product_id = 1 OR 1=1;

結果:Notebook、Penの2行を取得。

UPDATE products SET price = 1 WHERE product_id = 1;
ROLLBACK;

結果:UPDATEは1行更新、ROLLBACK成功。価格の変更は取り消しました。

5. 通常のSQLを学習する

管理接続でキャプチャを開始します。

BEGIN
  DBMS_SQL_FIREWALL.CREATE_CAPTURE(
    username       => 'SQLFW_LAB_20261023',
    top_level_only => TRUE,
    start_capture  => TRUE
  );
END;

結果:成功。

top_level_only => TRUE としたため、今回はクライアントが直接発行するSQLを対象にします。PL/SQL内部のSQLまで含める検証は行っていません。

検証ユーザーで、通常の検索SQLを1つ実行します。

SELECT product_id, product_name
FROM products WHERE product_id = 1;
PRODUCT_ID PRODUCT_NAME
1 Notebook

管理接続で停止し、取得結果を確認します。

BEGIN DBMS_SQL_FIREWALL.STOP_CAPTURE('SQLFW_LAB_20261023'); END;

SELECT sql_text FROM dba_sql_firewall_capture_logs
WHERE username = 'SQLFW_LAB_20261023'
ORDER BY sql_text;

結果:停止成功。取得したSQLは1種類でした。

SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"

実行時の 1 が :"SYS_B_0" に置き換わっています。SQLはそのままの文字列で保存されるのではなく、リテラル値などを正規化して記録されます。Oracle公式:SQL Firewallの開始と動作

学習させるのは、アプリが正規に実行するSQLです。攻撃を模したSQLまで学習期間に実行すると、それを許可するリストになってしまいます。

6. 許可リストを生成する

管理接続で実行:

BEGIN DBMS_SQL_FIREWALL.GENERATE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

SELECT sql_text FROM dba_sql_firewall_allowed_sql
WHERE username = 'SQLFW_LAB_20261023'
ORDER BY sql_text;

結果:生成成功。許可SQLは次の1種類です。

SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"

接続条件も学習されています。今回は個別の値を出力せず、登録件数だけ確認しました。

SELECT
  (SELECT COUNT(*) FROM dba_sql_firewall_allowed_ip_addr
    WHERE username='SQLFW_LAB_20261023') AS ip_count,
  (SELECT COUNT(*) FROM dba_sql_firewall_allowed_os_user
    WHERE username='SQLFW_LAB_20261023') AS os_user_count,
  (SELECT COUNT(*) FROM dba_sql_firewall_allowed_os_prog
    WHERE username='SQLFW_LAB_20261023') AS program_count
FROM dual;
IP_COUNT OS_USER_COUNT PROGRAM_COUNT
1 1 1

7. まずは監視だけにする

管理接続で実行:

BEGIN
  DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
    username => 'SQLFW_LAB_20261023',
    enforce  => DBMS_SQL_FIREWALL.ENFORCE_SQL,
    block    => FALSE
  );
END;

結果:成功。

検証ユーザーで、学習していない価格列付きのSQLを実行しました。

SELECT product_id, product_name, price
FROM products ORDER BY product_id;

結果:2行を取得できました。価格も300、100のままです。監視モードなので、未許可のSQLでも実行を継続します。

ログがすぐ見えない場合はFLUSH_LOGS

最初はSQL実行の2秒後に違反ログを参照しましたが、0行でした。後の参照では Allowed / SQL violation の記録を取得できました。

追加検証では、次を実行してからログを確認しました。

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

SELECT sql_text, firewall_action, cause
FROM dba_sql_firewall_violations
WHERE username = 'SQLFW_LAB_20261023'
ORDER BY occurred_at;

このプロシージャは、メモリー中のログをログ表へ反映します。操作直後のログ確認に使えることが公式に説明されています。Oracle公式:FLUSH_LOGS

追加検証では、監視モードで次の未学習SQLも実行しました。

SELECT COUNT(*) FROM products;

結果は 2。フラッシュ後、次の記録が増えました。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT COUNT (*) FROM PRODUCTS Allowed SQL violation

SQLが成功したことと、許可リストに一致したことは別です。 監視モードでは、違反ログも確認する必要があります。

8. 未許可のSQLを遮断する

管理接続で、監視用の許可リストをいったん無効化してから遮断モードで有効化しました。

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

BEGIN
  DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
    username => 'SQLFW_LAB_20261023',
    enforce  => DBMS_SQL_FIREWALL.ENFORCE_SQL,
    block    => TRUE
  );
END;

結果:両方成功。

学習済みSQLと、リテラル値だけの変更

SELECT product_id, product_name FROM products WHERE product_id = 1;
SELECT product_id, product_name FROM products WHERE product_id = 2;
条件 結果
product_id = 1 1, Notebook の1行
product_id = 2 2, Pen の1行

学習時に実行したのは 1 だけですが、2 に変えても成功しました。今回のSQLでは、条件値の違いは正規化され、同じ許可SQLとして扱われています。

これは行単位のアクセス制御とは異なります。商品1だけを見せたい場合、SQL Firewallの学習だけでは実現できません。

列追加・OR条件追加・UPDATE

検証ユーザーで実行:

SELECT product_id, product_name, price FROM products ORDER BY product_id;

SELECT product_id, product_name
FROM products WHERE product_id = 1 OR 1=1;

UPDATE products SET price = 1 WHERE product_id = 1;

ROLLBACK;
操作 実測結果
未学習の価格列付きSELECT ORA-47605
OR 1=1 を足したSELECT ORA-47605
未学習のUPDATE ORA-47605
ROLLBACK 成功

ORA-47605 はSQL Firewall違反を表すエラーです。今回はWebアプリに攻撃を送ったのではなく、条件改変後のSQLをDBへ直接発行して比較しました。あらゆるSQLインジェクションへの耐性を網羅検証したものではありません。

一方、比較ユーザーでは次の同じ形のSQLが成功しました。

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:2行。保護対象ユーザーの許可リストが、比較ユーザーには適用されていないことを確認できました。

9. 正規の機能追加に合わせてSQLを許可する

価格付きの検索が正規の新機能になったと想定し、そのSQLだけを追加学習します。

管理接続:

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;
BEGIN DBMS_SQL_FIREWALL.START_CAPTURE('SQLFW_LAB_20261023'); END;

検証ユーザー:

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:2行取得。

管理接続:

BEGIN DBMS_SQL_FIREWALL.STOP_CAPTURE('SQLFW_LAB_20261023'); END;

BEGIN
  DBMS_SQL_FIREWALL.APPEND_ALLOW_LIST(
    username => 'SQLFW_LAB_20261023',
    source   => DBMS_SQL_FIREWALL.CAPTURE_LOG
  );
END;

BEGIN
  DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
    username => 'SQLFW_LAB_20261023',
    enforce  => DBMS_SQL_FIREWALL.ENFORCE_SQL,
    block    => TRUE
  );
END;

結果:すべて成功。

同じ価格付きSELECTを再実行すると、遮断モードでも2行取得できました。一方、OR 1=1 を足したSQLを再実行すると、引き続き ORA-47605 でした。

今回は CAPTURE_LOG を追加元にしました。違反ログを一括で取り込むと、拒否したかったSQLも許可してしまう可能性があるため、学習するSQLを限定しています。

10. リテラルSQLとバインドSQLは実際のアプリの形で学習する

今回、予想と異なった点です。リテラルSQLを学習しただけでは、次のバインドSQLは許可されませんでした。

実際に実行したPython部分:

cursor.execute(
    'SELECT product_id, product_name FROM products WHERE product_id = :id',
    id=2
)

結果:ORA-47605。

そこで、遮断を一時停止してキャプチャを再開し、同じバインドSQLを id=1 で正常実行しました。停止後に FLUSH_LOGS、APPEND_ALLOW_LIST(..., source => DBMS_SQL_FIREWALL.CAPTURE_LOG) を実行し、再び遮断モードにしました。

許可リストには、次の3種類が表示されました。

SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID

再び上記のPythonコードを id=2 で実行すると、今度は 2, Pen を取得できました。その後も、学習していない SELECT COUNT(*) FROM products は ORA-47605 で拒否されました。

この結果から、今回の環境では、リテラルSQLの学習だけで明示的な :id のバインドSQLまで許可されるとは限らないことがわかります。バインド変数の名前やドライバーによる全差異まで試したわけではありません。アプリが実際に使うSQLとドライバーで学習・動作確認するのが確実です。

11. 接続条件を外れた新規接続を遮断する

まず、学習時と同じ接続条件で ENFORCE_ALL / block=TRUE に変更し、通常SELECTが成功することを確認しました。

次に管理接続で、検証ユーザーの許可プログラム名だけを変更しました。

BEGIN
  DBMS_SQL_FIREWALL.DELETE_ALLOWED_CONTEXT(
    username     => 'SQLFW_LAB_20261023',
    context_type => DBMS_SQL_FIREWALL.OS_PROGRAM,
    value        => NULL
  );
END;

BEGIN
  DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(
    username     => 'SQLFW_LAB_20261023',
    context_type => DBMS_SQL_FIREWALL.OS_PROGRAM,
    value        => 'sqlfw-deliberately-unmatched-client'
  );
END;

結果:成功。ここでの value => NULL は、指定した検証ユーザーのプログラム名条件をすべて削除する指定です。対象ユーザー自体をNULLにしているわけではありません。

続いて、許可リストを一度無効化し、接続条件だけをチェックするモードにしました。

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

BEGIN
  DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
    username => 'SQLFW_LAB_20261023',
    enforce  => DBMS_SQL_FIREWALL.ENFORCE_CONTEXT,
    block    => TRUE
  );
END;

結果:成功。

既存接続と新規接続では結果が異なった

操作 実測結果
変更前からある接続で通常SELECTを実行 1, Notebook を取得
同じユーザーで新しくDBへ接続 ORA-47605 で接続失敗

接続試験は、同じ接続ヘルパーで oracledb.connect(...) を再度呼び出して実行しました。実際の接続設定・パスワードは掲載していません。

公式ガイドにも、接続属性はセッション生成時に検査され、許可リスト有効化前からの既存セッションは条件に一致しなくても終了させず、この場合は違反を記録しないと説明されています。Oracle公式:実行時の考慮事項

接続条件の検証では、新しく接続し直すことが大切です。 初回は既存接続だけで試したため遮断されませんでしたが、新規接続で確認すると拒否されました。

最後に、検証ユーザーのプログラム名をワイルドカードで許可しました。

BEGIN
  DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(
    username     => 'SQLFW_LAB_20261023',
    context_type => DBMS_SQL_FIREWALL.OS_PROGRAM,
    value        => '%'
  );
END;

結果:成功。新規接続が成功し、通常SELECTで 1, Notebook を取得できました。% は今回の復旧確認用です。実運用では、許可するプログラム名を必要な範囲に絞ります。

今回は同じサーバーから、許可リスト側のプログラム名条件を意図的に不一致にした検証です。異なる実IPアドレスや異なるOSユーザーからの試験は行っていません。

12. 違反ログで「SQL違反」と「接続条件違反」を確認する

管理接続で FLUSH_LOGS の後、次を実行しました。

SELECT sql_text, firewall_action, cause
FROM dba_sql_firewall_violations
WHERE username = 'SQLFW_LAB_20261023'
ORDER BY occurred_at;

最終取得結果は11行です。次の表は代表的な5行を抜粋しています。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT COUNT (*) FROM PRODUCTS Allowed SQL violation
SELECT COUNT (*) FROM PRODUCTS Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
UPDATE PRODUCTS SET PRICE=:"SYS_B_0" WHERE PRODUCT_ID=:"SYS_B_1" Blocked SQL violation
NULL Blocked Context violation

接続時に拒否された行では、今回 SQL_TEXT はNULLでした。SQLを実行する前に接続が拒否された記録として区別できます。実測の FIREWALL_ACTION の表記は Allowed / Blocked でした。

13. (おまけ) 後片付けと既存環境の確認

専用ポリシーを停止し、専用ユーザーをロックしました。

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;
ALTER USER SQLFW_LAB_20261023 ACCOUNT LOCK;
ALTER USER SQLFW_CONTROL_20261023 ACCOUNT LOCK;

結果:成功。比較ユーザーのロックは初回検証の終了時、検証ユーザーの再ロックは追加検証の終了時にも実行しています。

次のSQLで、検証ユーザー以外の設定が追加されていないことを確認しました。

SELECT COUNT(*) FROM dba_sql_firewall_allow_lists
WHERE username <> 'SQLFW_LAB_20261023';

SELECT COUNT(*) FROM dba_sql_firewall_captures
WHERE username <> 'SQLFW_LAB_20261023';

結果:どちらも0件。開始前が無効だったため、全体設定も元に戻しました。

BEGIN DBMS_SQL_FIREWALL.DISABLE; END;

SELECT status, exclude_jobs FROM dba_sql_firewall_status;

SELECT username, account_status FROM dba_users
WHERE username IN ('SQLFW_LAB_20261023', 'SQLFW_CONTROL_20261023')
ORDER BY username;

SELECT username, status FROM dba_sql_firewall_captures
WHERE username = 'SQLFW_LAB_20261023';

SELECT username, status FROM dba_sql_firewall_allow_lists
WHERE username = 'SQLFW_LAB_20261023';
確認内容 結果
全体のSTATUS DISABLED(開始前と同じ)
EXCLUDE_JOBS Y(開始前と同じ)
検証ユーザー LOCKED
比較ユーザー LOCKED
専用キャプチャ DISABLED
専用許可リスト DISABLED

DBMS_SQL_FIREWALL.DISABLE は全体に作用します。今回は、開始前が無効、既存設定0件、終了時も他ユーザーの設定0件という条件を確認して実行しました。既存の保護設定がある環境で、そのまま実行してはいけません。

商品価格も管理接続で確認しました。

SELECT product_id, price
FROM SQLFW_LAB_20261023.products ORDER BY product_id;
PRODUCT_ID PRICE
1 300
2 100

確認用に専用テーブル・キャプチャ・許可リスト・ログは残し、ユーザー削除は行っていません。生成パスワードは成果物に保存していないため、再開する場合は管理者によるパスワード再設定が必要です。

作業用サーバーの既存アプリとnginxは検証前後で active でした。検証後、既存アプリの正しいヘルスチェック /healthz がHTTP 200、nginxがHTTP 301を返すことも確認しました。最初に試した /health・/ready・/ はアプリに存在しないURLで、前後とも404でした。これらの確認はサービス状態と応答の確認であり、既存アプリの全業務機能を網羅したテストではありません。

サーバーとADBは開始時に停止していたため、検証用に起動し、終了後に両方を停止状態へ戻しました。

14. 今回わかったこと

確認項目 実測結果
正常SQLの学習・許可リスト生成 成功
監視モードの未許可SQL 実行成功、Allowedの違反ログ
遮断モードの未許可SELECT・UPDATE ORA-47605
リテラル値だけを1から2へ変更 許可
OR条件を追加 ORA-47605
未学習の明示的バインドSQL ORA-47605
同じバインドSQLを学習後、値を変更 許可
正規SQLを追加学習 追加SQLだけ実行可能になることを確認
比較ユーザーのSQL 実行可能
接続条件に不一致の新規接続 ORA-47605、Context violation
既存セッション 接続条件の変更後も使用可能
操作直後の違反ログ FLUSH_LOGS後に取得確認

初回検証では14判定中11件が想定に一致し、3件は「ログがすぐに見える」「リテラル学習でバインドSQLも通る」「既存接続も接続条件違反で止まる」という検証側の想定と異なりました。この結果を消さずに残し、仕様確認と追加検証を行ったところ、追加の14判定はすべて確認できました。

SQL Firewallの導入では、実際のアプリが発行するSQLを十分に学習し、まず監視で不足を見つけ、その後に遮断へ進める流れが役立ちます。今回試していないストアドPL/SQL内部、ジョブ、接続プール、異なるIPからの接続などは、適用するシステムに合わせて別途確認する範囲です。

実行記録と参考資料

末尾の折りたたみ付録に、初回・追加検証の全116回のSQL、バインド値、結果、エラー番号を実行順で掲載しています。同じ内容を付属の sql-firewall/execution-transcript.md にも保存しました。sql-firewall/operations.md は環境操作の記録、sql-firewall/run_verification.py は実行に使った検証プログラムです。記事本文のSQLは説明用に改行しており、逐語的なSQLは実行記録を参照してください。

仕様の判断はOracle公式ドキュメントと今回の実測を根拠にしました。検証の進め方は、次の記事も参考にしています。

付録:全SQLと実行結果

初回・追加検証の全116回のSQLと結果を表示

検証日:2026-10-23(JST)。初回と追加確認を実行順に掲載する。
SQLは実行文字列を掲載し、CREATE USER・ALTER USERの生成パスワードだけを置換した。接続操作は接続設定を非公開にした呼び出し形を示す。
DDL・PL/SQLは「SUCCESS」が例外なしの完了を示す。rowcount=0はDDLの対象件数や失敗を意味しない。
SELECTは全取得行を掲載。NULLはDBが返したNULL値。SQLの末尾は読みやすさのためセミコロンを補っている。

初回の3件の想定不一致もそのまま残す。ログ反映、明示的バインドSQLの学習、新規接続の検査について追加確認し、記事で説明した。

初回検証

{
  "step": "START",
  "time_jst": "2026-10-23T09:59:03.529841+09:00",
  "client": "python-oracledb",
  "python": "3.9.25"
}

VERSION

実行者:ADMIN

SELECT banner_full FROM v$version;

結果:成功。

取得行数:1。

BANNER_FULL
Oracle AI Database 26ai Enterprise Edition Release 23.26.4.1.0 - Production
Version 23.26.4.1.0

INITIAL_STATUS

実行者:ADMIN

SELECT status, exclude_jobs FROM dba_sql_firewall_status;

結果:成功。

取得行数:1。

STATUS EXCLUDE_JOBS
DISABLED Y

ROLE

実行者:ADMIN

SELECT role FROM session_roles WHERE role = 'SQL_FIREWALL_ADMIN';

結果:成功。

取得行数:1。

ROLE
SQL_FIREWALL_ADMIN

INITIAL_POLICIES

実行者:ADMIN

SELECT COUNT(*) FROM dba_sql_firewall_allow_lists;

結果:成功。

取得行数:1。

COUNT(*)
0

INITIAL_CAPTURES

実行者:ADMIN

SELECT COUNT(*) FROM dba_sql_firewall_captures;

結果:成功。

取得行数:1。

COUNT(*)
0

COLLISION

実行者:ADMIN

SELECT COUNT(*) FROM dba_users WHERE username IN ('SQLFW_LAB_20261023','SQLFW_CONTROL_20261023');

結果:成功。

取得行数:1。

COUNT(*)
0

GLOBAL_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE; END;

結果:成功。

ドライバーのrowcount:0。

CREATE_SQLFW_LAB_20261023

実行者:ADMIN

CREATE USER SQLFW_LAB_20261023 IDENTIFIED BY "<GENERATED_PASSWORD>" QUOTA 5M ON DATA;

結果:成功。

ドライバーのrowcount:0。

GRANT_SQLFW_LAB_20261023

実行者:ADMIN

GRANT CREATE SESSION, CREATE TABLE TO SQLFW_LAB_20261023;

結果:成功。

ドライバーのrowcount:0。

TABLE_SQLFW_LAB_20261023

実行者:SQLFW_LAB_20261023

CREATE TABLE products (product_id NUMBER PRIMARY KEY, product_name VARCHAR2(30), price NUMBER);

結果:成功。

ドライバーのrowcount:0。

DATA1_SQLFW_LAB_20261023

実行者:SQLFW_LAB_20261023

INSERT INTO products VALUES (1, 'Notebook', 300);

結果:成功。

ドライバーのrowcount:1。

DATA2_SQLFW_LAB_20261023

実行者:SQLFW_LAB_20261023

INSERT INTO products VALUES (2, 'Pen', 100);

結果:成功。

ドライバーのrowcount:1。

COMMIT_SQLFW_LAB_20261023

実行者:SQLFW_LAB_20261023

COMMIT;

結果:成功。

ドライバーのrowcount:0。

CREATE_SQLFW_CONTROL_20261023

実行者:ADMIN

CREATE USER SQLFW_CONTROL_20261023 IDENTIFIED BY "<GENERATED_PASSWORD>" QUOTA 5M ON DATA;

結果:成功。

ドライバーのrowcount:0。

GRANT_SQLFW_CONTROL_20261023

実行者:ADMIN

GRANT CREATE SESSION, CREATE TABLE TO SQLFW_CONTROL_20261023;

結果:成功。

ドライバーのrowcount:0。

TABLE_SQLFW_CONTROL_20261023

実行者:SQLFW_CONTROL_20261023

CREATE TABLE products (product_id NUMBER PRIMARY KEY, product_name VARCHAR2(30), price NUMBER);

結果:成功。

ドライバーのrowcount:0。

DATA1_SQLFW_CONTROL_20261023

実行者:SQLFW_CONTROL_20261023

INSERT INTO products VALUES (1, 'Notebook', 300);

結果:成功。

ドライバーのrowcount:1。

DATA2_SQLFW_CONTROL_20261023

実行者:SQLFW_CONTROL_20261023

INSERT INTO products VALUES (2, 'Pen', 100);

結果:成功。

ドライバーのrowcount:1。

COMMIT_SQLFW_CONTROL_20261023

実行者:SQLFW_CONTROL_20261023

COMMIT;

結果:成功。

ドライバーのrowcount:0。

BEFORE_UNSEEN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100

BEFORE_INJECTION

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1 OR 1=1;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME
1 Notebook
2 Pen

BEFORE_UPDATE

実行者:SQLFW_LAB_20261023

UPDATE products SET price = 1 WHERE product_id = 1;

結果:成功。

ドライバーのrowcount:1。

BEFORE_ROLLBACK

実行者:SQLFW_LAB_20261023

ROLLBACK;

結果:成功。

ドライバーのrowcount:0。

CAPTURE_START

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.CREATE_CAPTURE(username=>'SQLFW_LAB_20261023',top_level_only=>TRUE,start_capture=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

TRAIN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — learned query returns one row

CAPTURE_STOP

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.STOP_CAPTURE('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

CAPTURE_LOG

実行者:ADMIN

SELECT sql_text FROM dba_sql_firewall_capture_logs WHERE username='SQLFW_LAB_20261023' ORDER BY sql_text;

結果:成功。

取得行数:1。

SQL_TEXT
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"

GENERATE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.GENERATE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

ALLOWED_SQL

実行者:ADMIN

SELECT sql_text FROM dba_sql_firewall_allowed_sql WHERE username='SQLFW_LAB_20261023' ORDER BY sql_text;

結果:成功。

取得行数:1。

SQL_TEXT
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"

CONTEXT_COUNTS

実行者:ADMIN

SELECT (SELECT COUNT(*) FROM dba_sql_firewall_allowed_ip_addr WHERE username='SQLFW_LAB_20261023') AS ip_count, (SELECT COUNT(*) FROM dba_sql_firewall_allowed_os_user WHERE username='SQLFW_LAB_20261023') AS os_user_count, (SELECT COUNT(*) FROM dba_sql_firewall_allowed_os_prog WHERE username='SQLFW_LAB_20261023') AS program_count FROM dual;

結果:成功。

取得行数:1。

IP_COUNT OS_USER_COUNT PROGRAM_COUNT
1 1 1

MONITOR_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023', enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL, block=>FALSE); END;

結果:成功。

ドライバーのrowcount:0。

MONITOR_UNSEEN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100

判定:PASS — monitor allows unknown SQL

MONITOR_LOG

実行者:ADMIN

SELECT sql_text, firewall_action, cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:0。

判定:想定不一致 — monitor logs violation without blocking

BLOCK_ENABLE_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

BLOCK_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023', enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL, block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

BLOCK_NORMAL

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — learned SQL allowed

BLOCK_LITERAL

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 2;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
2 Pen

判定:PASS — different literal allowed

BLOCK_BIND

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = :id;

バインド値:{"id": 2}。

結果:ORA-47605(SQL Firewall違反)。

判定:想定不一致 — bind value allowed

BLOCK_UNSEEN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — BLOCK_UNSEEN

BLOCK_INJECTION

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1 OR 1=1;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — BLOCK_INJECTION

BLOCK_UPDATE

実行者:SQLFW_LAB_20261023

UPDATE products SET price = 1 WHERE product_id = 1;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — BLOCK_UPDATE

BLOCK_ROLLBACK

実行者:SQLFW_LAB_20261023

ROLLBACK;

結果:成功。

ドライバーのrowcount:0。

CONTROL_UNSEEN

実行者:SQLFW_CONTROL_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100

判定:PASS — control user unaffected

BLOCK_LOG

実行者:ADMIN

SELECT sql_text, firewall_action, cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:0。

CHANGE_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

RETRAIN_START

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.START_CAPTURE('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

RETRAIN_APPROVED

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100

RETRAIN_STOP

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.STOP_CAPTURE('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

APPEND

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.APPEND_ALLOW_LIST(username=>'SQLFW_LAB_20261023',source=>DBMS_SQL_FIREWALL.CAPTURE_LOG); END;

結果:成功。

ドライバーのrowcount:0。

UPDATED_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023', enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL, block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

UPDATED_UNSEEN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name, price FROM products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRODUCT_NAME PRICE
1 Notebook 300
2 Pen 100

判定:PASS — newly approved SQL succeeds

UPDATED_INJECTION

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1 OR 1=1;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — UPDATED_INJECTION

UPDATED_SQL

実行者:ADMIN

SELECT sql_text FROM dba_sql_firewall_allowed_sql WHERE username='SQLFW_LAB_20261023' ORDER BY sql_text;

結果:成功。

取得行数:2。

SQL_TEXT
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID

CONTEXT_CLEAR_PROGRAM

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DELETE_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023', context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM, value=>NULL); END;

結果:成功。

ドライバーのrowcount:0。

CONTEXT_SET_PROGRAM

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023', context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM, value=>'sqlfw-deliberately-unmatched-client'); END;

結果:成功。

ドライバーのrowcount:0。

CONTEXT_ENABLE_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

CONTEXT_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023', enforce=>DBMS_SQL_FIREWALL.ENFORCE_CONTEXT, block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

CONTEXT_BLOCK

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:想定不一致 — CONTEXT_BLOCK

CONTEXT_ALLOW_ANY_PROGRAM

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023', context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM, value=>'%'); END;

結果:成功。

ドライバーのrowcount:0。

CONTEXT_RECOVER

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — context change takes effect immediately

FINAL_VIOLATIONS

実行者:ADMIN

SELECT sql_text, firewall_action, cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:5。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Allowed SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
UPDATE PRODUCTS SET PRICE=:"SYS_B_0" WHERE PRODUCT_ID=:"SYS_B_1" Blocked SQL violation

CLEAN_POLICY_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

CLEAN_LOCK_SQLFW_LAB_20261023

実行者:ADMIN

ALTER USER SQLFW_LAB_20261023 ACCOUNT LOCK;

結果:成功。

ドライバーのrowcount:0。

CLEAN_LOCK_SQLFW_CONTROL_20261023

実行者:ADMIN

ALTER USER SQLFW_CONTROL_20261023 ACCOUNT LOCK;

結果:成功。

ドライバーのrowcount:0。

FOREIGN_POLICIES

実行者:ADMIN

SELECT COUNT(*) FROM dba_sql_firewall_allow_lists WHERE username<>'SQLFW_LAB_20261023';

結果:成功。

取得行数:1。

COUNT(*)
0

FOREIGN_CAPTURES

実行者:ADMIN

SELECT COUNT(*) FROM dba_sql_firewall_captures WHERE username<>'SQLFW_LAB_20261023';

結果:成功。

取得行数:1。

COUNT(*)
0

GLOBAL_RESTORE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE; END;

結果:成功。

ドライバーのrowcount:0。

FINAL_STATUS

実行者:ADMIN

SELECT status, exclude_jobs FROM dba_sql_firewall_status;

結果:成功。

取得行数:1。

STATUS EXCLUDE_JOBS
DISABLED Y

FINAL_USERS

実行者:ADMIN

SELECT username,account_status FROM dba_users WHERE username IN ('SQLFW_LAB_20261023','SQLFW_CONTROL_20261023') ORDER BY username;

結果:成功。

取得行数:2。

USERNAME ACCOUNT_STATUS
SQLFW_CONTROL_20261023 LOCKED
SQLFW_LAB_20261023 LOCKED

FINAL_CAPTURE

実行者:ADMIN

SELECT username,status FROM dba_sql_firewall_captures WHERE username='SQLFW_LAB_20261023';

結果:成功。

取得行数:1。

USERNAME STATUS
SQLFW_LAB_20261023 DISABLED

FINAL_POLICY

実行者:ADMIN

SELECT username,status FROM dba_sql_firewall_allow_lists WHERE username='SQLFW_LAB_20261023';

結果:成功。

取得行数:1。

USERNAME STATUS
SQLFW_LAB_20261023 DISABLED
{
  "step": "SUMMARY",
  "passed": 11,
  "total": 14,
  "all_passed": false
}

追加検証

{
  "step": "FOLLOWUP_START",
  "time_jst": "2026-10-23T10:00:43.464586+09:00"
}

F_INITIAL

実行者:ADMIN

SELECT status,exclude_jobs FROM dba_sql_firewall_status;

結果:成功。

取得行数:1。

STATUS EXCLUDE_JOBS
DISABLED Y

F_FOREIGN

実行者:ADMIN

SELECT (SELECT COUNT(*) FROM dba_sql_firewall_allow_lists WHERE username<>'SQLFW_LAB_20261023'), (SELECT COUNT(*) FROM dba_sql_firewall_captures WHERE username<>'SQLFW_LAB_20261023') FROM dual;

結果:成功。

取得行数:1。

(SELECTCOUNT(*)FROMDBA_SQL_FIREWALL_ALLOW_LISTSWHEREUSERNAME<>'SQLFW_LAB_20261023') (SELECTCOUNT(*)FROMDBA_SQL_FIREWALL_CAPTURESWHEREUSERNAME<>'SQLFW_LAB_20261023')
0 0

F_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE; END;

結果:成功。

ドライバーのrowcount:0。

F_UNLOCK

実行者:ADMIN

ALTER USER SQLFW_LAB_20261023 IDENTIFIED BY "<GENERATED_PASSWORD>" ACCOUNT UNLOCK;

結果:成功。

ドライバーのrowcount:0。

F_FLUSH_BASELINE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

結果:成功。

ドライバーのrowcount:0。

F_BASELINE_LOG_FLUSH

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

結果:成功。

ドライバーのrowcount:0。

F_BASELINE_LOG

実行者:ADMIN

SELECT sql_text,firewall_action,cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:6。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Allowed SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
UPDATE PRODUCTS SET PRICE=:"SYS_B_0" WHERE PRODUCT_ID=:"SYS_B_1" Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation

F_MONITOR

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023',enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL,block=>FALSE); END;

結果:成功。

ドライバーのrowcount:0。

F_MONITOR_SQL

実行者:SQLFW_LAB_20261023

SELECT COUNT(*) FROM products;

結果:成功。

取得行数:1。

COUNT(*)
2

判定:PASS — monitor unknown aggregate returns two

F_MONITOR_LOG_FLUSH

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

結果:成功。

ドライバーのrowcount:0。

F_MONITOR_LOG

実行者:ADMIN

SELECT sql_text,firewall_action,cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:7。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Allowed SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
UPDATE PRODUCTS SET PRICE=:"SYS_B_0" WHERE PRODUCT_ID=:"SYS_B_1" Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
SELECT COUNT (*) FROM PRODUCTS Allowed SQL violation

判定:PASS — flushed monitor log increases Allowed count

F_BLOCK_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_BLOCK

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023',enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL,block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

F_BLOCK_AGGREGATE

実行者:SQLFW_LAB_20261023

SELECT COUNT(*) FROM products;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — F_BLOCK_AGGREGATE

F_BIND_BEFORE_TRAIN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = :id;

バインド値:{"id": 1}。

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — F_BIND_BEFORE_TRAIN

F_TRAIN_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_TRAIN_START

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.START_CAPTURE('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_TRAIN_BIND

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = :id;

バインド値:{"id": 1}。

結果:成功。

取得行数:1。

COLUMN_1 COLUMN_2
1 Notebook

判定:PASS — F_TRAIN_BIND

F_TRAIN_STOP

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.STOP_CAPTURE('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_TRAIN_FLUSH

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

結果:成功。

ドライバーのrowcount:0。

F_APPEND

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.APPEND_ALLOW_LIST(username=>'SQLFW_LAB_20261023',source=>DBMS_SQL_FIREWALL.CAPTURE_LOG); END;

結果:成功。

ドライバーのrowcount:0。

F_ALLOWED

実行者:ADMIN

SELECT sql_text FROM dba_sql_firewall_allowed_sql WHERE username='SQLFW_LAB_20261023' ORDER BY sql_text;

結果:成功。

取得行数:3。

SQL_TEXT
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0"
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID

F_REENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023',enforce=>DBMS_SQL_FIREWALL.ENFORCE_SQL,block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

F_BIND_AFTER_TRAIN

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = :id;

バインド値:{"id": 2}。

結果:成功。

取得行数:1。

COLUMN_1 COLUMN_2
2 Pen

判定:PASS — F_BIND_AFTER_TRAIN

F_STILL_BLOCK_AGGREGATE

実行者:SQLFW_LAB_20261023

SELECT COUNT(*) FROM products;

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — F_STILL_BLOCK_AGGREGATE

F_ALL_ENABLE_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_ALL_ENABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023',enforce=>DBMS_SQL_FIREWALL.ENFORCE_ALL,block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

F_ALL_NORMAL

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — combined mode accepts trusted context and SQL

F_PROGRAM_CLEAR

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DELETE_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023',context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM,value=>NULL); END;

結果:成功。

ドライバーのrowcount:0。

F_PROGRAM_RESTRICT

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023',context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM,value=>'sqlfw-deliberately-unmatched-client'); END;

結果:成功。

ドライバーのrowcount:0。

F_CONTEXT_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_CONTEXT

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(username=>'SQLFW_LAB_20261023',enforce=>DBMS_SQL_FIREWALL.ENFORCE_CONTEXT,block=>TRUE); END;

結果:成功。

ドライバーのrowcount:0。

F_EXISTING_SESSION

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — preexisting session remains usable

F_NEW_CONNECTION_BLOCK

実行者:SQLFW_LAB_20261023

oracledb.connect(user=LAB, password=<GENERATED_PASSWORD>, **private_connection_settings)

結果:ORA-47605(SQL Firewall違反)。

判定:PASS — new connection rejected by context

F_PROGRAM_ALLOW

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(username=>'SQLFW_LAB_20261023',context_type=>DBMS_SQL_FIREWALL.OS_PROGRAM,value=>'%'); END;

結果:成功。

ドライバーのrowcount:0。

F_NEW_CONNECTION_RECOVER

実行者:SQLFW_LAB_20261023

oracledb.connect(user=LAB, password=<GENERATED_PASSWORD>, **private_connection_settings)

結果:成功。

F_FRESH_SQL

実行者:SQLFW_LAB_20261023

SELECT product_id, product_name FROM products WHERE product_id = 1;

結果:成功。

取得行数:1。

PRODUCT_ID PRODUCT_NAME
1 Notebook

判定:PASS — fresh connection recovers

F_FINAL_LOG_FLUSH

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.FLUSH_LOGS; END;

結果:成功。

ドライバーのrowcount:0。

F_FINAL_LOG

実行者:ADMIN

SELECT sql_text,firewall_action,cause FROM dba_sql_firewall_violations WHERE username='SQLFW_LAB_20261023' ORDER BY occurred_at;

結果:成功。

取得行数:11。

SQL_TEXT FIREWALL_ACTION CAUSE
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Allowed SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME,PRICE FROM PRODUCTS ORDER BY PRODUCT_ID Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
UPDATE PRODUCTS SET PRICE=:"SYS_B_0" WHERE PRODUCT_ID=:"SYS_B_1" Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:"SYS_B_0" OR :"SYS_B_1"=:"SYS_B_2" Blocked SQL violation
SELECT COUNT (*) FROM PRODUCTS Allowed SQL violation
SELECT COUNT (*) FROM PRODUCTS Blocked SQL violation
SELECT PRODUCT_ID,PRODUCT_NAME FROM PRODUCTS WHERE PRODUCT_ID=:ID Blocked SQL violation
SELECT COUNT (*) FROM PRODUCTS Blocked SQL violation
NULL Blocked Context violation

判定:PASS — context violation is logged

判定:PASS — monitor and blocked SQL are logged

F_DATA_INTEGRITY

実行者:ADMIN

SELECT product_id,price FROM SQLFW_LAB_20261023.products ORDER BY product_id;

結果:成功。

取得行数:2。

PRODUCT_ID PRICE
1 300
2 100

判定:PASS — product prices unchanged

F_POLICY_DISABLE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST('SQLFW_LAB_20261023'); END;

結果:成功。

ドライバーのrowcount:0。

F_LOCK

実行者:ADMIN

ALTER USER SQLFW_LAB_20261023 ACCOUNT LOCK;

結果:成功。

ドライバーのrowcount:0。

F_FINAL_FOREIGN

実行者:ADMIN

SELECT (SELECT COUNT(*) FROM dba_sql_firewall_allow_lists WHERE username<>'SQLFW_LAB_20261023'), (SELECT COUNT(*) FROM dba_sql_firewall_captures WHERE username<>'SQLFW_LAB_20261023') FROM dual;

結果:成功。

取得行数:1。

(SELECTCOUNT(*)FROMDBA_SQL_FIREWALL_ALLOW_LISTSWHEREUSERNAME<>'SQLFW_LAB_20261023') (SELECTCOUNT(*)FROMDBA_SQL_FIREWALL_CAPTURESWHEREUSERNAME<>'SQLFW_LAB_20261023')
0 0

F_GLOBAL_RESTORE

実行者:ADMIN

BEGIN DBMS_SQL_FIREWALL.DISABLE; END;

結果:成功。

ドライバーのrowcount:0。

F_FINAL_STATUS

実行者:ADMIN

SELECT status,exclude_jobs FROM dba_sql_firewall_status;

結果:成功。

取得行数:1。

STATUS EXCLUDE_JOBS
DISABLED Y

F_FINAL_USERS

実行者:ADMIN

SELECT username,account_status FROM dba_users WHERE username IN ('SQLFW_LAB_20261023','SQLFW_CONTROL_20261023') ORDER BY username;

結果:成功。

取得行数:2。

USERNAME ACCOUNT_STATUS
SQLFW_CONTROL_20261023 LOCKED
SQLFW_LAB_20261023 LOCKED

F_FINAL_POLICY

実行者:ADMIN

SELECT username,status,enforce,block FROM dba_sql_firewall_allow_lists WHERE username='SQLFW_LAB_20261023';

結果:成功。

取得行数:1。

USERNAME STATUS ENFORCE BLOCK
SQLFW_LAB_20261023 DISABLED ENFORCE_CONTEXT Y
{
  "step": "FOLLOWUP_SUMMARY",
  "passed": 14,
  "total": 14,
  "all_passed": true
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?