
第3回 アクセス制御の実装は“巧妙”かつ“大胆”に
海外 浩平
日本SELinuxユーザ会
2007/10/12
行レベルのアクセス制御
さて、SE-PostgreSQLの主要機能の1つに行レベルのアクセス制御があったことを思い出してください。
先ほどの例では行レベルアクセス制御に言及していませんでしたが、これには理由があります。それは、SQLクエリーの検査がクエリーの実行前、即ち「エグゼキュータ」より前の処理フェイズで行われているのに対して、どの行がアクセスされるのかはクエリーの実行段階にならないと確定しないという問題があるからです。
この問題を回避するため、SE-PostgreSQLは行レベルのアクセス制御を、SQLクエリーの検査ではなく、書き換えによって実現しています。下記の例を見てください。
【書き換え前】 【書き換え後】 |
WHERE句に条件が追加されており、これによって、検索対象の行が絞り込まれることになります。ここでのポイントは、SE-PostgreSQLがSQLクエリーの検査と併せてSQLクエリーの書き換えも行っているものの、条件句に追加された関数は「エグゼキュータ」の実行中に呼び出されるということです。従って、SQLクエリーの検査時にはどの行(タプル)にアクセスするのか確定できないという問題は解決します。
sepgsql_tuple_perms関数は、各行のセキュリティコンテキストを引数に取り、クライアントがその行にアクセス可能かどうかを判定する関数です。この関数によってアクセス不可能な行がフィルタリングされた結果、クライアントにはあたかもアクセス不可能な行が存在しないかのように見えます。
SQLクエリーが書き換えられている様子は、クエリーの実行プランを確認する EXPLAIN 文を使って確認することができます。
kaigai=# EXPLAIN SELECT * FROM drink WHERE id = 3; QUERY PLAN --------------------------------------------------------------- Seq Scan on drink (cost=0.00..1.09 rows=1 width=17) Filter: (pg_catalog.sepgsql_tuple_perms(tableoid, security_context, 12, drink.*) AND (id = 3)) (2 rows) |
このように、本来は「id = 3」という条件だけのはずなのに、実行プランにはsepgsql_tuple_perms関数の呼び出しが含まれています。
クライアントにはあたかもアクセス不可能な行が存在しないかのように見えるという点で、SE-PostgreSQLは徹底しています。
複数のテーブルを結合(JOIN)する際にも、まず両側のテーブルに sepgsql_tuple_perms関数でフィルタリングを行い、その結果を結合するのと等価であるように条件句の書き換えを行います。
【書き換え前】 【書き換え後】 |
特殊ケース(OUTER JOIN)への対応
行レベルアクセス制御の特殊なケースとして、外部結合(OUTER JOIN)の利用があります。
以下はPostgreSQL 8.2.5文書[和訳]からの引用ですが、左外部結合(LEFT OUTER JOIN)について以下のように述べています。
T1 LEFT OUTER JOIN T2 ON <結合条件> まず、内部結合が行われます。その後、T2のどの行との結合条件も満たさないT1の各行については、T2の列をNULL値として結合した行が追加されます。したがって、連結されたテーブルは無条件にT1の行それぞれに少なくとも1つの行があります。 |
【注3】 右外部結合(RIGHT OUTER JOIN)、完全外部結合(FULL OUTER JOIN)の場合は適宜T1/T2を読み替えてください。 |
いうまでもなく、「無条件にT1の行が少なくとも1個」外部結合の結果に含まれてしまうと、行レベルのアクセス制御は破たんします。そこで、SE-PostgreSQLは次のような大胆なSQLクエリーの書き換えを行います。
【書き換え前】 【書き換え後】 |
書き換え前にはt1テーブルとt2テーブルを左外部結合していたものが、書き換え後は「t1テーブルに対するフィルタリング条件付きサブクエリーの結果」とt2テーブルの左外部結合となっています。
外部結合の対象となるテーブルをサブクエリーへと書き換えることによって、クライアントが権限を持たない行があたかも存在しないかのように扱うことができるのです。
しかし、これには副作用もあります。上の例で、t1テーブルへの参照がサブクエリーに書き換えられたことで、t1テーブルへのアクセスは常にシーケンシャルスキャンを伴うようになってしまい、パフォーマンスの面ではマイナスです。
SE-PostgreSQLを利用することでセキュリティ上のメリットを得ることができますが、一方で、このようなデメリットも存在することには留意しておくべきでしょう。
今回の記事では、SE-PostgreSQLアクセス制御の内側を紹介してみました。少しいじってみる程度であれば、その実装にまで気を配る必要はないかもしれません。しかし、SE-PostgreSQLがどのようにSQLクエリーの検査を行い、どのようにSQLクエリーを書き換えているのかを知っておくことで、適切なデータベース設計やSQLクエリの記述が可能になるでしょう。
次回はいよいよ連載の最終回、SE-PostgreSQLの運用についてご紹介したいと思います。
参考情報:Fedora 8 以降での SE-PostgreSQL 連載第1回で、Fedora 7へのSE-PostgreSQLのインストール方法を紹介しましたが、Fedora 8以降ではインストール手順が非常に簡単になる予定です。 というのも、Fedora 8以降では、SELinuxの標準セキュリティポリシーにSE-PostgreSQL対応のルールが含まれるようになり、SE-PostgreSQL自体もFedoraパッケージの1つとして取り込まれました。 ですので、これまでのようにパッケージを個別にダウンロードしてインストールする必要はなくなり、yumコマンドを実行するだけで、すべての依存関係を解決したうえで SE-PostgreSQL をインストールできるようになりました。
|
![]() |
3/3 |
Index | |
アクセス制御の実装は“巧妙”かつ“大胆”に | |
Page1 PostgreSQLのクエリー処理手順を理解する SE-PostgreSQLによる拡張 |
|
Page2 SE-PostgreSQLによるSQLクエリーの検査 例1:シンプルなSQLに必要な権限を検査する 例2:UPDATE文の実行に必要な権限を検査する |
|
![]() |
Page3 行レベルのアクセス制御 特殊ケース(OUTER JOIN)への対応 参考情報:Fedora 8 以降での SE-PostgreSQL |
Profile |
海外 浩平(かいがい こうへい) 日本SELinuxユーザ会 某社でLinuxカーネルの開発・サポートを行うかたわら、SELinux並列実行性能の改善や、組み込み向けファイルシステムのSELinux対応などを行っている。 現在は本業に加えて、IPA未踏ソフトウェア創造事業の支援を受けて、SE-PostgreSQL開発という二足のわらじを履いている日々。 「アンチ事なかれ主義」がモットー、好きな言葉は「前代未聞」。 |
![]() |
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)対策の観点から考える。
![]() |
|
|
|
![]() |