クライアントコードはpublic staticフィールドにアクセスすることができる。セキュリティマネージャはそのようなフィールドの読み書きをチェックしない。さらに、フィールドに代入される値は、代入が完了するまでプログラムから検証することはできない。
マルチスレッド環境では、final宣言されていないpublic staticフィールドの変更で不整合が発生する可能性がある。具体例については「TSM01-J. オブジェクトの構築時にthis参照を逸出させない」を参照。
public staticフィールドを間違って使うと型安全性の問題につながる可能性がある。たとえば、変数がjava.lang.Objectのようなより一般的な型であるとき、信頼できないコードは悪意あるメソッドを持つサブタイプを用意することができる[Gong 2003]。したがって、クラスはfinalでないpublic staticフィールドを持つべきではない。
違反コード
以下の違反コード例はJDK v1.4.2から引用した[FT 2008]。public staticなフィールドを持った関数テーブルを宣言している。
package org.apache.xpath.compiler; public class FunctionTable { public static FuncLoader m_functions; }
攻撃者は以下のように関数テーブルを入れ換えることができる。
FunctionTable.m_functions = new_table;
関数テーブルを入れ換えることで、攻撃者はXPathContextにアクセスできるようになる。XPathContextはXPath式を評価するときの参照ノードを設定するために使用される。XPathContextを操作することでXMLフィールドを変更して矛盾した状態にし、予期せぬ動作をさせることが可能である。また、static変数はJRE全体でグローバルにアクセスされるため、異なるアプリケーションドメイン間で通信するための裏口として使われる可能性がある(たとえば異なるクラスローダでロードされたコード間など)。
この脆弱性は JDK v1.4.2_05 で修正された。
適合コード
以下の適合コードでは、FuncLoaderフィールドをstatic final宣言し、定数として扱っている。
public static final FuncLoader m_functions; // コンストラクタの中で m_functions を初期化
static final宣言されたフィールドはマルチスレッド環境においても安全である(「TSM03-J. 初期化が完了していないオブジェクトを公開しない」を参照)。 しかし、final宣言するだけでは、初期化される前のstatic final変数の値を攻撃者が間接的に読み出すことは、防げないかもしれない(詳細は「DCL00-J. クラスの初期化を循環させない」を参照)。さらに、参照されるオブジェクト自体が可変であれば、そのオブジェクトのフィールドを変更できる。
m_functionsをprivate宣言し、その値を取得するためのラッパーメソッドを使うのもよい。詳しくは「OBJ01-J. データメンバはprivate宣言し、それにアクセスするためのラッパーメソッドを提供する」を参照。
違反コード (serialVersionUID)
以下の違反コード例では、シリアライズすることを想定したクラスで、public static宣言されたfinalでないserialVersionUIDフィールドを使っている。
class DataSerializer implements Serializable { public static long serialVersionUID = 1973473122623778747L; // ... }
適合コード
以下の適合コードでは、serialVersionUIDフィールドをprivate final宣言している。
class DataSerializer implements Serializable { private static final long serialVersionUID = 1973473122623778747L; }
serialVersionUID フィールドはシリアライズのメカニズムの内部で使われており、ラッパーメソッドを実装する必要はない。
リスク評価
public static変数を不正に変更されると、予期せぬ動作やクラスの不変条件の侵害につながる可能性がある。さらにstatic変数は、一つの委譲連鎖(delegation chain)に属する異なるクラスローダによってロードされたコードからもアクセスできるため、そのような変数は異なるアプリケーションドメイン間で通信するための裏口として使われる可能性がある。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
OBJ10-J | 中 | 中 | 中 | P8 | L2 |
関連ガイドライン
MITRE CWE | CWE-493. Critical public variable without final modifier |
CWE-500. Public static field not marked final | |
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 3-1. Treat public static fields as constants |
参考文献
[FT 2008] | Function Table, Class Function Table |
[Gong 2003] | 9.3, Static Fields |
[Nisewanger 2007] | Antipattern 5, Misusing Public Static Variables |
[Sterbenz 2006] | Antipattern 5, Misusing Public Static Variables |
翻訳元
これは以下のページを翻訳したものです。
OBJ10-J. Do not use public static non-final variables (revision 134)