特権ブロックにおいて、検証されていないあるいは信頼できないデータ(「汚染された(tainted)データ」とも呼ばれる)を使った処理を行ってはならない。攻撃者は、プログラムに対し、権限昇格攻撃につながるような悪意ある入力を与えることができる。このような脅威を緩和する方法としては、引数を取るのではなく値をハードコードしたり(それが適切である場合)、データの検証や無害化を行った後で特権を持つ処理を行う方法がある(「IDS00-J. SQL インジェクションを防ぐ」を参照)。
違反コード
以下の違反コード例では、引数として受け取るパス名やファイル名は汚染されている。攻撃者は、このメソッドにファイルのパス名を与えることで、保護されるべきファイルにアクセスできる。
private void privilegedMethod(final String filename) throws FileNotFoundException { try { FileInputStream fis = (FileInputStream) AccessController.doPrivileged( new PrivilegedExceptionAction() { public FileInputStream run() throws FileNotFoundException { return new FileInputStream(filename); } } ); // ファイルを使って何らかの処理を行い、その後ファイルをクローズする } catch (PrivilegedActionException e) { // ハンドラに処理を移す } }
適合コード (入力値検査)
以下の適合コードでは、悪意ある入力を無害化する cleanAFilenameAndPath() メソッドを呼び出している。無害化メソッドの呼出しが正常に完了したということは、入力を受け付けてよく、doPrivileged() ブロックを実行してよいということを意味する。
private void privilegedMethod(final String filename) throws FileNotFoundException { final String cleanFilename; try { cleanFilename = cleanAFilenameAndPath(filename); } catch (/* cleanAFileNameAndPath の仕様が定める例外 */) { // cleanAFilenameAndPath の仕様に基づき、 // ログに保存するか、ハンドラに処理を移す } try { FileInputStream fis = (FileInputStream) AccessController.doPrivileged( new PrivilegedExceptionAction() { public FileInputStream run() throws FileNotFoundException { return new FileInputStream(cleanFilename); } } ); // ファイルを使って何らかの処理を行い、その後ファイルをクローズする } catch (PrivilegedActionException e) { // ハンドラに処理を移す } }
この手法の欠点の1つは、効果的に無害化するメソッドを書くのは難しいということである。逆に利点は、「汚染解析(taint analysis)」との相性がよいという点である(本ルールの自動検出セクションを参照)。安全にファイル操作を行う方法については、「FIO00-J. 共有ディレクトリにあるファイルを操作しない」を参照。
適合コード (ファイル名とパス名をあらかじめ組み込む)
汚染された入力値の無害化には常に、データが完全に無害化されないリスクが伴う。異なるファイル名やパス名が同じ実体を指すことを検出できないエラーや、ディレクトリトラバーサルは、入力として受け取ったパス名やファイル名を適切に無害化しないことが原因で作り込まれる脆弱性の例である(「IDS02-J. パス名は検証する前に正規化する」を参照)。権限を持たないユーザが、任意の、保護されたファイルやリソースにアクセスしなくてはならないようなプログラムの設計は、常に疑うべきである。ハードコードされたリソース名を使用したり、リソース名に間接的にマッピングされた選択肢から選択させるような設計を検討すること。
次に示す適合コードでは、ファイル名をハードコードし、特権ブロックで使用される変数を同じメソッド内に制限している。これにより、特権メソッドを攻撃して悪意あるファイルを開かせることはできない。
static final String FILEPATH = "/path/to/protected/file/fn.ext"; private void privilegedMethod() throws FileNotFoundException { try { FileInputStream fis = (FileInputStream) AccessController.doPrivileged( new PrivilegedExceptionAction() { public FileInputStream run() throws FileNotFoundException { return new FileInputStream(FILEPATH); } } ); // ファイルを使って何らかの処理を行い、その後クローズする } catch (PrivilegedActionException e) { // ハンドラに処理を移し、ログに保存する } }
リスク評価
特権を伴う処理で汚染された入力が用いられると、権限昇格攻撃につながる恐れがある。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
SEC01-J | 高 | 高 | 低 | P27 | L1 |
自動検出
汚染解析をサポートする静的解析ツールを使うことで、最初の適合コードに示したようなコードを検証することが可能になる。典型的な汚染解析では、汚染されている可能性のある入力を無害化し、汚染されていない出力(あるいは適切なエラーの通知)を行う1つ以上のメソッドが存在することを前提に解析を行う。汚染解析を行うことで、汚染されていないデータのみが doPrivileged ブロックの中で使用されることを保証することができる。静的解析を行う場合には、無害化メソッドが必ず正しく無害化を行うということを前提にしなくてはならないが、現実はそうではないであろう。
関連ガイドライン
MITRE CWE | CWE-266. Incorrect privilege assignment |
CWE-272. Least privilege violation | |
CWE-732. Incorrect permission assignment for critical resource | |
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 6-2. Safely invoke java.security.AccessController.doPrivileged |
参考文献
[API 2006] | Method doPrivileged() |
[Gong 2003] | Sections 6.4, AccessController, and 9.5, Privileged Code |
[Jovanovic 2006] | Pixy: A Static Analysis Tool for Detecting Web Application Vulnerabilities |
翻訳元
これは以下のページを翻訳したものです。
SEC01-J. Do not allow tainted variables in privileged blocks (revision 79)