🌟

文字コードとShift-JISの5C問題

2023/10/09に公開

文字コードとは

各文字に対応付けられた数値 (符号) のこと。
初期の文字コードは文字にコードを対応付けるシンプルなものだったが、複数の文字コードを組み合わせて使ったり、用途に応じて形式を変換したりすることが増えたため、「符号化文字集合」と「文字符号化方式」の大きく2段階で文字コードを説明することが多くなった。

Alt text
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html

もっとやさしいことばで

文字コード

  • 文字コード = 文字集合 + 文字エンコーディング

文字集合

  • 文字を集めたもの
  • その中でも符号化文字集合とは集めた文字に符号(番号)をつけたもの
  • 代表的なものはASCII、ISO-8859-1、JIS X 0201、JIS X 0208、JIS X 0213、Unicode

Alt text
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html

文字エンコーディング(文字符号化方式)

  • 文字集合を使ってコンピュータ処理するために、文字をバイト列として表現する方式
  • 文字集合は複数組み合わせてもよい
  • 代表的なものはShift-JIS、EUC-JP、UTF-8、UTF-16

Alt text
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html

文字集合と文字符号化方式の対応

Alt text
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html

5C問題とは

Shift-JIS文字の2バイト目に「5c(0x5C)」が来る問題に起因する問題。2バイト目の0x5Cを「\」と解釈するため発生する。
1貫して1バイト文字として取り扱われれば脆弱性にならないが、1バイト文字として取り扱われる場合/Shift-JISとして取り扱われる場合が混在するときに脆弱性が発生する。

たとえば、Shift-JISにおいて「熊」「表」「暴」は以下のような符号が付される

  • 0x94 | 0x5C → 能
  • 0x95 | 0x5C → 表
  • 0x96 | 0x5C → 暴

上記はすべて2バイト目が「5c(0x5C)」の文字である。0x5CはUS-ASCII や ISO-8859-1 ではバックスラッシュに該当するため、エスケープ処理を施したときに0x5cがエスケープ対象と解釈されてしまうことがある。
これはSQLインジェクションなどの攻撃につながる脆弱性になりうる。

以下のSQL文を生成したい

$q = "SELECT * FROM atable WHERE a='$id'";

ここで、$idに以下の文字列を加える

表';DELETE FROM atable--

「表'」の部分の文字コードは以下のようになる
Alt text

0x5cは、US-ASCII や ISO-8859-1 ではバックスラッシュに該当するため、この文字列に対し、文字エンコーディングを考慮せずにエスケープ処理を施した場合、0x5c がエスケープ対象と解釈され、以下のようにエスケープされることがある。
Alt text

これをShift-JISとして解釈すると以下のようになる
Alt text

これを元のSQL文に与えると以下のようになる

SELECT * FROM atable WHERE a='表\'';DELETE FROM atable--'

「'」が「シングルクォートをエスケープしたもの」として解釈されるため、続くもう1つのシングルクォートで文字列リテラルが終端し、セミコロン以降がリテラルの外にはみ出し、SQL文として解釈されてしまう。

どうすればよいの

  • HTTPレスポンスに「ブラウザが認識できる形式」で文字エンコーディングを指定する
    • 〇 Shift-JIS / EUC-JP / UTF - 8
    • × SJIS / Shift-JIS / EUPJP / UTF8
  • エスケープ処理関数において、文字エンコーディングを必ず指定する
  • DB接続ライブラリには文字エンコーディングが指定できるものを選び、正しく指定する
  • Shift-JISは避ける

参考

Discussion