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

FIO05-J. wrap() や duplicate() メソッドで作成したバッファを信頼できないコードにアクセスさせない

IntBufferCharBufferByteBuffer など java.nio パッケージのバッファクラスは、プリミティブデータ型の配列をバッファにラップし Buffer オブジェクトとして返す様々な wrap() メソッドを定義している。これらのメソッドは新しい Buffer オブジェクトを構築するが、構築された Buffer オブジェクトは入力として与えられた配列をそのまま使っている。これらのメソッドについて、Java API [API 2006] には以下のように記述されている。

新しいバッファは指定された char 配列を使ってつくられている。つまり、バッファに変更を加えると配列も変更され、配列に変更を加えるとバッファも変更される。

これらのバッファが信頼できないコードにアクセスされると、バッファで使われている配列が変更される可能性がある。同様に、duplicate() メソッドが作成するバッファにも、元のバッファと同じ配列が使われる。このように複製したバッファへのアクセスを許しても、元の配列の不正な変更が行われる可能性がある。

違反コード (wrap())

以下の違反コード例では、char 型配列を宣言し、この配列をラップする CharBuffergetBufferCopy() メソッドを通じて信頼できないコードに見せている。

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // 初期化
  }

  public CharBuffer getBufferCopy() {
    return CharBuffer.wrap(dataArray);
  }
}
適合コード (asReadOnlyBuffer())

以下の適合コードでは、char 型配列の読取り専用のビューを読取り専用の CharBuffer として返している。標準ライブラリの CharBuffer の実装では、読取り専用 CharBuffer の要素を変更しようとすると java.nio.ReadOnlyBufferException 例外がスローされることが保証されている。

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // 初期化
  }

  public CharBuffer getBufferCopy() {
    return CharBuffer.wrap(dataArray).asReadOnlyBuffer();
  }
}
適合コード (コピー)

以下の適合コードでは、新規に割り当てた CharBufferchar 型配列の内容を明示的にコピーしてから、CharBuffer を返している。悪意ある呼出し元は配列のコピーを変更できるが、元の配列を変更することはできない。

final class Wrap {
  private char[] dataArray;

  public Wrap() {
    dataArray = new char[10];
    // 初期化
  }

  public CharBuffer getBufferCopy() {
    CharBuffer cb = CharBuffer.allocate(dataArray.length);
    cb.put(dataArray);
    return cb;
  }
}
違反コード (duplicate())

以下の違反コード例では、duplicate() メソッドを呼び出し、CharBuffer のコピーを作成して返している。duplicate() メソッドの使用契約に定められているように、返されるバッファで使われている配列は、元のバッファで使われている配列と同じものである。呼出し元が CharBuffer のコピーで使われている配列要素を変更すると、元のバッファで使われている配列も変更されることになる。

final class Dup {
  CharBuffer cb;

  public Dup() {
    cb = CharBuffer.allocate(10);
    // 初期化
  }

  public CharBuffer getBufferCopy() {
    return cb.duplicate();
  }
}
適合コード (asReadOnlyBuffer())

以下の適合コードでは、CharBuffer の読取り専用ビューを返している。

final class Dup {
  CharBuffer cb;

  public Dup() {
    cb = CharBuffer.allocate(10);
    // 初期化
  }

  public CharBuffer getBufferCopy() {
    return cb.asReadOnlyBuffer();
  }
}
リスク評価

信頼できない呼出し元が、wrap()duplicate() メソッドを使って作成されたバッファにアクセスできると、コピー元のデータを変更されてしまう可能性がある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
FIO05-J P18 L1
自動検出

この脆弱性を適切に自動検出することは不可能である。ヒューリスティックなアプローチが役に立つかもしれない。

参考文献
[API 2006] class CharBuffer
[Hitchens 2002] 2.3 Duplicating Buffers
翻訳元

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

FIO05-J. Do not expose buffers created using the wrap() or duplicate() methods to untrusted code (revision 53)

Top へ

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