6 開発者のセキュリティ上の考慮事項
この項では、開発者にOracle Linux用のセキュアなアプリケーションを作成する方法、およびセキュリティを徹底しながら外部システムにアクセスできるようにOracle Linuxを拡張する方法を提供します。
セキュアなコーディングのための設計原則
ソース・コード・レベルでセキュリティを強化するには、次の設計原則に従います:
- 最小限の権限
-
プロセスまたはユーザーには、作業の実行に必要な最小限の権限のみを付与します。ユーザー権限はロールに従って割り当てられ、その他すべての権限は拒否されます。最小保護ドメインを作成するには、プロセスまたはスレッドで必要とするときに権限を割り当て、その後権限を削除します。この原則により、攻撃およびユーザー・エラーによって発生する可能性のある損害を限度内にとどめることができます。
- メカニズムの簡潔性
-
設計を簡潔にします。これにより、誤りが減少し、不整合が少なくなり、コードの理解とデバッグが容易になります。
- すべての媒介
-
最初のリソースのみでなく、リソースへのアクセスを試行するたびにチェックします。たとえば、Linuxではプロセスでファイルを開いた後ではなく、開くときにアクセス権をチェックします。プロセスでファイルをオープンしている間にファイルの権限が変更された場合は、不正なアクセスにつながる可能性があります。開いているファイルがアクセスされるたびに権限をチェックできますが、実際には、アクセスが最初に取得された状況のために、このようなチェックは不要なオーバーヘッドとみなされます。
- オープンな設計
-
コードの設計または実装を共有します。システムへの開放的なバック・ドアの安全性は、その存在を認識していることと同じなので、バック・ドアが発見される前に見つけて閉じることができるようにすることは、適切なセキュリティ・プラクティスと考えられます。この原則はパスワードや暗号化キーなどの情報には適用されません。これらの情報は、できるだけ少数の人々の間で共有することが適切です。このため、多くのセキュアな認証スキーマでは、PINコードやパスワードの情報に加えて、生体認証またはハードウェア・トークンやスマート・カードなどの物理的なアーティファクトの所持にも依拠しています。
- 権限の分離
-
コードを、各モジュールで特定タスクを実行するための特定の限定された権限セットを必要とする、複数のモジュールに分割します。機密操作へのアクセス権を付与するには、複数の権限が必要になる場合があります。この原則により、職務が確実に分離され、徹底的な防御が可能になります。たとえば、権限のないメイン・スレッドは、タスクを実行するために特権スレッドを生成できます。メイン・スレッドへの攻撃に成功しても、システムへの最小限のアクセス権しか取得できません。
- 最小限の共通メカニズム
-
ユーザーとそれらのアクティビティを互いに分離します。ユーザーがプロセスやスレッド、情報チャネルを共有することは、適切なセキュリティ・プラクティスとはみなされません。
- フェイルセーフなデフォルト
-
デフォルトでは、操作へのアクセスを拒否します。必要な権限を持たないユーザーが操作を実行しようとすると、その操作は拒否され、システムは操作が開始される前と同じくらい安全です。
- アカウンタビリティ
-
ユーザーが実行を試みたアクションごとに、ユーザーとユーザーの権限をログに記録します。ログをローテーションおよびアーカイブして、ファイル・システムが一杯にならないようにできます。
- 心理的な受け入れやすさ
-
インストール、構成、使用が簡単なセキュリティ・メカニズムを選択し、ユーザーが回避しようと考えないようにします。
セキュアなコーディングの一般的なガイドライン
-
タイプ・チェック、長さチェック、バインド・チェックを実行して、入力データがプログラムで必要なデータであることを確認します。入力には、ユーザーが入力するデータに加えて、コマンドライン引数および環境変数が含まれます。
-
インジェクション攻撃で利用される可能性のあるシェル・コマンド、SQL文、XMLまたはHTMLコードなどの構造体が含まれているかどうか、入力データを確認します。
-
システム・コールおよびライブラリ・ルーチンに対する引数のタイプ、長さ、バインドを確認します。可能な場合は、バッファ・オーバーフローを防ぐライブラリ・ルーチンを使用します。
-
ファイル名引数にはフルパス名を使用します。あらゆるユーザーが書込み可能なディレクトリのファイルは使用しないでください。また、書き込まれるファイルがシンボリック・リンクでないことを確認し、既存のファイルが間違って上書きされないようにします。
-
システム・コールおよびライブラリ・ルーチンから返される値のタイプ、長さ、バインドを確認します。コードが、システム・コールおよびライブラリ関数で設定された、またはこれらから返されたエラー・コードに適切に応答するようにします。
-
シェル環境の状態を想定しないでください。ユーザー・ファイル作成マスク、シグナル処理、ファイル記述子、現在の作業ディレクトリ、環境変数など、特に
PATH
やIFS
など、プログラムがシェルから継承した設定を確認します。必要に応じて、設定をリセットします。 -
有限の値セットをとる変数で、アサーション・チェックを実行します。
-
権限アクションやエラー条件に関する情報を記録します。エンドユーザーのシステム上で、プログラムがコア・ファイルをダンプしないようにしてください。
-
パスワードを画面にエコーしたり、クリア・テキストで送信または保存したりしないでください。パスワードを送信または保存する前に、Salt値と組み合せて、SHA-512などのセキュアな一方向アルゴリズムを使用してハッシュを作成します。
-
プログラムで擬似乱数生成ルーチンを使用する場合、生成する番号がセキュリティ要件を満たすのに十分にランダムであることを確認します。また、潜在的な攻撃者が予測できないよいランダム・シードを使用してください。詳細は、RFC 4086、『Randomness Requirements for Security』を参照してください。
-
ホスト・システムでアドレス空間配置のランダム化(ASLR)を有効にします。この機能は、特定のタイプのバッファ・オーバーフロー攻撃を撃退する可能性があるためです。「アドレス空間配置のランダム化」を参照してください。
-
プログラムをコンパイルしてリンクする際、位置独立実行形式(PIE)機能を使用して位置独立バイナリを生成します。「位置独立実行形式」を参照してください。
-
chroot()
を使用して、プログラムの操作境界をファイル・システム内の指定された場所に制限することを検討してください。 -
プログラム内、特に
setuid
またはsetgid
プログラムからpopen()
またはsyscall()
をコールしてシェル・コマンドを実行しないでください。
setuid
またはsetgid
ビットが設定されていて、権限を持たないユーザーのかわりに権限アクションを実行できる場合に適用されます:
-
シェル・スクリプトで
setuid
またはsetgid
ビットを設定しないでください。ただし、setuid
またはsetgid
のPerlスクリプトを使用する場合は、perlを"taint"モードで実行できます。これは、同様のCコードを使用するよりも安全です。詳細は、perlsec(1)
マニュアル・ページを参照してください。 -
setuid
またはsetgid
が付与する権限の使用を、その権限を必要とする機能に制限し、その後有効なUIDまたはGIDをユーザーのUIDまたはGIDに戻します。可能な場合は、権限機能は独自の監視対象スレッドまたはプロセスで実行します。 -
PATH
環境変数を使用するexeclp()
またはexecvp()
を使用して、子プロセス内でsetuid
またはsetgid
プログラムを実行しないでください。
ネットワーク・プログラムの一般的なガイドライン
-
IPアドレスで逆参照を実行して完全修飾ドメイン名を取得し、このドメイン名を使用してIPアドレスを検索します。両方のIPアドレスが同一であることを確認します。
-
オーバーロードされたリクエストの処理を一時停止して、サービスをサービス拒否(DoS)攻撃から保護します。
-
ネットワーク経由の読取りおよび書込みリクエストにタイムアウトを設定します。
-
ネットワーク経由で受信したデータのコンテンツ、バインド、値およびタイプをチェックして、プログラムで必要とされる内容と合致しないデータは拒否します。
-
証明書または事前共有キーを使用して、ネットワーク接続のローカルおよびリモート・エンドを認証します。
-
TLSやSSLなどの暗号化テクノロジを使用して、ネットワーク接続を介して送信されるデータを保護します。
-
可能な場合は、セキュリティ特性が広く認識されている既存のネットワーキング・プロトコルおよびネットワーキング・テクノロジを使用します。
-
成功および失敗した接続試行、データ受信および送信エラー、サービス状態の変更に関する情報を記録します。