IntBuffer、CharBuffer、ByteBuffer など java.nio パッケージのバッファクラスは、プリミティブデータ型の配列をバッファにラップし Buffer オブジェクトとして返す様々な wrap() メソッドを定義している。これらのメソッドは新しい Buffer オブジェクトを構築するが、構築された Buffer オブジェクトは入力として与えられた配列をそのまま使っている。これらのメソッドについて、Java API [API 2006] には以下のように記述されている。
新しいバッファは指定された char 配列を使ってつくられている。つまり、バッファに変更を加えると配列も変更され、配列に変更を加えるとバッファも変更される。
これらのバッファが信頼できないコードにアクセスされると、バッファで使われている配列が変更される可能性がある。同様に、duplicate() メソッドが作成するバッファにも、元のバッファと同じ配列が使われる。このように複製したバッファへのアクセスを許しても、元の配列の不正な変更が行われる可能性がある。
違反コード (wrap())
以下の違反コード例では、char 型配列を宣言し、この配列をラップする CharBuffer を getBufferCopy() メソッドを通じて信頼できないコードに見せている。
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(); } }
適合コード (コピー)
以下の適合コードでは、新規に割り当てた CharBuffer に char 型配列の内容を明示的にコピーしてから、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)