Audit Trailについての検証 その7

投稿日: 2003年9月17日

Oracleデータベースの監査機能である、Audit Trail に関する性能検証、機能検証をLevel1-4でまとめた人気コンテンツのeBook版。標準監査機能の基本から応用まで全8回で解説。

Level 1)Audit sessionなどによる文監査
Level 2)オブジェクト監査
Level 3)ファイングレイン監査 Basic
Level 4)ファイングレイン監査 Advanced

*eBook版のダウンロードをご希望の方は、画像をクリック

<Audit Trailについての検証 ~その7~>
ペンネーム ベロ

先週に引き続き3階層アーキテクチャのセキュリティについて見ていきましょう。

先週はJDBC THINドライバを使用してコネクションプールを作成し、監査レコー
ドを確認してみた。THINドライバの場合はTERMINAL列がUNKNOWNとなり、APサー
バの特定すらできない状態でした。

また、APサーバから1つのコネクションを使用する場合、大きなセキュリティ
ホールを作ってしまうことになる。

実際に次のようなアプリケーションを考えてみる。

(1) WEBを使った社内システム
(2) 社内の階級ごとにDBユーザを作成
    例)employee
        chief
        manager
(3) 階級にはそれぞくロールが付与されセキュリティを確保する
(4) APからMANAGER.HYOUKAテーブルの参照は許可するが、同テーブルに対して
    更新は許可しない

このような環境の場合みなさんなのアプリケーションはどのように設計するで
しょうか?

1つの方法はAPサーバがDBユーザ/パスワードをフォームにより入力させ認証する。
この場合、エンドユーザはそれぞれDBユーザを記憶しておく必要があり、また
DBユーザが大量に存在する場合、コネクションプールの使用に向かない。

2つ目の方法はすべてのDBユーザの権限をもつスーパーユーザを作成し(APPSRV)
エンドユーザからのDBアクセスは全てこのAPPSRVが引き受ける。この方法は、
コネクションプールには向くが、ORACLEが提供するロールによるセキュリティ
を設定することができず、APPSRVによる故意、不注意によるデータ破壊を防ぐ
ことはできない。また、AUDITに関してもAPPSRVのみが監査対象となり、各DB
ユーザのアクティビティを監査することはできない。
これは、アカウンタビリティという最低限の監査すらできないという大きなセ
キュリティホールと言えるでしょう。

上記1、2の方法に加えOracle9iではプロキシ認証をサポートしています。APサー
バには必要最低限の権限のみをもたせたユーザーproxyで接続させ、アクセスす
るユーザにはプロキシ認証を実装するという方法です。この方式では、SQL処理
を要求する際にユーザーproxyのコネクション・プールを経由して認証を受けた
利用者アカウントの権限でデータベースにアクセスできます。

では、実際にプロキシ認証を使ってみましょう。

その前に環境をちょっと設定。

(1) PROXY, EMPLOYEE, CHIEFユーザ作成, MANAGERユーザ作成
(2) PROXYユーザはCREATE SESSION権限のみ付与、他のユーザはRESOUCE権限も付与
(3) MANAGER.HYOUKAテーブルについてSELECT権限を含むROLE1作成
(4) MANAGER.HYOUKAテーブルについてINSERT権限を含むROLE2作成
(5) ROLE1,ROLE2をEMPLOYEEユーザに付与
(6) EMPLOYEEユーザへのプロキシ認証を許可(ROLE1,ROLE2使用可能)

alter user employee grant connect through proxy with role role1,role2 ;  audit session by proxy on behalf of employee ;  alter user employee grant connect through proxy ;

(b)ではプロキシ経由のEMPLOYEEユーザのアクティビティを監査する。プロキ
シ経由ですべのユーザを監査する場合は以下の通り。

audit session by proxy on behalf of any ;

では、監査がどのように設定されたか確認してみよう。

select * from dba_stmt_audit_opts;
USER_NAME PROXY_NAME AUDIT_OPTION   SUCCESS   FAILURE
--------- ---------- -------------- --------- ---------
EMPLOYEE  PROXY      CREATE SESSION BY ACCESS BY ACCESS <--(c)
          ^^^^^

