第2回 データベース強制アクセス制御をカスタマイズする
海外 浩平
日本SELinuxユーザ会
2007/9/4
SE-PostgreSQLでTEを使ってみる
それでは、TEを使ったアクセス制御を試してみましょう。まず、テーブルをセットアップするためにunconfined_tドメインでSE-PostgreSQLに接続し、以下のSQL文を実行してください。
CREATE TABLE drink ( id integer primary key, name varchar(20), price integer ); GRANT ALL ON drink TO public; INSERT INTO drink VALUES(1, 'water', 100); INSERT INTO drink VALUES(2, 'coke', 120); INSERT INTO drink VALUES(3, 'juice', 120); INSERT INTO drink VALUES(4, 'coffee', 180); INSERT INTO drink VALUES(5, 'beer', 260); INSERT INTO drink VALUES(6, 'wine', 420); |
各行のセキュリティコンテキストを確認すると、「sepgsql_table_t」というタイプが付与されていることが分かります。
postgres=> SELECT security_context, * FROM drink ; security_context | id | name | price ------------------------------------+----+--------+------- system_u:object_r:sepgsql_table_t | 1 | water | 100 system_u:object_r:sepgsql_table_t | 2 | coke | 120 system_u:object_r:sepgsql_table_t | 3 | juice | 120 system_u:object_r:sepgsql_table_t | 4 | coffee | 180 system_u:object_r:sepgsql_table_t | 5 | beer | 260 system_u:object_r:sepgsql_table_t | 6 | wine | 420 (6 rows) |
「sepgsql_table_t」は、SE-PostgreSQL標準セキュリティポリシーで定義済みのタイプで、管理ドメイン、一般ドメインの両方からすべての操作を許可されています。このタイプは新しいテーブル、カラム、行に対して自動的に付与されますが、SE-PostgreSQL標準セキュリティポリシーでは、ほかにも以下の定義済みタイプが提供されています。
タイプ名 |
定義済みの動作 |
sepgsql_table_t | すべての操作が可能、デフォルトのタイプ |
sepgsql_fixed_table_t | 一般ドメインはSELECT/INSERTのみ可能 |
sepgsql_ro_table_t | 一般ドメインはSELECTのみ可能 |
sepgsql_secret_table_t | 一般ドメインはアクセス不可 |
sepgsql_sysobj_t | すべての操作が可能、システムカタログに付与される |
表1 テーブル/カラム/行の定義済みタイプ一覧 |
それでは、各行のタイプを変更して、一般ドメインからアクセスが不可能であることを確認してみましょう。
以下のSQL文を実行し、‘juice’と‘coffee’に「sepgsql_ro_table_t」タイプを、‘beer’と‘wine’に「sepgsql_secret_table_t」タイプを付与します。
UPDATE drink SET security_context = 'user_u:object_r:sepgsql_ro_table_t' WHERE id in (3,4); UPDATE drink SET security_context = 'user_u:object_r:sepgsql_secret_table_t' WHERE id in (5,6); |
このSQL文を実行すると、以下のようにタイプが更新されていることが確認できます。
postgres=> SELECT security_context, * FROM drink ; security_context | id | name | price ------------------------------------+----+--------+------- system_u:object_r:sepgsql_table_t | 1 | water | 100 system_u:object_r:sepgsql_table_t | 2 | coke | 120 user_u:object_r:sepgsql_ro_table_t | 3 | juice | 120 user_u:object_r:sepgsql_ro_table_t | 4 | coffee | 180 user_u:object_r:sepgsql_secret_table_t | 5 | beer | 260 user_u:object_r:sepgsql_secret_table_t | 6 | wine | 420 (6 rows) |
ここでいったん、SE-PostgreSQLへのコネクションを閉じて、一般ドメインで再接続することにします。一般ドメイン用に設定したアカウントでSELinuxにログインし、以下のようにunconfined_t以外のドメインであることを確認してください。
[ymj@masu ~]$ id -Z user_u:user_r:user_t |
先ほどのdrinkテーブルを参照すると、「sepgsql_secret_table_t」タイプの行が結果セットからフィルタリングされていることが分かります。
postgres=> SELECT security_context, * FROM drink ; security_context | id | name | price ------------------------------------+----+--------+------- system_u:object_r:sepgsql_table_t | 1 | water | 100 system_u:object_r:sepgsql_table_t | 2 | coke | 120 user_u:object_r:sepgsql_ro_table_t | 3 | juice | 120 user_u:object_r:sepgsql_ro_table_t | 4 | coffee | 180 (4 rows) |
続いて、drinkテーブルを更新してみます。
postgres=> UPDATE drink SET price = 2 * price; UPDATE 2 postgres=> SELECT security_context, * FROM drink ; security_context | id | name | price ------------------------------------+----+--------+------- user_u:object_r:sepgsql_ro_table_t | 3 | juice | 120 user_u:object_r:sepgsql_ro_table_t | 4 | coffee | 180 system_u:object_r:sepgsql_table_t | 1 | water | 200 system_u:object_r:sepgsql_table_t | 2 | coke | 240 (4 rows) |
このように、一般ドメインは「sepgsql_ro_table_t」タイプの行を更新することはできません。「sepgsql_table_t」タイプを付与された‘water’と‘coke’の行だけが更新の対象となっています。
テーブル/カラムに対するアクセス制御
テーブルやカラムに対するアクセス制御は、SQLクエリーの実行前に実施されます。SQLクエリーで用いられるテーブルやカラムに対して必要な権限を持っていない場合、SE-PostgreSQLはトランザクションをアボートしてSQLの実行を即座に中止します。
それでは、実際に試してみましょう。まず、テーブルをセットアップするため、管理ドメインから以下のSQL文を実行してください。
CREATE TABLE customer ( id integer primary key, name varchar(32), credit varchar(20) ); GRANT ALL ON customer TO public; INSERT INTO customer VALUES (10, 'kaigai', '1234-5678-9012-3456'); INSERT INTO customer VALUES (11, 'ymj', '1111-2222-3333-4444'); INSERT INTO customer VALUES (12, 'tak', '5555-6666-7777-8888'); |
customerテーブルや、id、name、creditの各カラムにはデフォルトの「sepgsql_table_t」タイプが付与されており、参照や更新などすべての操作が許可されています。ここで、creditカラムに「sepgsql_secret_table_t」タイプを付与して、一般ドメインのcreditカラムへのアクセスを禁止してみましょう。
以下のように、SE-PostgreSQLの拡張ALTER TABLE構文を用いてテーブルやカラムのセキュリティコンテキストを変更することができます。
ALTER TABLE customer ALTER credit CONTEXT = 'system_u:object_r:sepgsql_secret_table_t'; |
セキュリティコンテキストの変更に成功したら、一般ドメインからSE-PostgreSQLに接続し、customerテーブルにアクセスを試してみましょう。
postgres=> SELECT security_context, * FROM customer; ERROR: SELinux: denied { select } scontext=user_u:user_r:user_t tcontext=system_u:object_r:sepgsql_secret_table_t tclass=db_column name=customer.credit |
このようにSE-PostgreSQLは、適切な権限のないカラムを参照するSQLクエリーの実行を中断してエラーメッセージを出力します。
なお、この場合でもcreditカラムへの参照を含まないSQLクエリーの実行は可能です。
postgres=> SELECT security_context, id, name FROM customer; security_context | id | name -----------------------------------+----+-------- system_u:object_r:sepgsql_table_t | 10 | kaigai system_u:object_r:sepgsql_table_t | 11 | ymj system_u:object_r:sepgsql_table_t | 12 | tak (3 rows) |
SQL関数に対するアクセス制御
テーブルやカラムと同様に、SQL関数の呼び出しに対してもアクセス制御が実施されます。
SQL関数には表2にあるタイプを付与することができますが、新しく定義したSQL関数に付与されるタイプはドメインによって異なることに気を付けてください。
管理ドメインがSQL関数を定義すると「sepgsql_proc_t」タイプが付与され、このSQL関数は誰でも実行することが可能です。一方、一般ドメインがSQL関数を定義すると「sepgsql_user_proc_t」タイプが付与されますが、管理ドメインはこのSQL関数を実行することができません(タイプを変更することは可能です)。
このような振る舞いがSE-PostgreSQL標準セキュリティポリシーで定義されている理由は、一般ドメインは必ずしも信頼できるドメインではないため、誤って管理ドメインが高い権限でそれを実行することを避けるためです。管理ドメインが一般ドメインで定義されたSQL関数を実行するには、それが無害であることを確認し、明示的に「sepgsql_proc_t」にタイプを変更する必要があります。
タイプ名 |
定義済みの動作 |
sepgsql_proc_t | すべてのドメインから実行可能、管理ドメインがSQL関数を作成した場合のデフォルト |
sepgsql_user_proc_t | 一般ドメインのみ実行可能、一般ドメインがSQL関数を作成した場合のデフォルト |
sepgsql_trusted_proc_t | すべてのドメインから実行可能、ドメイン遷移を引き起こす |
表2 SQL関数の定義済みタイプ一覧 |
では、実際の例を見てみましょう。
以下のSQL関数は、integer型の引数2つを加算して返却するもので、もちろん無害です。
CREATE FUNCTION integer_plus (integer, integer) RETURNS integer LANGUAGE sql AS 'SELECT $1 + $2'; |
一般ドメインでこのSQL関数を定義し、自身が呼び出すことは可能です。
postgres=> CREATE FUNCTION integer_plus (integer, integer) RETURNS integer postgres-> LANGUAGE sql AS 'SELECT $1 + $2'; CREATE FUNCTION postgres=> SELECT integer_plus(3, 4); integer_plus -------------- 7 (1 row) |
しかし、管理ドメインがこの関数を実行しようとしても拒否されます。
postgres=# SELECT integer_plus(3, 4); ERROR: SELinux: denied { execute } scontext=system_u:system_r:unconfined_t tcontext=user_u:object_r:sepgsql_user_proc_t tclass=db_procedure name=integer_plus |
管理ドメインは、このSQL関数が無害であり、高い権限の下で実行しても問題ないと判断すれば、SQL関数のタイプを「sepgsql_proc_t」に変更することが可能です。SQL関数のセキュリティコンテキストを変更するには、SE-PostgreSQLの拡張ALTER FUNCTION構文を利用します。
ALTER FUNCTION integer_plus (integer, integer) CONTEXT = 'system_u:object_r:sepgsql_proc_t'; |
これによって、管理ドメインがinteger_plus関数を実行することが可能になります。
postgres=# ALTER FUNCTION integer_plus (integer, integer) postgres-# CONTEXT = 'system_u:object_r:sepgsql_proc_t'; ALTER FUNCTION postgres=# SELECT integer_plus(3, 4); integer_plus -------------- 7 (1 row) |
2/3 |
Index | |
データベース強制アクセス制御をカスタマイズする | |
Page1 OSとデータベースのアクセス制御ポリシーを一元化する 最も詳細なアクセス制御を実現するType Enforcement 「誰が」「何に」「何をする」――TEのアクセス制御方式 ドメイン遷移とは SE-PostgreSQLとクライアントのドメイン |
|
Page2 SE-PostgreSQLでTEを使ってみる テーブル/カラムに対するアクセス制御 SQL関数に対するアクセス制御 |
|
Page3 Trusted Procedureの設定 条件変数booleanによるポリシーのカスタマイズ |
SE-PostgreSQLによるセキュアDB構築 連載インデックス |
- Windows起動前後にデバイスを守る工夫、ルートキットを防ぐ (2017/7/24)
Windows 10が備える多彩なセキュリティ対策機能を丸ごと理解するには、5つのスタックに分けて順に押さえていくことが早道だ。連載第1回は、Windows起動前の「デバイスの保護」とHyper-Vを用いたセキュリティ構成について紹介する。 - WannaCryがホンダやマクドにも。中学3年生が作ったランサムウェアの正体も話題に (2017/7/11)
2017年6月のセキュリティクラスタでは、「WannaCry」の残り火にやられたホンダや亜種に感染したマクドナルドに注目が集まった他、ランサムウェアを作成して配布した中学3年生、ランサムウェアに降伏してしまった韓国のホスティング企業など、5月に引き続きランサムウェアの話題が席巻していました。 - Recruit-CSIRTがマルウェアの「培養」用に内製した動的解析環境、その目的と工夫とは (2017/7/10)
代表的なマルウェア解析方法を紹介し、自社のみに影響があるマルウェアを「培養」するために構築した動的解析環境について解説する - 侵入されることを前提に考える――内部対策はログ管理から (2017/7/5)
人員リソースや予算の限られた中堅・中小企業にとって、大企業で導入されがちな、過剰に高機能で管理負荷の高いセキュリティ対策を施すのは現実的ではない。本連載では、中堅・中小企業が目指すべきセキュリティ対策の“現実解“を、特に標的型攻撃(APT:Advanced Persistent Threat)対策の観点から考える。
|
|