シリアライズ可能なクラスが private 宣言された可変インスタンス変数を持っている場合、readObject() メソッドでは、可変インスタンス変数についてはディフェンシブコピーを作成しなければならない。攻撃者は、このようなクラスのシリアライズバイトストリームを改変し、悪意ある参照を追加するかもしれない。このような改変されたバイトストリームを復元すると、内部の変数参照を攻撃者が制御できるようなクラスインスタンスが作られる可能性がある。すなわち、クラスインスタンスが改変され、クラスの不変条件に違反するかもしれない。
このルールは、コンストラクタや信頼できない可変な引数をとるメソッドに適用される「OBJ06-J. 可変入力や可変な内部コンポーネントはディフェンシブコピーを作成する」の具体例である。OBJ06-J と同様の考え方を、可変なフィールドの復元時にも適用するものである。
違反コード
この違反コード例では、可変な Date クラスのオブジェクト date をディフェンシブコピーしていない。そのため、攻撃者は、以下のような MutableSer クラスのインスタンスを作ることができるかもしれない。すなわち、Date のサブクラスとして、攻撃者が意図する動作をするメソッドを持つサブクラスのオブジェクトを date として持つようなインスタンスである。インスタンスに含まれるフィールドが不変であることを前提としているようなコードはすべて脆弱である。
class MutableSer implements Serializable {
private static final Date epoch = new Date(0);
private Date date = null; // 可変なコンポーネント
public MutableSer(Date d){
date = new Date(d.getTime()); // このコンストラクタはディフェンシブコピーを行っている
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// 必要なら内容を検証する
}
}
適合コード
以下の適合コードでは、readObject() のなかで、可変な Date クラスのオブジェクト date のディフェンシブコピーを行っている。フィールドごとに入力値の検証を行っていることに注意。また、このコード例ではセンシティブなデータの保護は行っていない。この点について詳しくは「SER03-J. 暗号化されていないセンシティブなデータをシリアライズしない」を参照。
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = ois.readFields();
Date inDate = (Date) fields.get("date", epoch);
// 以下で可変コンポーネントをディフェンシブコピーしている
date = new Date(inDate.getTime());
// 必要なら内容を検証する
}
不変なサブオブジェクトについてはディフェンシブコピーを行う必要はない。さらに、clone() メソッドを使わないように注意せよ。サブオブジェクトのクラス定義が final 宣言されていなければ clone() メソッドはオーバーライドされているかもしれないし、そもそも clone() メソッドは浅いコピーしか行わないからだ。サブオブジェクトへの参照自体は、ディフェンシブコピーを行えるよう、final 宣言してはならない。clone() の代わりに、writeUnshared() や readUnshared() メソッドを使うことも推奨できない。
リスク評価
オブジェクトを復元するときに可変コンポーネントのディフェンシブコピーを行わないと、オブジェクトの不変性を守ることができない。
| ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
|---|---|---|---|---|---|
| SER06-J | 低 | 中 | 中 | P4 | L3 |
関連ガイドライン
| MITRE CWE | CWE-502. Deserialization of untrusted data |
参考文献
| [API 2006] | |
| [Bloch 2008] | Item 76, Write readObject methods defensively |
| [Sun 2006] | Serialization Specification, A.6, Guarding Unshared Deserialized Objects |
翻訳元
これは以下のページを翻訳したものです。
SER06-J. Make defensive copies of private mutable components during deserialization (revision 58)