(c)でPROXYユーザによる接続でEMPLOYEEユーザのアクティビティ(この場合は
LOGIN)の監査を実施する設定になっていることが分かる。

では、実際にプロキシ認証にてEMPLOYEEユーザでログインしSELECT文、および
INSERT文を発行してみよう。

WEBからアクセス・・・

— select from the proxy connection —
1 <–(d)
— insert with the proxy connection —
Exception : ORA-01031: 権限が不足しています。

select os_username
      ,username
      ,terminal
      ,to_char(timestamp,'hh24:mi:ss') timestamp
      ,action_name
      ,to_char(logoff_time,'hh24:mi:ss') logoff_time
      ,returncode
from   dba_audit_session ;
OS_USERNAM USERNAME  TERMINAL  TIMESTAMP   ACTION_NAM LOGOFF_TIME   RETURNCODE
---------- --------- --------- ----------- ---------- ------------- ----------
SYSTEM     EMPLOYEE  KSHINKUB  09:50:41    LOGOFF     09:50:42               0
SYSTEM     EMPLOYEE  KSHINKUB  10:05:27    LOGOFF     10:05:27               0
SYSTEM     EMPLOYEE  KSHINKUB  10:13:33    LOGOFF     10:13:33               0 <--(f)
           ^^^^^^^^  ^^^^^^^^

(f)でセッションを確立したPROXYユーザではなく、きちんとEMPLOYEEユーザの
監査レコードが作成されている。また、前回のJDBC THINドライバではUNKNOWN
となっていたTERMINAL列にAPサーバである「KSHINKUB」が設定されている。
しかしながら(やはり)エンドユーザの監査はできない。

今回のプロキシ認証では、セキュリティの面でいろいろ便利な点がある。
以下ちょっとまとめてみます。

1.ロールを使用してユーザごとのセキュリティが確保できる。
2.APサーバから必要最小限の権限をもつユーザで接続できる。
3.DBユーザに対して正確なアカウンタビリティを確保できる。
4.DBからロールの管理によるセキュリティに加え、APからの設定(接続時に
  使用するロール)により、DB・AP両面からセキュリティ対策が行える。

などでしょうか。

参考)
以下は今回使用したプロキシ認証のサンプルソースです。

/*+----------------------------------------------------------------------------+
 *|                           ProxyConnSample                                  |
 *+----------------------------------------------------------------------------+*/
import java.sql.*;
import javax.sql.*;
import java.util.Properties;
import oracle.jdbc.*;
import oracle.jdbc.pool.*;
import oracle.jdbc.oci.*;
class ProxyConnSample
{
    public static void main (String args [])
         throws SQLException
    {
        DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
        String url = "jdbc:oracle:oci8:@nas";
        OracleOCIConnectionPool cp = new OracleOCIConnectionPool("proxy"
                                                                ,"proxy"
                                                                , url
                                                                , null);
        Properties prop = new Properties();
        String[] roles = {"role1"};
        prop.put(OracleOCIConnectionPool.PROXY_USER_NAME,"employee" );
        prop.put(OracleOCIConnectionPool.PROXY_ROLES, roles);
        // Get the proxy connection
        OracleOCIConnection conn = (OracleOCIConnection) 
            cp.getProxyConnection(OracleOCIConnectionPool.PROXYTYPE_USER_NAME
                                 , prop);

        Statement stmt = conn.createStatement ();
        ResultSet rs = stmt.executeQuery ("select * from manager.hyouka");
        System.out.println ("-- select from the proxy connection --");
        while (rs.next ())
            System.out.println (rs.getString (1));

        rs.close();
        rs = null;

        System.out.println ("-- insert with the proxy connection --");
        try {
            stmt.execute("insert into manager.hyouka values (2)");
        } catch (SQLException e) {
          System.out.println ("Exception : " + e.getMessage());
        } finally {
            if (stmt != null)
                stmt.close();
        }

        conn.close();
        conn = null;

        cp.close();
        cp = null;
    }
}

9月の方が暑苦しい茅ヶ崎より