9 アプリケーション開発者のセキュリティの管理
アプリケーション開発者のセキュリティ・ポリシーでは、パスワード管理や外部プロシージャおよびアプリケーション権限の保護といった領域を網羅する必要があります。
- アプリケーション・セキュリティ・ポリシーについて
アプリケーション・セキュリティ・ポリシーは、アプリケーション・セキュリティの要件およびデータベース・オブジェクトへのユーザー・アクセスを規制するルールのリストです。 - アプリケーション・ベースのセキュリティの使用に関する考慮事項
アプリケーション・セキュリティの実装では、アプリケーション・ユーザーとデータベース・ユーザーについて、アプリケーション内とデータベース内のどちらでセキュリティを強制するのかを検討する必要があります。 - アプリケーション設計におけるパスワードの保護
Oracleでは、パスワード・サービスの安全な呼出し(スクリプトを使用するなど)のための戦略や、これらの戦略をその他の機密データに適用するための戦略を用意しています。 - 外部プロシージャの保護
外部プロシージャはデータベースとは別に.dll
または.so
ファイルに保存され、資格証明認証で保護できます。 - アプリケーション権限の管理
ほとんどのデータベース・アプリケーションでは、異なるスキーマ・オブジェクトごとに異なる権限が関与します。 - アプリケーション権限の管理にロールを使用する利点
複数のアプリケーション権限を1つのロールにグループ化すると、権限の管理に役立ちます。 - アプリケーションへのアクセスを制御するセキュア・アプリケーション・ロールの作成
セキュア・アプリケーション・ロールは関連するPL/SQLパッケージまたはプロシージャでのみ使用可能にできます。 - 権限とユーザーのデータベース・ロールとの関連付け
ユーザーの権限が、現在のデータベース・ロールに関連した権限のみであることを確認します。 - スキーマを使用したデータベース・オブジェクトの保護
スキーマとは、データベース・オブジェクトを含めることができるセキュリティ・ドメインです。ユーザーおよびロールに付与された権限によって、これらのデータベース・オブジェクトへのアクセスが制御されます。 - アプリケーションでのオブジェクト権限
アプリケーションの設計時には、ユーザーのタイプとユーザーに必要なレベル・アクセスについて検討する必要があります。 - データベース通信のセキュリティを強化するためのパラメータ
プロトコル・エラーによる不正パケットの処理や認証エラーの上限の構成など、パラメータを使用してセキュリティを管理できます。
親トピック: アプリケーション開発のセキュリティ
9.1 アプリケーション・セキュリティ・ポリシーについて
アプリケーション・セキュリティ・ポリシーは、アプリケーション・セキュリティの要件およびデータベース・オブジェクトへのユーザー・アクセスを規制するルールのリストです。
安全なデータベース・アプリケーションを作成する最初のステップは、アプリケーション・セキュリティ・ポリシーの作成です。セキュリティ・ポリシーは、データベース・アプリケーションごとに立案する必要があります。たとえば、各データベース・アプリケーションには、アプリケーションの実行時に異なるレベルのセキュリティを提供する1つ以上のデータベース・ロールが必要です。データベース・ロールは、他のロールに付与するか、または特定のユーザーに直接付与できます。
(SQL*PlusやSQL Developerなどのツールを使用して)SQL文を制限なしで処理できるアプリケーションの場合でも、機密扱いのスキーマ・オブジェクトや重要なスキーマ・オブジェクトへの不当なアクセスを防ぐために、セキュリティ・ポリシーが必要です。特に、使用するアプリケーションでパスワードが安全に処理されることを確認する必要があります。
親トピック: アプリケーション開発者のセキュリティの管理
9.2 アプリケーション・ベースのセキュリティの使用に関する考慮事項
アプリケーション・セキュリティの実装では、アプリケーション・ユーザーとデータベース・ユーザーについて、アプリケーション内とデータベース内のどちらでセキュリティを強制するのかを検討する必要があります。
- アプリケーション・ユーザーはデータベース・ユーザーでもあるか
できるかぎり、アプリケーション・ユーザーがデータベース・ユーザーであるアプリケーションを作成し、データベースに備わるセキュリティ・メカニズムを使用できるようにします。 - アプリケーション内またはデータベース内でのセキュリティ規定
アプリケーションでできるだけ多くのデータベース・セキュリティ・メカニズムが使用されるようにすることをお薦めします。
親トピック: アプリケーション開発者のセキュリティの管理
9.2.1 アプリケーション・ユーザーはデータベース・ユーザーでもあるか
できるかぎり、アプリケーション・ユーザーがデータベース・ユーザーであるアプリケーションを作成し、データベースに備わるセキュリティ・メカニズムを使用できるようにします。
多くの市販のパッケージ・アプリケーションでは、アプリケーション・ユーザーは、データベース・ユーザーではありません。これらのアプリケーションでは、複数のユーザーがユーザー自身をアプリケーションに対して認証し、次に、アプリケーションが単一の高い権限を持つユーザーとしてデータベースに接続します。これを、One Big Application Userモデルと呼びます。
この方法で作成されたアプリケーションは、通常、データベースに本来備わっているセキュリティ機能の多くを使用できません。これは、ユーザーの識別情報がデータベースで認識されないためです。ただし、クライアント識別子を使用して、いくつかのタイプの追跡を実行できます。たとえば、Oracle Call InterfaceのメソッドOCIAttrSet
のOCI_ATTR_CLIENT_IDENTIFIER
属性を使用して、クライアント接続の監査と監視を有効にできます。クライアント識別子を使用すると、個々のWebユーザーの監査証跡データの収集、Webユーザーによるデータ・アクセスを制限するルールの適用、および各Webユーザーが使用しているアプリケーションの監視および追跡を行うことができます。
表9-1は、One Big Application Userモデルが様々なOracle Databaseセキュリティ機能にどのように影響するかを説明しています。
表9-1 One Big Application Userモデルの影響を受ける機能
Oracle Database機能 | One Big Application Userモデルの制限 |
---|---|
監査 |
セキュリティの基本原則の1つは、監査によるアカウンタビリティです。One Big Application Userがデータベース内のすべての操作を実行する場合、データベース監査では、個々のユーザーが実行したアクションに対する責任をそのユーザー自身に持たせることができません。アプリケーションでは、独自の監査メカニズムを実装して、ユーザーのアクションを個別に捕捉する必要があります。 |
Oracle厳密認証 |
データベースに対するクライアントの認証が、個々のユーザーではなくアプリケーションの場合、認証の厳密な形式(たとえば、SSLやトークンなどでのクライアント認証)は使用できません。 |
ロール |
ロールは、データベース・ユーザーに割り当てられます。エンタープライズ・ロールは、データベース内で作成されていない場合でも、エンタープライズ・ユーザーに割り当てられ、データベースに認識されます。アプリケーション・ユーザーがデータベース・ユーザーではない場合、ロールの有用性は低くなります。この場合、アプリケーションでは独自のメカニズムを作成して、様々なアプリケーション・ユーザーがアプリケーション内のデータへアクセスするのに必要とする権限を識別する必要があります。 |
エンタープライズ・ユーザー管理 |
エンタープライズ・ユーザー管理機能は、Oracle Internet DirectoryなどのLDAPベースのディレクトリにユーザー情報を安全に格納して認可を管理することで、OracleデータベースがOracle Identity Managementインフラストラクチャを使用できるようにします。エンタープライズ・ユーザーは、データベース内に作成する必要はありませんが、データベースに認識される必要があります。One Big Application Userモデルでは、Oracle Identity Managementを利用できません。 |
9.2.2 アプリケーション内またはデータベース内でのセキュリティ規定
アプリケーションでできるだけ多くのデータベース・セキュリティ・メカニズムが使用されるようにすることをお薦めします。
ユーザーがデータベース・ユーザーでもあるアプリケーションは、アプリケーションの中にセキュリティを組み込むか、きめ細かい権限、仮想プライベート・データベース(アプリケーション・コンテキストによるファイングレイン・アクセス・コントロール)、ロール、ストアド・プロシージャ、および監査(ファイングレイン監査を含む)などのデータベースに本来備わっているセキュリティ・メカニズムを使用できます。
セキュリティがアプリケーション内ではなくデータベース自体で規定されている場合は、セキュリティを回避することはできません。アプリケーション・ベースのセキュリティの主なデメリットは、ユーザーがアプリケーションを回避してデータにアクセスすると、セキュリティが回避されることです。たとえば、データベースへのSQL*Plusアクセス権を持つユーザーは、人事管理アプリケーションを介さずに問合せを実行できます。したがって、このユーザーは、アプリケーション内のセキュリティ対策のすべてをバイパスします。
One Big Application Userモデルを使用するアプリケーションでは、データベースのセキュリティ・メカニズムを使用せずに、アプリケーション内にセキュリティ規定を作成する必要があります。ユーザーを認識するのは、データベースではなくアプリケーションであるため、アプリケーション自体が各ユーザーに対してセキュリティ対策を規定する必要があります。
このアプローチでは、データにアクセスする各アプリケーションでのセキュリティの再実装が必要になります。組織では複数のアプリケーションに同じセキュリティ・ポリシーを実装する必要があるため、セキュリティが高コストになり、新規アプリケーションごとに高コストな再実装が必要になります。
関連トピック
9.3 アプリケーション設計におけるパスワードの保護
Oracleでは、パスワード・サービスの安全な呼出し(スクリプトを使用するなど)のための戦略や、これらの戦略をその他の機密データに適用するための戦略を用意しています。
- アプリケーションでのパスワードの保護に関する一般的なガイドライン
アプリケーションでのパスワードの保護に関するガイドラインでは、プラットフォーム固有のセキュリティ脅威などの領域を扱います。 - 外部パスワード・ストアを使用したパスワードの保護
データベースに接続するためのパスワード資格証明は、クライアント側のOracleウォレットを使用して格納できます。 - ORAPWDユーティリティを使用したパスワードの保護
SYSDBA
またはSYSOPER
ユーザーはパスワード・ファイルを使用して、ネットワーク経由でアプリケーションに接続できます。 - 例: パスワードを読み取るためのJavaコード
パスワードの読取りに使用できるJavaパッケージを作成できます。
親トピック: アプリケーション開発者のセキュリティの管理
9.3.1 アプリケーションでのパスワードの保護に関する一般的なガイドライン
アプリケーションでのパスワードの保護に関するガイドラインでは、プラットフォーム固有のセキュリティ脅威などの領域を扱います。
- プラットフォーム固有のセキュリティへの脅威
次の潜在的なセキュリティへの脅威は、わかりにくい可能性があるので注意してください。 - パスワード入力を処理するアプリケーションの設計のガイドライン
Oracleには、パスワード入力を扱うアプリケーションの設計に関するガイドラインが用意されています。 - パスワードの形式と動作の構成のガイドライン
Oracle Databaseには、パスワードの形式と動作の構成に関するガイドラインが用意されています。 - SQLスクリプトにおけるパスワードの処理のガイドライン
Oracleには、SQLスクリプトにおけるパスワードの取扱いに関するガイドラインが用意されています。
親トピック: アプリケーション設計におけるパスワードの保護
9.3.1.1 プラットフォーム固有のセキュリティへの脅威
次の潜在的なセキュリティへの脅威は、わかりにくい可能性があるので注意してください。
これらのセキュリティへの脅威は次のとおりです。
-
UNIXおよびLinuxプラットフォームでは、同じホスト・コンピュータ上のすべてのオペレーティング・システム・ユーザーがコマンド・パラメータを表示できます。結果として、コマンドラインに入力したパスワードは他のユーザーに公開される可能性があります。ただし、UNIXおよびLinux以外のプラットフォームがこの脅威を回避できるとは考えないでください。
-
HP Tru64およびIBM AIXなど一部のUNIXプラットフォームでは、すべてのオペレーティング・システム・ユーザーがあらゆるプロセスの環境変数を表示できます。ただし、UNIXおよびLinux以外のプラットフォームがこの脅威を回避できるとは考えないでください。
-
Microsoft Windowsでは、コマンド・リコール機能(上矢印)に、コマンド起動間のユーザー入力が記憶されます。たとえば、SQL*Plusの
CONNECT SYSTEM/
password
表記法を使用し、終了してから上矢印を押してCONNECT
コマンドを繰り返した場合、コマンド・リコール機能により接続文字列が明らかになり、パスワードが表示されます。また、Microsoft Windows以外のプラットフォームがこの脅威を回避できるとは考えないでください。
9.3.1.2 パスワード入力を処理するアプリケーションの設計のガイドライン
Oracleには、パスワード入力を扱うアプリケーションの設計に関するガイドラインが用意されています。
-
パスワードの入力を対話形式で求めるアプリケーションを設計します。コマンドライン・ユーティリティの場合、コマンド・プロンプトでパスワードを公開することをユーザーに強制しないでください。
アプリケーションの設計に使用するプログラミング言語のAPIについて、ユーザーからのパスワードを処理する最適な方法を確認します。この機能を処理するJavaコードの例は、「例: パスワードを読み取るためのJavaコード」を参照してください。
-
コード・インジェクション攻撃からデータベースを保護します。コード・インジェクション攻撃の標的は主に、データベースにSQLを送信するクライアント・アプリケーション・ツール(SQL*Plus、Oracle Call Interface (OCI)、JDBCアプリケーションなど)です。これらのツールを使用して作成されたデータベース・ドライバも含まれます。SQLインジェクション攻撃では、PL/SQLアプリケーションで想定されていない方法でSQL文が動作します。インジェクション攻撃は、データベースに文が送信される前に行われます。たとえば、侵入者は
WHERE
句をTRUE
に設定してパスワード認証を回避できます。SQLインジェクション攻撃の問題に対処するには、バインド変数引数を使用するか妥当性チェックを作成します。バインド変数を使用できない場合は、
DBMS_ASSERT
PL/SQLパッケージを使用して入力値のプロパティを検証することを検討してください。DBMS_ASSERT
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。また、PUBLIC
などのロールに対する権限付与も検討してください。インジェクションはデータベースに文が送信される前に行われる可能性があるため、クライアント・アプリケーションのユーザーがSQLインジェクションをPL/SQLに結び付けることができるとは限らないことに注意してください。
SQLインジェクションの防止の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
-
可能な場合は、認証を遅延するアプリケーションを設計します。たとえば:
-
ログインに証明書を使用します。
-
オペレーティング・システムで提供される機能を使用してユーザーを認証します。たとえば、Microsoft Windows上で動作するアプリケーションはドメイン認証を使用できます。
-
-
パスワードをマスクまたは暗号化します。パスワードを格納する必要がある場合、パスワードをマスクまたは暗号化します。たとえば、ログ・ファイルでパスワードをマスクし、リカバリ・ファイルでパスワードを暗号化できます。
-
各接続を認証します。たとえば、スキーマAがデータベース1に存在する場合、データベース2のスキーマAが同一のユーザーであるとは考えないでください。同様に、ローカル・オペレーティング・システム・ユーザー
psmith
は、必ずしもリモート・ユーザーpsmith
と同じユーザーではありません。 -
ファイルまたはリポジトリにクリアテキスト・パスワードを格納しないでください。パスワードをファイルに格納すると、侵入者がパスワードにアクセスする危険性が高まります。
-
1つのマスター・パスワードを使用します。たとえば:
-
1人のデータベース・ユーザーに、他のデータベース・ユーザーとなるためのプロキシ認証を付与できます。この場合、必要となるデータベース・パスワードは1つのみです。詳細は、「プロキシ・ユーザー・アカウントと、そのアカウントを介して接続するユーザーの認可」を参照してください。
-
マスター・パスワードでオープンできるパスワード・ウォレットを作成できます。ウォレットにはその他のパスワードが含められます。Wallet Managerの詳細は、『Oracle Databaseエンタープライズ・ユーザー・セキュリティ管理者ガイド』を参照してください。
-
9.3.1.3 パスワードの形式と動作の構成のガイドライン
Oracle Databaseには、パスワードの形式と動作の構成に関するガイドラインが用意されています。
-
パスワードの存続期間を制限します。パスワード存続期間を設定して、その期間が過ぎるとパスワードが期限切れになり、変更しないとユーザーがアカウントにログインできなくなるようにすることができます。パスワードの存続期間を制御するために使用できるパラメータは、パスワード・エイジングおよび期限切れの制御についてを参照してください。
-
ユーザーが古いパスワードを再利用する機能を制限します。詳細は、ユーザーによる以前のパスワードの再利用の制御を参照してください。
-
強力かつ安全なパスワードを作成するようユーザーに要求します。強力なパスワードの作成に関するガイドラインは、パスワードの保護に関するガイドラインを参照してください。パスワードの複雑度検証についてでは、パスワードの要件をカスタマイズする方法について説明しています。
-
パスワードで大/小文字を区別できるようにします。詳細は、パスワードでの大/小文字の区別の管理を参照してください。
関連トピック
9.3.1.4 SQLスクリプトにおけるパスワードの処理のガイドライン
Oracleには、SQLスクリプトにおけるパスワードの取扱いに関するガイドラインが用意されています。
-
プログラムまたはスクリプトのコマンドラインにパスワードを指定してSQL*Plusを起動しないでください。パスワードが必須であるにもかかわらず省略した場合、SQL*Plusではパスワードの入力を求めるプロンプトが表示され、パスワードが表示されないようにエコー機能が自動的に無効となります。
次の各例は、パスワードがコマンドライン上で公開されないため安全です。また、Oracle Databaseではこれらのパスワードがネットワークを介して自動的に暗号化されます。
$ sqlplus system Enter password: password SQL> CONNECT SYSTEM Enter password: password
次の例では、パスワードが他のオペレーティング・システム・ユーザーに公開されます。
sqlplus system/password
次の例は、2つのセキュリティ上のリスクをもたらします。1つ目の例では、覗き込んでいる可能性のある他のユーザーにパスワードを公開してしまいます。2つ目の例では、Microsoft Windowsなどの一部のプラットフォームにおいて、パスワードがコマンドラインのリコール攻撃を受けやすくなります。
$ sqlplus /nolog SQL> CONNECT SYSTEM/password
-
たとえばパスワードまたは秘密キーを必要とするSQLスクリプトの場合、アカウントを作成したりあるアカウントでログインするには、置換変数&1、&2などの位置パラメータを使用しないでください。かわりに、ユーザーに値の入力を求めるプロンプトを表示するスクリプトを設計します。また、スクリプトから、またはスプール・モードを使用している場合に出力を表示するエコー機能を無効にする必要があります。エコー機能を無効にするには、次の設定を使用します。
SET ECHO OFF
スクリプトにより値の目的を明白にする必要があります。たとえば、値によりアカウントまたは証明書などの新しい値が設定されるかどうか、または既存のアカウントへのログインなど、値が認証されるかどうかを明白にする必要があります。
次の例は、セキュリティ上のリスクをもたらす方法でユーザーがスクリプトを起動することが回避されるため安全です。パスワードはエコーされず、スプール・ファイルに記録されません。
SET VERIFY OFF ACCEPT user CHAR PROMPT ‘Enter user to connect to: ‘ ACCEPT password CHAR PROMPT ‘Enter the password for that user: ' HIDE CONNECT &user/&password
この例では、次のようになります。
-
SET VERIFY OFF
は、パスワードの表示を防止します。(SET VERIFY
は、置換の前後にスクリプトの各行をリストします。)SET VERIFY OFF
コマンドをHIDE
コマンドと結合する方法は、パスワードおよびその他の機密入力データを非表示にする便利なテクニックです。 -
ACCEPT password CHAR PROMPT
は、ACCEPT password
プロンプトにHIDE
オプションを含めます。これによって入力パスワードのエコーが回避されます。
次の例では位置パラメータを使用しており、ユーザーがコマンドライン上でパスワードを渡すことでスクリプトを起動できるため、セキュリティ上のリスクをもたらします。ユーザーがパスワードを入力せず、入力を求めるプロンプトが表示される場合、ユーザーが入力した内容がすべて画面およびスプール・ファイル(スプールが有効な場合)にエコーされるため危険です。
CONNECT &1/&2
-
-
バッチ・スクリプトのログイン時間を制御します。パスワードを必要とするバッチ・スクリプトでは、実行されることになっている時間内のみにバッチ・スクリプトがログインできるようにアカウントを構成します。たとえば、毎日午後8時から1時間実行するバッチ・スクリプトを想定します。この時間のみスクリプトがログインできるようにアカウントを設定します。侵入者がアクセスしようとした場合、安全性の低いアカウントが利用される可能性は低くなります。
-
パスワードの入力を求めるDML文またはDDL SQL文を使用する場合は注意してください。この場合、機密情報がネットワークを介してクリアテキストで渡されます。Oracle厳密認証を使用して、この問題に対処できます。
次のパスワード変更例は、パスワードが公開されないため安全です。
password psmith Changing password for psmith New password: password Retype new password: password
この例は、パスワードがコマンドラインおよびネットワーク上の両方に公開されるため、セキュリティ上のリスクをもたらします。
ALTER USER psmith IDENTIFIED BY password
9.3.2 外部パスワード・ストアを使用したパスワードの保護
データベースに接続するためのパスワード資格証明は、クライアント側のOracleウォレットを使用して格納できます。
Oracleウォレットは、ユーザーのログインに必要な認証および署名用証明書を格納する安全性の高いソフトウェア・コンテナです。
関連項目:
-
安全性の高い外部パスワード・ストアの詳細は、パスワード資格証明用の安全性の高い外部パスワード・ストアの管理を参照してください
-
Oracle Wallet Managerを使用したOracleウォレットの構成の詳細は、『Oracle Databaseエンタープライズ・ユーザー・セキュリティ管理者ガイド』を参照してください。
親トピック: アプリケーション設計におけるパスワードの保護
9.3.3 ORAPWDユーティリティを使用したパスワードの保護
SYSDBA
またはSYSOPER
ユーザーはパスワード・ファイルを使用して、ネットワーク経由でアプリケーションに接続できます。
-
パスワード・ファイルを作成するには、
ORAPWD
ユーティリティを使用します。
関連項目:
パスワード・ファイルの作成および管理方法の詳細は、『Oracle Database管理者ガイド』を参照してください。
親トピック: アプリケーション設計におけるパスワードの保護
9.3.4 例: パスワードを読み取るためのJavaコード
パスワードの読取りに使用できるJavaパッケージを作成できます。
例9-1に、パスワードの読取りに使用できるJavaパッケージの作成方法を示します。
例9-1 パスワードを読み取るためのJavaコード
// Change the following line to a name for your version of this package package passwords.sysman.emSDK.util.signing; import java.io.IOException; import java.io.PrintStream; import java.io.PushbackInputStream; import java.util.Arrays; /** * The static readPassword method in this class issues a password prompt * on the console output and returns the char array password * entered by the user on the console input. */ public final class ReadPassword { //---------------------------------- /** * Test driver for readPassword method. * @param args the command line args */ public static void main(String[] args) { char[] pass = ReadPassword.readPassword("Enter password: "); System.out.println("The password just entered is \"" + new String(pass) + "\""); System.out.println("The password length is " + pass.length); } * Issues a password prompt on the console output and returns * the char array password entered by the user on the console input. * The password is not displayed on the console (chars are not echoed). * As soon as the returned char array is not needed, * it should be erased for security reasons (Arrays.fill(charArr, ' ')); * A password should never be stored as a java String. * * Note that Java 6 has a Console class with a readPassword method, * but there is no equivalent in Java 5 or Java 1.4. * The readPassword method here is based on Sun's suggestions at * http://java.sun.com/developer/technicalArticles/Security/pwordmask. * * @param prompt the password prompt to issue * @return new char array containing the password * @throws RuntimeException if some error occurs */ public static final char[] readPassword(String prompt) throws RuntimeException { try { StreamMasker masker = new StreamMasker(System.out, prompt); Thread threadMasking = new Thread(masker); int firstByte = -1; PushbackInputStream inStream = null; try { threadMasking.start(); inStream = new PushbackInputStream(System.in); firstByte = inStream.read(); } finally { masker.stopMasking(); } try { threadMasking.join(); } catch (InterruptedException e) { throw new RuntimeException("Interrupt occurred when reading password"); } if (firstByte == -1) { throw new RuntimeException("Console input ended unexpectedly"); } if (System.out.checkError()) { throw new RuntimeException("Console password prompt output error"); } inStream.unread(firstByte); return readLineSecure(inStream); } catch (IOException e) { throw new RuntimeException("I/O error occurred when reading password"); } } //---------------------------------- /** * Reads one line from an input stream into a char array in a secure way * suitable for reading a password. * The char array will never contain a '\n' or '\r'. * * @param inStream the pushback input stream * @return line as a char array, not including end-of-line-chars; * never null, but may be zero length array * @throws RuntimeException if some error occurs */ private static final char[] readLineSecure(PushbackInputStream inStream) throws RuntimeException { if (inStream == null) { throw new RuntimeException("readLineSecure inStream is null"); } try { char[] buffer = null; try { buffer = new char[128]; int offset = 0; // EOL is '\n' (unix), '\r\n' (windows), '\r' (mac) loop: while (true) { int c = inStream.read(); switch (c) { case -1: case '\n': break loop; case '\r': int c2 = inStream.read(); if ((c2 != '\n') && (c2 != -1)) inStream.unread(c2); break loop; default: buffer = checkBuffer(buffer, offset); buffer[offset++] = (char) c; break; } } char[] result = new char[offset]; System.arraycopy(buffer, 0, result, 0, offset); return result; } finally { if (buffer != null) Arrays.fill(buffer, ' '); } } catch (IOException e) { throw new RuntimeException("I/O error occurred when reading password"); } } //---------------------------------- /** * This is a helper method for readLineSecure. * * @param buffer the current char buffer * @param offset the current position in the buffer * @return the current buffer if it is not yet full; * otherwise return a larger buffer initialized with a copy * of the current buffer and then erase the current buffer * @throws RuntimeException if some error occurs */ private static final char[] checkBuffer(char[] buffer, int offset) throws RuntimeException { if (buffer == null) throw new RuntimeException("checkBuffer buffer is null"); if (offset < 0) throw new RuntimeException("checkBuffer offset is negative"); if (offset < buffer.length) return buffer; else { try { char[] bufferNew = new char[offset + 128]; System.arraycopy(buffer, 0, bufferNew, 0, buffer.length); return bufferNew; } finally { Arrays.fill(buffer, ' '); } } } //---------------------------------- /** * This private class prints a one line prompt * and erases reply chars echoed to the console. */ private static final class StreamMasker extends Thread { private static final String BLANKS = StreamMasker.repeatChars(' ', 10); private String m_promptOverwrite; private String m_setCursorToStart; private PrintStream m_out; private volatile boolean m_doMasking; //---------------------------------- /** * Constructor. * @throws RuntimeException if some error occurs */ public StreamMasker(PrintStream outPrint, String prompt) throws RuntimeException { if (outPrint == null) throw new RuntimeException("StreamMasker outPrint is null"); if (prompt == null) throw new RuntimeException("StreamMasker prompt is null"); if (prompt.indexOf('\r') != -1) throw new RuntimeException("StreamMasker prompt contains a CR"); if (prompt.indexOf('\n') != -1) throw new RuntimeException("StreamMasker prompt contains a NL"); m_out = outPrint; m_setCursorToStart = StreamMasker.repeatChars('\010', prompt.length() + BLANKS.length()); m_promptOverwrite = m_setCursorToStart + prompt + BLANKS + m_setCursorToStart + prompt; } //---------------------------------- /** * Begin masking until asked to stop. * @throws RuntimeException if some error occurs */ public void run() throws RuntimeException { int priorityOriginal = Thread.currentThread().getPriority(); Thread.currentThread().setPriority(Thread.MAX_PRIORITY); try { m_doMasking = true; while (m_doMasking) { m_out.print(m_promptOverwrite); if (m_out.checkError()) throw new RuntimeException("Console output error writing prompt"); try { Thread.currentThread().sleep(1); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); return; } } m_out.print(m_setCursorToStart); } finally { Thread.currentThread().setPriority(priorityOriginal); } } //---------------------------------- /** * Instructs the thread to stop masking. */ public void stopMasking() { m_doMasking = false; } //---------------------------------- /** * Returns a repeated char string. * * @param c the char to repeat * @param length the number of times to repeat the char * @throws RuntimeException if some error occurs */ private static String repeatChars(char c, int length) throws RuntimeException { if (length < 0) throw new RuntimeException("repeatChars length is negative"); StringBuffer sb = new StringBuffer(length); for (int i = 0; i < length; i++) sb.append(c); return sb.toString(); } } }
親トピック: アプリケーション設計におけるパスワードの保護
9.4 外部プロシージャの保護
外部プロシージャはデータベースとは別に.dll
または.so
ファイルに保存され、資格証明認証で保護できます。
- 外部プロシージャの保護について
安全上の理由のため、Oracle外部プロシージャは、データベースと物理的に異なるプロセスで実行されます。 - 資格証明の認証に対するextprocの構成に関する一般プロセス
セキュリティを強化するために、extproc
プロセスを構成して、資格証明を介して認証できます。 - extprocプロセス認証および偽装の予期される動作
extprocプロセスには、認証および偽装に対する一連の動作が含まれています。 - 外部プロシージャの認証の構成
extproc
プロセスの資格証明を構成するには、DBMS_CREDENTIAL
PL/SQLパッケージを使用します。 - レガシー・アプリケーションの外部プロシージャ
セキュリティを最大にするために、ENFORCE_CREDENTIAL
環境変数をTRUE
に設定します。
親トピック: アプリケーション開発者のセキュリティの管理
9.4.1 外部プロシージャの保護について
安全上の理由のため、Oracle外部プロシージャは、データベースと物理的に異なるプロセスで実行されます。
ほとんどの場合、このプロセスを構成して、Oracleソフトウェア・アカウント以外のユーザーとして実行します。アプリケーションがこの外部プロシージャを呼び出す場合(.dll
または.so
ファイルのライブラリにアクセスする必要がある場合など)、Oracle Databaseがextproc
と呼ばれるオペレーティング・システム・プロセスを作成します。デフォルトでは、extproc
プロセスは、サーバー・プロセスで直接通信します。つまり、資格証明を使用しない場合、Oracle Databaseは、デフォルトのOracle Databaseサーバー構成でextproc
プロセスを作成し、oracle
ソフトウェア・アカウントとしてextproc
を実行します。また、Oracle Databaseリスナーを介して通信できます。
関連項目:
親トピック: 外部プロシージャの保護
9.4.2 資格証明の認証に対するextprocの構成に関する一般プロセス
セキュリティを強化するために、extproc
プロセスを構成して、資格証明を介して認証できます。
一般プロセスは次のとおりです。
-
資格証明を作成します。
資格証明は、暗号化されたコンテナにあります。パブリック・シノニムとプライベート・シノニムの両方でこの資格証明を参照できます。「外部プロシージャの認証の構成」では、この資格証明を作成し、データベースを構成して使用する方法について説明します。
-
専用サーバーまたは共有サーバー・プロセスで実行しているデータベースへの最初の接続を行います。
-
アプリケーションは、外部プロシージャへのコールを行います。
これが最初のコールの場合、Oracle Databaseは
extproc
プロセスを作成します。extproc
の資格証明を使用する場合、Oracleリスナーを使用してextproc
プロセスを起動できません。 -
extproc
プロセスは、偽装(つまり、指定された資格証明のかわりに実行)して、必要な.dll
、.so
、.sl
または.a
ファイルをロードし、SQLおよびC間のデータを送信します。
親トピック: 外部プロシージャの保護
9.4.3 extprocプロセス認証および偽装の予期される動作
extprocプロセスには、認証および偽装に対する一連の動作が含まれています。
表9-2では、可能性のある認証および偽装シナリオに基づくextproc
プロセスの予期される動作について説明します。
表9-2 extprocプロセス認証および偽装設定の予期される動作
ENFORCE_CREDENTIAL環境変数設定 | 資格証明を使用したPL/SQLライブラリか | GLOBAL_EXTPROC_CREDENTIAL資格証明の有無(1) | 予期される動作 |
---|---|---|---|
|
いいえ |
いいえ |
OracleリスナーまたはOracleサーバー・プロセスの所有者のオペレーティング・システム権限で認証される12cより前のリリースの認証を使用します。 |
|
いいえ |
はい |
Oracleインスタンス全体の指定された |
|
はい |
いいえ |
PL/SQLライブラリで定義された資格証明を使用して認証および偽装します |
|
はい |
はい |
認証および偽装します(脚注3) |
|
いいえ |
いいえ |
|
|
いいえ |
はい |
Oracleシステム全体の指定された |
|
はい |
いいえ |
PL/SQLライブラリで定義された資格証明を使用して認証および偽装します |
|
はい |
はい |
認証および偽装します(脚注2) |
脚注1 資格証明が明示的に指定されず、ENFORCE_CREDENTIAL環境変数がTRUEに設定されている場合、GLOBAL_EXTPROC_CREDENTIALは、デフォルトの資格証明の予約された資格証明名です。そのため、ENFORCE_CREDENTIALがTRUEに設定されている場合、この名前で資格証明を作成することをお薦めします。
脚注2
GLOBAL_EXTPROC_CREDENTIAL
資格証明のみを使用している場合、このグローバル資格証明のEXECUTE
権限が暗黙的にすべてのユーザーに自動的に付与されます。
脚注3
PL/SQLライブラリおよびGLOBAL_EXTPROC_CREDENTIAL
設定の両方で資格証明が定義された場合、PL/SQLライブラリの資格証明が優先されます。
親トピック: 外部プロシージャの保護
9.4.4 外部プロシージャの認証の構成
extproc
プロセスの資格証明を構成するには、DBMS_CREDENTIAL
PL/SQLパッケージを使用します。
関連項目:
-
DBMS_CREDENTIAL
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
extproc
エージェントの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。 -
extproc.ora
ファイルの詳細は、『Oracle Database Net Services管理者ガイド』を参照してください。
親トピック: 外部プロシージャの保護
9.4.5 レガシー・アプリケーションの外部プロシージャ
セキュリティを最大にするために、ENFORCE_CREDENTIAL
環境変数をTRUE
に設定します。
ただし、下位互換性に対応する必要がある場合、ENFORCE_CREDENTIAL
をFALSE
に設定します。FALSE
によって、extproc
プロセスは、指定された資格証明のかわりにユーザー定義コールアウト関数を認証、偽装および実行できます。
-
資格証明がPL/SQLライブラリで定義されます。
-
資格証明は定義されていませんが、
GLOBAL_EXTPROC_CREDENTIAL
資格証明が存在します。
これらの資格証明定義が設定されていない場合、ENFORCE_CREDENTIAL
パラメータをFALSE
に設定すると、OracleリスナーまたはOracleサーバー・プロセスの所有者のオペレーティング・システム権限で認証されるextproc
プロセスが設定されます。
extproc
プロセス上で実行されるレガシー・アプリケーションでは、レガシー・アプリケーション・コードを変更して、すべての別名ライブラリと資格証明を関連付けることをお薦めします。これを実行できない場合、Oracle DatabaseはGLOBAL_EXTPROC_CREDENTIAL
資格証明を使用して、認証の処理方法を決定します。GLOBAL_EXTPROC_CREDENTIAL
資格証明が定義されていない場合、extproc
プロセスは、OracleリスナーまたはOracleサーバー・プロセスの所有者のオペレーティング・システム権限で認証されます。
親トピック: 外部プロシージャの保護
9.5 アプリケーション権限の管理
ほとんどのデータベース・アプリケーションでは、異なるスキーマ・オブジェクトごとに異なる権限が関与します。
各アプリケーションに必要な権限の追跡は、複雑な場合があります。また、アプリケーションを実行するユーザーの認可には、多くのGRANT
操作が関与する場合があります。
-
アプリケーションの権限管理を簡素化するために、アプリケーションごとに作成した1つのロールに、1人のユーザーがそのアプリケーションを実行するために必要なすべての権限を付与します。
実際には、1つのアプリケーションに複数のロールがある可能性があり、各ロールには、アプリケーションの実行中に使用できる機能の多少を決める権限の特定サブセットが付与されます。
たとえば、すべての管理アシスタントが休暇アプリケーションを使用して、部門のメンバーが取得した休暇を記録するとします。このアプリケーションを効率的に管理するには、次の操作手順が必要です。
VACATION
ロールを作成します。- 休暇アプリケーションに必要なすべての権限を
VACATION
ロールに付与します。 VACATION
ロールをすべての管理アシスタントに付与します。より効率的な方法は、管理アシスタントが持つ権限を定義したロールを作成し、VACATION
ロールをそのロールに付与します。
関連項目:
-
ロールの作成、使用可能化と使用禁止化、および権限の付与と取消しの詳細は、「権限とロール認可の構成」を参照してください。
-
ROLE_TAB_PRIVS
、ROLE_SYS_PRIVS
およびDBA_ROLE_PRIVS
データ・ディクショナリ・ビューのセキュリティ使用の詳細は、ユーザー権限およびロールのデータ・ディクショナリ・ビューを参照してください
親トピック: アプリケーション開発者のセキュリティの管理
9.6 アプリケーション権限の管理にロールを使用する利点
複数のアプリケーション権限を1つのロールにグループ化すると、権限の管理に役立ちます。
次の管理オプションを考えてみます。
-
アプリケーションを実行するユーザーに、多数の個別の権限ではなく、ロールを付与できます。したがって、従業員が業務を変更するときは、多くの権限ではなく、1つのロールのみを付与または取り消す必要があります。
-
アプリケーションに対応付けられている権限の変更は、そのアプリケーションのすべてのユーザーが保持する権限ではなく、ロールに付与されている権限のみを修正することで実行できます。
-
特定のアプリケーションの実行に必要な権限は、
ROLE_TAB_PRIVS
とROLE_SYS_PRIVS
の各データ・ディクショナリ・ビューを問い合せることで判断できます。 -
どのユーザーに、どのアプリケーションの権限があるかは、
DBA_ROLE_PRIVS
データ・ディクショナリ・ビューを問い合せることで判断できます。
親トピック: アプリケーション開発者のセキュリティの管理
9.7 アプリケーションへのアクセスを制御するセキュア・アプリケーション・ロールの作成
セキュア・アプリケーション・ロールは関連するPL/SQLパッケージまたはプロシージャでのみ使用可能にできます。
- ステップ1: セキュア・アプリケーション・ロールの作成
IDENTIFIED USING
句を持つCREATE
ROLE
文で、セキュア・アプリケーション・ロールを作成します。 - ステップ2: アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージの作成
アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージを作成できます。
親トピック: アプリケーション開発者のセキュリティの管理
9.7.1 ステップ1: セキュア・アプリケーション・ロールの作成
IDENTIFIED USING
句を持つCREATE
ROLE
文で、セキュア・アプリケーション・ロールを作成します。
この文を実行するには、CREATE ROLE
システム権限が必要です。
たとえば、sec_mgr.hr_admin
パッケージに対応付けられるhr_admin
というセキュア・アプリケーション・ロールを作成するには、次の手順を実行します。
9.7.2 ステップ2: アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージの作成
アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージを作成できます。
- アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージの作成について
セキュア・アプリケーション・ロールを有効または無効にするには、PL/SQLパッケージ内にロールのセキュリティ・ポリシーを作成する必要があります。 - アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージまたはプロシージャの作成
作成するPL/SQLパッケージまたはプロシージャでは、アクセス・ポリシーを定義するために実行者権限を使用する必要があります。 - セキュア・アプリケーション・ロールのテスト
セキュア・アプリケーション・ロールを付与されたユーザーとして、そのロールで付与される権限を要するアクションを実行します。
9.7.2.1 アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージの作成について
セキュア・アプリケーション・ロールを有効または無効にするには、PL/SQLパッケージ内にロールのセキュリティ・ポリシーを作成する必要があります。
個別のプロシージャを作成してこれを実行することもできますが、パッケージを使用すると、一連のプロシージャをグループ化できます。これにより、一緒に使用するポリシーのグループを作成して、アプリケーションを保護するための強固なセキュリティ戦略を提示できます。セキュリティ・ポリシーに失敗したユーザー(潜在的な侵入者)については、監査チェックをパッケージに追加して、その失敗を記録できます。通常、このパッケージは、セキュリティ管理者のスキーマに作成します。
このパッケージまたはプロシージャは、次の内容を実行する必要があります。
-
実行者権限を使用してロールを有効にする必要があります。実行者権限を使用してパッケージを作成するには、
AUTHID
プロパティをCURRENT_USER
に設定する必要があります。定義者権限を使用してパッケージを作成することはできません。実行者権限と定義者権限の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
-
ユーザーを検証するためのセキュリティ・チェックを1つ以上組み込む必要があります。ユーザーを検証する方法の1つは、
SYS_CONTEXT
SQLファンクションを使用することです。SYS_CONTEXT
の詳細は、Oracle Database SQL言語リファレンスを参照してください。ユーザーに関するセッション情報を検索するために、アプリケーション・コンテキストでSYS_CONTEXT
を使用できます。詳細は、「アプリケーション・コンテキストを使用したユーザー情報の取得」を参照してください。 -
ユーザーがセキュリティ・チェックを通過するときにSET ROLE SQL文またはDBMS_SESSION.SET_ROLEプロシージャを発行する必要があります。パッケージは実行者権限を使用して作成するため、
SET ROLE
SQL文またはDBMS_SESSION.SET_ROLE
プロシージャを発行することによりロールを設定する必要があります。(ただし、このタイプのロール有効化でSET ROLE ALL
文を使用することはできません。)PL/SQL埋込みSQL構文はSET ROLE
文をサポートしませんが、動的SQL(たとえばEXECUTE IMMEDIATE
により)を使用することによりSET ROLE
を起動できます。EXECUTE IMMEDIATE
の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
このパッケージまたはプロシージャの作成方法が原因で、セキュア・アプリケーション・ロールを使用可能または使用禁止にする際にログイン・トリガーを使用できません。かわりに、ユーザーがセキュリティ・アプリケーション・ロールで付与された権限を使用する前のユーザー・ログイン時に、アプリケーションからパッケージを直接起動します。
9.7.2.2 アプリケーションに対するアクセス・ポリシーを定義するPL/SQLパッケージまたはプロシージャの作成
作成するPL/SQLパッケージまたはプロシージャでは、アクセス・ポリシーを定義するために実行者権限を使用する必要があります。
たとえば、hr_admin
ロールを使用する全員を、オンサイト(特定の端末を使用)で午前8時から午後5時まで勤務する従業員に限定するとします。システム管理者またはセキュリティ管理者として、アプリケーションに対してアクセス・ポリシーを定義するプロシージャを作成できます。
9.7.2.3 セキュア・アプリケーション・ロールのテスト
セキュア・アプリケーション・ロールを付与されたユーザーとして、そのロールで付与される権限を要するアクションを実行します。
セキュア・アプリケーション・ロールを付与されたユーザーとしてログインすると、そのロールが有効になります。
-
そのユーザーとしてデータベース・セッションにログインします。
たとえば:
CONNECT PSMITH@hrpdb Enter password: password
-
セキュア・アプリケーション・ロールで付与される権限を要求するアクションを実行します。
たとえば、そのロールが
sec_admin.hr_admin_role_check
プロシージャに対してEXECUTE
権限を付与するとします。EXECUTE sec_admin.hr_admin_role_check;
9.8 権限とユーザーのデータベース・ロールとの関連付け
ユーザーの権限が、現在のデータベース・ロールに関連した権限のみであることを確認します。
- ユーザーの権限が現在のデータベース・ロールのみである理由
1人のユーザーが、多数のアプリケーションおよび多数の対応付けられたロールを使用できます。 - ロールを自動的に使用可能または使用禁止にするSET ROLE文の使用
各アプリケーションの開始時にSET
ROLE
文を使用して、各アプリケーションに対応付けられているロールを自動的に使用可能にし、他のすべてのロールを使用禁止にします。
親トピック: アプリケーション開発者のセキュリティの管理
9.8.1 ユーザーの権限が現在のデータベース・ロールのみである理由
1人のユーザーが、多数のアプリケーションおよび多数の対応付けられたロールを使用できます。
ただし、このユーザーの権限は、現在のデータベース・ロールに関連した権限のみであることを確認する必要があります。
次の使用例を考えてみます。
-
(「受注」というアプリケーションの)
ORDER
ロールには、INVENTORY
表に対するUPDATE
権限が含まれています。 -
(「在庫」というアプリケーションの)
INVENTORY
ロールには、INVENTORY
表に対するSELECT
権限が含まれています。 -
何人かの受注入力担当には、
ORDER
ロールとINVENTORY
ロールの両方が付与されています。
このシナリオでは、両方のロールを付与された受注入力担当がINVENTORY
アプリケーションの実行時にORDER
ロールの権限を使用してINVENTORY
表を更新できます。問題は、INVENTORY
表の更新は、INVENTORY
アプリケーションにとって承認された操作ではないということです。ORDER
アプリケーションにとって承認された操作です。この問題を防ぐには、SET
ROLE
文を次のセクションの説明のとおりに使用します。
親トピック: 権限とユーザーのデータベース・ロールとの関連付け
9.8.2 ロールを自動的に使用可能または使用禁止にするSET ROLE文の使用
各アプリケーションの開始時にSET
ROLE
文を使用して、各アプリケーションに対応付けられているロールを自動的に使用可能にし、他のすべてのロールを使用禁止にします。
この方法によって、各アプリケーションでは、必要な場合にのみ、ユーザーの特定の権限を動的に使用可能にします。SET
ROLE
文は、権限の管理を簡素化します。ユーザーがどのような情報にアクセスできるかと、その情報にいつアクセスできるかを制御します。また、このSET
ROLE
文によって、ユーザーは、明確に定義された権限ドメイン内で操作を続行できます。あるユーザーがロールからのみ権限を取得している場合、そのユーザーはこれらの権限を組み合せて不正な操作を実行することはできません。
9.9 スキーマを使用したデータベース・オブジェクトの保護
スキーマとは、データベース・オブジェクトを含めることができるセキュリティ・ドメインです。ユーザーおよびロールに付与された権限によって、これらのデータベース・オブジェクトへのアクセスが制御されます。
- 一意スキーマでのデータベース・オブジェクトの保護
ほとんどのスキーマはユーザー名と考えることができます。つまり、ユーザーがデータベースに接続してそのデータベース・オブジェクトへのアクセスを可能にするアカウントです。 - 共有スキーマでのデータベース・オブジェクトの保護
多くのアプリケーションでは、ユーザーがアクセスする必要があるのはアプリケーション・スキーマのみであるため、データベースで自分自身のアカウントつまりスキーマを必要としません。
親トピック: アプリケーション開発者のセキュリティの管理
9.9.1 一意スキーマでのデータベース・オブジェクトの保護
ほとんどのスキーマはユーザー名と考えることができます。つまり、ユーザーがデータベースに接続してそのデータベース・オブジェクトへのアクセスを可能にするアカウントです。
ただし、一意スキーマではデータベースへの接続は許可されませんが、関連する一連のオブジェクトを格納するために使用されます。この種のスキーマは通常ユーザーとして作成されますが、CREATE
SESSION
システム権限は(明示的にもロールを介しても)付与されません。
-
オブジェクトを保護するには、
CREATE
SCHEMA
を使用して、1つのトランザクション内に複数の表とビューを作成する場合は、一意スキーマにCREATE
SESSION
およびRESOURCE
権限を一時的に付与します。
たとえば、所定のスキーマが特定のアプリケーションのスキーマ・オブジェクトを所有する場合があります。アプリケーション・ユーザーに権限がある場合、そのユーザーは、一般的なデータベース・ユーザー名を使用してデータベースに接続し、アプリケーションとそれに対応するオブジェクトを使用できます。ただし、ユーザーはアプリケーションに設定されたスキーマを使用して、データベースに接続することはできません。この構成は、対応付けられたオブジェクトへのスキーマを介したアクセスを防ぎ、スキーマ・オブジェクトの保護を強化します。この場合、アプリケーションではALTER SESSION SET CURRENT_SCHEMA
文を発行して、ユーザーを適切なアプリケーション・スキーマに接続できます。
親トピック: スキーマを使用したデータベース・オブジェクトの保護
9.9.2 共有スキーマでのデータベース・オブジェクトの保護
多くのアプリケーションでは、ユーザーがアクセスする必要があるのはアプリケーション・スキーマのみであるため、データベースで自分自身のアカウントつまりスキーマを必要としません。
たとえば、ユーザーJohn、FiruzehおよびJaneはすべて給与アプリケーションのユーザーで、finance
データベースのpayroll
スキーマにアクセスする必要があるとします。この場合、データベースに自分自身のオブジェクトを作成する必要があるユーザーはいません。これらのユーザーに必要なのは、payroll
オブジェクトへのアクセスのみです。この問題に対処するために、Oracle Databaseではエンタープライズ・ユーザー(スキーマに依存しないユーザー)が提供されています。
エンタープライズ・ユーザー、つまりディレクトリ・サービスで管理されるユーザーは、共有データベース・スキーマを使用するため、データベース・ユーザーとして作成する必要はありません。管理コストを削減するために、管理者はディレクトリに1つのエンタープライズ・ユーザーを1回作成し、他の多数のユーザーもアクセスできる共有スキーマで、そのユーザーを指し示すことができます。
関連項目:
エンタープライズ・ユーザーの管理の詳細は、『Oracle Databaseエンタープライズ・ユーザー・セキュリティ管理者ガイド』を参照してください。
親トピック: スキーマを使用したデータベース・オブジェクトの保護
9.10 アプリケーションでのオブジェクト権限
アプリケーションの設計時には、ユーザーのタイプとユーザーに必要なレベル・アクセスについて検討する必要があります。
- アプリケーション開発者に必要なオブジェクト権限に関する知識
オブジェクト権限によって、エンド・ユーザーは、表、ビュー、順序、プロシージャ、ファンクション、パッケージなどのオブジェクトに対してアクションを実行できます。 - オブジェクト権限によって許可されるSQL文
アプリケーションの実装時およびテスト時には、必要な各ロールを作成する必要があります。
親トピック: アプリケーション開発者のセキュリティの管理
9.10.1 アプリケーション開発者に必要なオブジェクト権限に関する知識
オブジェクト権限によって、エンド・ユーザーは、表、ビュー、順序、プロシージャ、ファンクション、パッケージなどのオブジェクトに対してアクションを実行できます。
表9-3に、オブジェクトの各タイプで使用できるオブジェクト権限の概要を示します。
表9-3 権限とスキーマ・オブジェクトとの関連
オブジェクト権限 | 表への適用 | ビューへの適用 | 順序への適用 | プロシージャへの適用(4) |
---|---|---|---|---|
|
はい |
いいえ |
はい |
いいえ |
|
はい |
はい |
いいえ |
いいえ |
|
いいえ |
いいえ |
いいえ |
はい |
|
はい脚注 5 |
いいえ |
いいえ |
いいえ |
|
はい |
はい |
いいえ |
いいえ |
|
はいはい(5) |
いいえ |
いいえ |
いいえ |
|
はい |
はい脚注6 |
はい |
いいえ |
|
はい |
はい |
いいえ |
いいえ |
脚注4 スタンドアロンのストアド・プロシージャ、関数およびパブリック・パッケージ構成
脚注5
ロールに付与できない権限
脚注6
スナップショットに対しても付与可能
関連トピック
親トピック: アプリケーションでのオブジェクト権限
9.10.2 オブジェクト権限によって許可されるSQL文
アプリケーションの実装時およびテスト時には、必要な各ロールを作成する必要があります。
各ロールの使用例をテストし、データベースへのアクセス権がアプリケーション・ユーザーに正しく付与されることを確認します。テスト終了後は、アプリケーションの管理者と共同で各ユーザーに適切なロールが割り当てられていることを確認します。
表9-4に、表9-3で示したオブジェクト権限によって許可されるSQL文を示します。
表9-4 データベース・オブジェクト権限によって許可されるSQL文
オブジェクト権限 | 許可されるSQL文 |
---|---|
|
|
|
|
|
パブリック・パッケージ変数への参照 |
|
|
|
|
|
オブジェクト(表のみ)に対する |
|
順序を使用するSQL文 |
関連トピック
親トピック: アプリケーションでのオブジェクト権限
9.11 データベース通信のセキュリティを強化するためのパラメータ
プロトコル・エラーによる不正パケットの処理や認証エラーの上限の構成など、パラメータを使用してセキュリティを管理できます。
- プロトコル・エラーによってデータベースで受信した不正パケット
SEC_PROTOCOL_ERROR_TRACE_ACTION
初期化パラメータで、プロトコル・エラーが発生したときにトレース・ファイルをどのように管理するかを制御します。 - 不正パケット受信後のサーバー実行の制御
SEC_PROTOCOL_ERROR_FURTHER_ACTION
初期化パラメータで、サーバーで不正パケットを受信した後のサーバー実行を制御します。 - 認証の最大試行回数の構成
SEC_MAX_FAILED_LOGIN_ATTEMPTS
初期化パラメータに設定された認証試行回数を超過すると、確立できなかった接続がデータベースで削除されます。 - データベース・バージョン・バナーの表示構成
SEC_RETURN_SERVER_RELEASE_BANNER
初期化パラメータを使用して、認証中の詳細な製品情報の表示を抑制できます。 - 不正なアクセスおよびユーザー・アクションの監査に関するバナーの構成
SEC_USER_UNAUTHORIZED_ACCESS_BANNER
およびSEC_USER_AUDIT_ACTION_BANNER
初期化パラメータで、不正アクセスやユーザーの監査に関するバナーの表示を制御します。
親トピック: アプリケーション開発者のセキュリティの管理
9.11.1 プロトコル・エラーによってデータベースで受信した不正パケット
SEC_PROTOCOL_ERROR_TRACE_ACTION
初期化パラメータで、プロトコル・エラーが発生したときにトレース・ファイルをどのように管理するかを制御します。
サーバーが不正なパケット、順序に誤りがあるパケット、プライベートまたは未使用のリモート・プロシージャ・コールを受信した場合、Oracle Call Interface(OCI)やTwo-Task Common(TTC)などのネットワーキング通信ユーティリティでは、スタック・トレースおよびヒープ・ダンプを格納する大規模なディスク・ファイルを生成できます。
通常、このディスク・ファイルは、非常に大規模になる可能性があります。侵入者は、サーバーに不正なパケットを繰り返し送信し、ディスクあふれやサービス拒否(DOS)攻撃を発生させることで、システムを使用できないようにする可能性があります。認証されていないクライアントが、この種の攻撃を仕掛ける可能性もあります。
これらの攻撃は、SEC_PROTOCOL_ERROR_TRACE_ACTION
初期化パラメータを次の値のいずれかに設定することで防止できます。
-
None
: サーバーが不正なパケットを無視し、トレース・ファイルまたはログ・メッセージを生成しないように構成します。サーバーの可用性が不正なパケットの受信を認識することよりも圧倒的に重要な場合は、この設定を使用します。たとえば:
SEC_PROTOCOL_ERROR_TRACE_ACTION = None
-
Trace
(デフォルト設定): トレース・ファイルを作成します。これは、ネットワーク・クライアントが不具合の結果として不正なパケットを送信している場合など、デバッグを目的とする場合に便利です。たとえば:
SEC_PROTOCOL_ERROR_TRACE_ACTION = Trace
-
Log
: サーバー・トレース・ファイルに1行の短いメッセージを書き込みます。この選択肢では、一定レベルの監査とシステムの可用性とのバランスがとれます。たとえば:
SEC_PROTOCOL_ERROR_TRACE_ACTION = Log
-
Alert
: データベース管理者または監視コンソールにアラート・メッセージを送信します。たとえば:
SEC_PROTOCOL_ERROR_TRACE_ACTION = Alert
親トピック: データベース通信のセキュリティを強化するためのパラメータ
9.11.2 不正パケット受信後のサーバー実行の制御
SEC_PROTOCOL_ERROR_FURTHER_ACTION
初期化パラメータで、サーバーで不正パケットを受信した後のサーバー実行を制御します。
-
サーバーが悪意のあるクライアントから不正なパケットを受信しているときに、サーバー・プロセスの実行を詳細に制御するには、
SEC_PROTOCOL_ERROR_FURTHER_ACTION
初期化パラメータを次の値のいずれかに設定します。-
Continue
: サーバーの実行を続行します。ただし、サーバーがさらに攻撃を受ける可能性があることに注意してください。たとえば:
SEC_PROTOCOL_ERROR_FURTHER_ACTION = Continue
-
(Delay,
m
)
: クライアントをm
秒間遅延させます(サーバーが次のリクエストを同じクライアント接続から受け付けるまで)。この設定により悪意のあるクライアントはサーバー・リソースを過剰使用できなくなります。正当なクライアントのパフォーマンスも低下しますが、引き続き機能します。この設定を入力する場合は、カッコで囲みます。たとえば:
SEC_PROTOCOL_ERROR_FURTHER_ACTION = (Delay,3)
ALTER SYSTEM
またはALTER SESSION
SQL文を使用してSEC_PROTOCOL_ERROR_FURTHER_ACTION
を設定している場合は、Delay
設定を一重引用符または二重引用符で囲む必要があります。ALTER SYSTEM SEC_PROTOCOL_ERROR_FURTHER_ACTION = '(Delay,3)';
-
(Drop,
n
)
: クライアント接続は、n
個の不正パケットを受信した後に強制的に終了します。この設定を使用すると、トランザクションの損失など、クライアントを犠牲にしてサーバー自体を保護できます。ただし、クライアントは再度接続して、同じ操作を再試行できます。この設定はカッコで囲みます。SEC_PROTOCOL_ERROR_FURTHER_ACTION
のデフォルト値は、(Drop,3)
です。たとえば:
SEC_PROTOCOL_ERROR_FURTHER_ACTION = (Drop,10)
Delay
設定と同様に、ALTER SYSTEM
またはALTER SESSION
を使用してこの設定を変更している場合は、Drop
設定を一重引用符または二重引用符で囲む必要があります。
-
親トピック: データベース通信のセキュリティを強化するためのパラメータ
9.11.3 認証の最大試行回数の構成
SEC_MAX_FAILED_LOGIN_ATTEMPTS
初期化パラメータに設定された認証試行回数を超過すると、確立できなかった接続がデータベースで削除されます。
接続作成の一環として、リスナーはサーバー・プロセスを開始し、そのプロセスをクライアントに付加します。この物理的な接続を使用して、クライアントは接続を認証できます。サーバー・プロセスが開始された後、このサーバー・プロセスに対してクライアントが認証がされます。侵入者は、サーバー・プロセスを起動し、様々なユーザー名とパスワードを使用して認証リクエストを無制限に発行し、データベースへのアクセスを試みます。
アプリケーション接続に対するログイン失敗回数を制限するには、SEC_MAX_FAILED_LOGIN_ATTEMPTS
初期化パラメータを設定して、接続に対する認証試行回数を制限します。認証の試行が指定した回数失敗すると、データベース・プロセスは接続を切断し、サーバー・プロセスが終了します。デフォルトでは、SEC_MAX_FAILED_LOGIN_ATTEMPTS
は3
に設定されます。
SEC_MAX_FAILED_LOGIN_ATTEMPTS
初期化パラメータは、潜在的な侵入者によるアプリケーションへの攻撃を防ぐために設計されているだけでなく、パスワードを忘れた正当なユーザーも対象となることに留意してください。sqlnet.ora
INBOUND_CONNECT_TIMEOUT
パラメータとFAILED_LOGIN_ATTEMPTS
プロファイル・パラメータもログイン失敗を制限しますが、この2つのパラメータは正当なユーザー・アカウントにのみ適用されるという点で異なります。
たとえば、最大試行回数を5に制限するには、init
sid
.ora
初期化パラメータ・ファイルで、次のようにSEC_MAX_FAILED_LOGIN_ATTEMPTS
を設定します。
SEC_MAX_FAILED_LOGIN_ATTEMPTS = 5
親トピック: データベース通信のセキュリティを強化するためのパラメータ
9.11.4 データベース・バージョン・バナーの表示構成
SEC_RETURN_SERVER_RELEASE_BANNER
初期化パラメータを使用して、認証中の詳細な製品情報の表示を抑制できます。
クライアント接続(Oracle Call Interfaceクライアントを含む)が認証されてから、詳細な製品バージョン情報にアクセスできるようにする必要があります。侵入者は、データベース・バージョンを使用して、データベース・ソフトウェアに存在するセキュリティの脆弱性に関する情報を検出する可能性があります。
-
認証されていないクライアントに対してデータベース・バージョン・バナーの表示を制限するには、
init
sid
.ora
初期化パラメータ・ファイルでSEC_RETURN_SERVER_RELEASE_BANNER
初期化パラメータをTRUE
またはFALSE
のいずれかに設定します。デフォルトでは、
SEC_RETURN_SERVER_RELEASE_BANNER
はFALSE
に設定されます。
たとえば、TRUE
に設定すると、Oracle Databaseに正確なデータベース・バージョンが表示されます。たとえば、リリース12.2.0.0の場合は次のようになります。
Oracle Database 12c Enterprise Edition Release 12.2.0.0 - Production
リリース番号にポイント・リリース表記法(Oracle Databaseリリース12.2.0.1など)が使用されている場合、バナーには次のように表示されます。
Oracle Database 12c Enterprise Edition Release 12.2.0.1 - Production
ただし、同じリリースでこのパラメータをNO
に設定すると、このバナーは制限されて、リリース12.2で始まる次の固定テキスト(12.2.0.1のかわりに12.2.0.0.0)が表示されます。
Oracle Database 12c Release 12.2.0.0.0 - Production
親トピック: データベース通信のセキュリティを強化するためのパラメータ
9.11.5 不正なアクセスおよびユーザー・アクションの監査に関するバナーの構成
SEC_USER_UNAUTHORIZED_ACCESS_BANNER
およびSEC_USER_AUDIT_ACTION_BANNER
初期化パラメータで、不正アクセスやユーザーの監査に関するバナーの表示を制御します。
不正なアクセスおよびユーザー・アクション監査をユーザーに警告するには、バナーを作成して構成する必要があります。この通知は、クライアント・アプリケーションがデータベースにログインすると使用可能になります。
-
これらのバナーを構成して表示するには、データベース・サーバー側で次の
sqlnet.ora
パラメータを設定して、バナー情報が含まれるテキスト・ファイルを指し示します。-
SEC_USER_UNAUTHORIZED_ACCESS_BANNER
。たとえば:SEC_USER_UNAUTHORIZED_ACCESS_BANNER = /opt/Oracle/12c/dbs/unauthaccess.txt
-
SEC_USER_AUDIT_ACTION_BANNER
。たとえば:SEC_USER_AUDIT_ACTION_BANNER = /opt/Oracle/12c/dbs/auditactions.txt
-
デフォルトでは、これらのパラメータは設定されません。さらに、バナー・テキストに使用される文字数には512バイトの制限があることを注意してください。
これらのパラメータを設定したら、これらのバナーを取得してエンドユーザーに表示するように、Oracle Call Interfaceアプリケーションで適切なOCI APIを使用する必要があります。
親トピック: データベース通信のセキュリティを強化するためのパラメータ