第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構築 連載インデックス


Security&Trust フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Security & Trust 記事ランキング

本日 月間