このトピックでは、SQL/Protectプラグインを使用して、SQLインジェクション攻撃からデータベースを保護する方法について説明します。
背景情報
開発者は、SQL インジェクション攻撃からデータベースを保護する責任があります。 データベース管理者は、わずかな種類のSQLインジェクション攻撃しか防止できません。 SQL/Protectは、クエリ要求に基づいてSQLインジェクション攻撃を検出します。 疑わしいクエリ要求が特定された場合、SQL/Protectはすぐにデータベース管理者にアラートを送信し、クエリの実行を防ぎます。
SQL インジェクション攻撃の種類
攻撃タイプ | 説明 |
不正なリレーション | 管理者はテーブルへのアクセスを制限できます。 この操作は面倒である。 SQL/Protectは、ユーザーがアクセスしたテーブルの関係を動的に追跡する学習モードを提供します。 学習モードでは、SQL/Protectは、アプリケーションがユーザーまたはグループに対してどのテーブルにアクセスできるかを自動的に学習できます。 SQL/Protectがパッシブモードまたはアクティブモードの場合、受信クエリは学習済みテーブルのリストに基づいてチェックされます。 |
ユーティリティコマンド | SQLインジェクション攻撃で使用される一般的な手法は、一般的なDDLステートメントなどのユーティリティコマンドを実行することです。 例えば、ユーザ定義関数は、他のテーブルのデータにアクセスするために作成される。 SQL/Protectは、一部のユーティリティコマンドの実行を妨げます。 ほとんどの場合、これらのコマンドはアプリケーションでは使用されません。 |
SQL 同語反復 | SQLインジェクション攻撃で使用される最も頻繁な手法は、トートロジーWHERE句を発行することです。 トートロジーWHERE句には、 |
無制限の DML 文 | 制限のないDMLステートメントは、条件が指定されていないデータベース更新ステートメントです。 これらのステートメントは、WHERE句を持たないUPDATEおよびDELETEステートメントです。 たとえば、攻撃者がユーザーのパスワードを更新または削除して、サービス拒否 (DoS) 攻撃を開始する可能性があります。 |
保護されたロール
保護されたロールは、SQL/Protectによって保護されたユーザーまたはグループです。 データベース管理者は、SQL/Protectを使用して保護ロールを指定できます。 SQL/Protectを使用して、さまざまな保護ロールに対してさまざまなレベルのインジェクション攻撃防止をカスタマイズできます。 SQLインジェクション攻撃の種類は、レベルによって異なります。
スーパーユーザー権限を持つロールを保護ロールにすることはできません。 保護された非スーパーユーザーロールは、保護されたスーパーユーザーロールになります。 この場合、SQL/Protectは、次のシナリオで保護されたスーパーユーザーロールの操作を実行します。
SQL/Protectは、保護されたスーパーユーザーによって実行されるコマンドごとにアラートを生成します。
SQL/Protectがアクティブモードの場合、SQL/Protectは保護されたスーパーユーザーによって実行されるすべてのコマンドをブロックします。
SQL/Protectが実行されている場合、スーパーユーザー権限を持つ保護ロールは共通ロールに変更されるか、保護されていないロールに復元されます。
さらに、保護されたロールによって実行される各コマンドは、統計ビューに記録されます。 このビューは、ロールに対する潜在的なSQLインジェクション攻撃の開始を特定するのに役立ちます。 統計は、SQLインジェクション攻撃のタイプに基づいて収集されます。
デフォルトでは、各データベースは最大 64 の保護されたロールと最大 1024 の保護されたテーブルをサポートします。 保護できるロールの最大数は、max_protected_rolesパラメーターで指定します。 保護できるテーブルの最大数は、max_protected_relationsパラメーターで指定します。
管理者ロールを使用してデータベースのSQL/Protectを構成する
次のコードブロックのパラメーターを変更して、SQL/Protectを有効にします。
set polar_sql_protect.enabled = on; #(The default value is off.) set polar_sql_protect.level = passive; #(Valid values: learn, active, and passive. The default value is passive.)targetdbという名前のテストデータベースとtestという名前のテストユーザーを作成します。
CREATE DATABASE targetdb; CREATE ROLE test; GRANT ALL ON DATABASE targetdb TO test; ALTER ROLE test LOGIN;テストデータベースtargetdbにログインします。 次に、次のステートメントを実行してSQL/Protectを作成し、保護されたロールを追加します。
CREATE EXTENSION sqlprotect; SELECT sqlprotect.protect_role('test');保護されたロールのリストを表示します。
SELECT * FROM sqlprotect.list_protected_users; SELECT * FROM sqlprotect.polar_sql_protect;要件に基づいてSQL/Protectが機能するモードを変更します。
SQL/Protectは、学習、アクティブ、パッシブの3つのモードで動作します。 デフォルトモードでは、パッシブ (passive) が設定されています。 詳細については、「SQL/Protectが保護されたロールを監視するモードの設定」をご参照ください。
SQL/Protectが学習するモードを変更します。
polar_sql_protect.level = learn; #(Valid values: learn, active, and passive. The default value is passive.)テストユーザーとして targetdb データベースにログインします。 次に、companyという名前のテストテーブルを作成し、SELECTステートメントとINSERTステートメントを実行します。
CREATE TABLE company(name VARCHAR(100), employee_num INT); SELECT * FROM company; INSERT INTO company VALUES('new', 1); SELECT * FROM company;テストユーザーが使用するテーブルに関する学習情報を表示します。
SELECT * FROM sqlprotect.polar_sql_protect_rel; SELECT * FROM sqlprotect.list_protected_rels;
SQL/Protectが動作するモードをパッシブに変更します。
polar_sql_protect.level = passive; #(Valid values: learn, active, and passive. The default value is passive.)テストユーザーとして targetdb データベースにログインします。
SQL文を注入します。
SELECT * FROM company WHERE 1 = 1; DELETE FROM company;説明SQL/Protectは、不正なSQLステートメントを示すメッセージを返します。 ただし、SQL/ProtectはSQL文の実行を妨げません。
SQL/Protectが機能するモードをアクティブに変更します。
polar_sql_protect.level = active; #(Valid values: learn, active, and passive. The default value is passive.)テストユーザーとして targetdb データベースにログインします。
SQL文を注入します。
SELECT * FROM company WHERE 1 = 1; DELETE FROM company;説明SQL/Protectは、不正なSQLステートメントを示すメッセージを返します。 SQL/Protectは、SQL文の実行も防ぎます。
保護されたロールの設定
保護されたロールは、polar_sql_protectテーブルに格納されます。 データベース管理者は、保護されているユーザーとユーザーグループを選択し、ユーザーとユーザーグループをテーブルに追加できます。
protect_role関数を呼び出して、ユーザーをテーブルに追加します。
SELECT sqlprotect.protect_role('userA');SQL/Protectが保護されたロールについて学習したテーブルに関する情報を照会します。
select * from sqlprotect.list_protected_users; select * from sqlprotect.polar_sql_protect;保護されたロールを削除するには、unprotect_role関数を呼び出します。
SELECT sqlprotect.unprotect_role('userA');
SQL/Protectが機能するモードを設定して、保護されたロールを監視する
polar_sql_protect.levelパラメーターは、SQL/Protectが保護されたロールを監視するモードを指定します。 学習、パッシブ、アクティブの3つのモードを使用できます。 デフォルトモードでは、パッシブ (passive) が設定されています。
仕事モード | 説明 |
learn | SQL/Protectは、ユーザーがアクセスするテーブルを追跡し、テーブルを記録します。 これにより、保護されたロールの動作を記録できます。 |
passive | 保護されたロールが不正なSQLステートメントを実行しようとした場合、SQL/Protectはアラートを送信しますが、SQLステートメントの実行を妨げません。 |
active | SQL/Protectは、すべての不正なSQL文が保護ロールによって実行されないようにします。 SQLステートメントが実行されないようにするために、攻撃者が侵入テストを実行するときにSQLファイアウォールが有効になります。 SQL/Protectは、SQLステートメントも追跡およびクエリします。 これにより、管理者は攻撃者よりも早くデータベースの脆弱性を特定できます。 |
たとえば、SQL/Protectが機能するモードをアクティブに変更する場合は、次のステートメントを実行します。
polar_sql_protect.level = active; #Set the mode in which SQL/Protect works to active.polar_sql_protectテーブルの一部のフィールドを変更して、ロールの保護対象を指定するには、次のステートメントを実行します。
targetdb=# \d sqlprotect.polar_sql_protect;
Table "sqlprotect.polar_sql_protect"
Column | Type | Collation | Nullable | Default
--------------------+---------+-----------+----------+---------
dbid | oid | | not null |
roleid | oid | | not null |
protect_relations | boolean | | |
allow_utility_cmds | boolean | | |
allow_tautology | boolean | | |
allow_empty_dml | boolean | | |
Indexes:
"polar_sql_protect_pkey" PRIMARY KEY, btree (roleid)たとえば、次のステートメントを実行して、16480という名前の保護されたロールのallow_utility_cmdsパラメーターをTRUEに設定すると、SQL/Protectは保護されたロール16480によって実行されるユーティリティコマンドをブロックします。
UPDATE sqlprotect.polar_sql_protect SET allow_utility_cmds = TRUE WHERE roleid = 16480;その他の操作
SQL/Protectを停止するには、次のステートメントを実行します。
polar_sql_protect.enabled = off #(The default value of this parameter is off.) polar_sql_protect.level = passive #(Valid values: learn, active, and passive. The default value is passive.)SQL/ProtectによってブロックされたSQLステートメントに関する統計を表示するには、次のステートメントを実行します。
SELECT * FROM sqlprotect.polar_sql_protect_stats;指定されたユーザーのSQL/ProtectブロックによってブロックされたSQLステートメントに関する統計を削除するには、次のステートメントを実行します。
SELECT sqlprotect.drop_stats('username');