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

FIO11-J. バイナリデータを文字データとして読み込もうとしない

Javaでは、文字データやバイナリデータを送信するときに、バイト配列がよく使われる。一方、バイナリデータを文字データとして読み込むと、正しく処理されない場合がある。なぜならば、バイナリデータのなかには、デフォルトあるいは指定されたエンコーディングの文字コードの範囲に収まらない値が含まれ、文字データとして扱えない場合があるからである。たとえば、暗号鍵データを、送信する際に単純に文字データに変換しようとすると、文字コードの範囲に収まらないバイト値が含まれるため、エラーになる。

違反コード

以下の違反コード例では、BigInteger を表現しているバイト配列を String に変換している。ところが、いくつかのバイト値は有効な文字を表さないため、結果として得られる String データでは、元のデータの情報が落ちてしまっている。この String データを BigInteger データに戻すと異なる値となる。

BigInteger x = new BigInteger("530500452766");
// x を String に変換
byte[] byteArray = x.toByteArray();
String s = new String(byteArray);
// s から BigInteger に変換しなおす
byteArray = s.getBytes();
x = new BigInteger(byteArray);

デフォルトの文字エンコーディングが US-ASCII である Linux 環境で実行すると、文字列 s{?J?? となる。これは表示可能でない文字が含まれているためである。これを BigInteger に変換しなおすと、149830058370101340468658109 となる。

適合コード

以下の適合コードでは、まず BigInteger オブジェクトの String 表現を生成し、それから String オブジェクトをバイト配列に変換している。入力に対してはこの逆の処理が行われる。String オブジェクトのテキスト表現は BigInteger クラスによって生成されるため、有効な文字のみが含まれている。

BigInteger x = new BigInteger("530500452766");
String s = x.toString();  // 有効な文字データ
try {
  byte[] byteArray = s.getBytes("UTF8");
  // ns の中身は "530500452766"
  String ns = new String(byteArray, "UTF8");  
  // 元の BigInteger を作る
  BigInteger x1 = new BigInteger(ns); 
} catch (UnsupportedEncodingException ex) {
  // エラー処理
}

元の BigInteger を得ようとして String オブジェクトをバイト配列に変換してはいけない。変換して得られるバイト配列を BigInteger に変換すると、元とは異なった値になってしまう。

例外

FIO11-EX0: バイナリデータが文字データとして有効な値のみを含むのであれば、文字データとしての読み込みや文字列への変換を行ってもよい。このような処理をセキュアに行う方法については「IDS13-J. ファイル入出力やネットワーク入出力の両端で互換性のある文字エンコーディングを使う」を参照。 あわせて「IDS10-J. 一文字を構成するデータを分割しない」も参照。

リスク評価

バイナリデータを含むバイト配列を文字データとして読み込むと、予期せぬ結果を招く可能性がある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
FIO11-J P2 L3
参考文献
[API 2006] Class String
翻訳元

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

FIO11-J. Do not attempt to read raw binary data as character data (revision 59)

Top へ

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