JPCERT コーディネーションセンター

SEC08-J. ネイティブメソッドにはラッパーメソッドを定義する

Javaにはネイティブメソッドが定義されており、これはCやC++言語で書かれている[JNI 2006]。ネイティブメソッドはJavaに拡張性をもたらす一方、Java言語のポリシーがネイティブメソッドには適用されないため、Java特有の柔軟性と可搬性が失われてしまう。ネイティブメソッドが利用される場面としては、プラットフォーム固有の処理を行う場合、レガシーなライブラリコードとのやり取りを行う場合、プログラムの性能を向上させる場合などが挙げられる。[Bloch 2008]

ネイティブメソッドに対するラッパーメソッドを定義することで、セキュリティマネージャによる適切なチェック、ネイティブコードに渡される引数や返り値の検証、可変な入力のディフェンシブコピーの作成、信頼できないデータの無害化処理等を行うことができる。したがって、すべてのネイティブメソッドはprivate宣言し、ラッパーメソッドからのみ呼び出されるようにしなくてはならない。

違反コード

以下の違反コード例において、nativeOperation()メソッドはpublic宣言されたネイティブメソッドである。したがって、信頼できない呼び出し元によって呼び出されてしまうかもしれない。ネイティブメソッド呼び出しはセキュリティマネージャによるチェックを回避する。

ラッパーメソッドであるdoOperation()は、ネイティブメソッドであるnativeOperation()を呼び出している。しかし、入力値検査やセキュリティチェックは行っていない。

public final class NativeMethod {

  // public 宣言されたネイティブメソッド
  public native void nativeOperation(byte[] data, int offset, int len);

  // セキュリティチェックと入力値検査を行わないラッパーメソッド
  public void doOperation(byte[] data, int offset, int len) {
    nativeOperation(data, offset, len);
  }
  
  static {
    // クラスの静的初期化子でネイティブライブラリをロード
    System.loadLibrary("NativeMethodLib"); 
  }
}
適合コード

以下の適合コードでは、ネイティブメソッドをprivate宣言している。ラッパーメソッドであるdoOperaton()は、権限(permission)を確認し、可変入力配列dataのディフェンシブコピーを作成し、引数の範囲チェックを行っている。そのため、nativeOperation()メソッドは安全な入力を引数として呼び出されている。入力値検査の結果はネイティブメソッドが要求する入力の仕様に合致していなくてはならない点に注意。

public final class NativeMethodWrapper {

  // private 宣言したネイティブメソッド
  private native void nativeOperation(byte[] data, int offset, int len);

  // セキュリティマネジャーによるチェックと入力値検査を行うラッパーメソッド
  public void doOperation(byte[] data, int offset, int len) {
    // ネイティブメソッドを呼び出すには権限が必要
    securityManagerCheck();

    if (data == null) {
      throw new NullPointerException();
    }

    // 可変である入力をコピー
    data = data.clone();

    // 入力値の検査
    if ((offset < 0) || (len < 0) || (offset > (data.length - len))) {
      throw new IllegalArgumentException();
    }

    nativeOperation(data, offset, len);
  }

  static {
    // クラスの静的初期化子でネイティブライブラリをロード
    System.loadLibrary("NativeMethodLib"); 
  }
}
例外

SEC08-EX0: セキュリティマネージャによるチェック、引数や返り値の検査、可変入力のディフェンシブコピーの作成等が不要(たとえばCの標準関数int rand(void))であるようなネイティブメソッドは、ラッパーを作成する必要はない。

リスク評価

ネイティブメソッドにラッパーメソッドを定義しないと、権限を持たない呼び出し元がネイティブメソッドを呼び出し、ネイティブメソッドのライブラリに存在する脆弱性(たとえばバッファオーバーフロー)を悪用する恐れがある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
SEC08-J P4 L3
自動検出

一般に自動検出は不可能であるが、「デザインフラグメント」 [Fairbanks 2007]のような手法は、プログラマや静的解析ツールの助けになるであろう。

関連ガイドライン
MITRE CWE CWE-111. Direct use of unsafe JNI
Secure Coding Guidelines for the Java Programming Language, Version 3.0 Guideline 3-3. Define wrappers around native methods
参考文献
[Fairbanks 2007]  
[JNI 2006]  
[Liang 1997]  
[Macgregor 1998] Section 2.2.3, Interfaces and Architectures
翻訳元

これは以下のページを翻訳したものです。

SEC08-J. Define wrappers around native methods (revision 85)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter