
第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構築 バックナンバー
- 第1回 SELinuxのアクセス制御をデータベースでも
- 第2回 データベース強制アクセス制御をカスタマイズする
- 第3回 アクセス制御の実装は“巧妙”かつ“大胆”に
- 最終回 SE-PostgreSQLの実運用に向けて
| SE-PostgreSQLによるセキュアDB構築 連載インデックス |
TechTargetジャパン
- 実録、「Hardening Zero」の舞台裏 (2012/5/25)
コラムの更新頻度を落として何をやっていたかって? 「守る技術」に焦点を当てたこんなイベントを開催しました - 複雑化、巧妙化する脅威への対策は? (2012/5/23)
データ保護や標的型攻撃対策、クラウドセキュリティ……「第9回 情報セキュリティEXPO」の会場で見つけた製品を一挙に紹介 - 仮想化がはらむ新たなリスク (2012/5/17)
仮想化に伴って生じるセキュリティやパフォーマンスへの影響を慎重に考慮し、うまく制御していく方法を紹介します - 新入生も新入社員も勉強会に寄っといで! (2012/5/14)
週末ともなれば至るところでセキュリティ系勉強会やCTFなどのイベントがあり、ツイートも盛り上がりました
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -
