文字コードとShift-JISの5C問題
文字コードとは
各文字に対応付けられた数値 (符号) のこと。
初期の文字コードは文字にコードを対応付けるシンプルなものだったが、複数の文字コードを組み合わせて使ったり、用途に応じて形式を変換したりすることが増えたため、「符号化文字集合」と「文字符号化方式」の大きく2段階で文字コードを説明することが多くなった。
引用: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
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html
文字エンコーディング(文字符号化方式)
- 文字集合を使ってコンピュータ処理するために、文字をバイト列として表現する方式
- 文字集合は複数組み合わせてもよい
- 代表的なものはShift-JIS、EUC-JP、UTF-8、UTF-16
引用:https://www.ogis-ri.co.jp/otc/hiroba/technical/program_standards/part1.html
文字集合と文字符号化方式の対応
引用: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--
「表'」の部分の文字コードは以下のようになる
0x5cは、US-ASCII や ISO-8859-1 ではバックスラッシュに該当するため、この文字列に対し、文字エンコーディングを考慮せずにエスケープ処理を施した場合、0x5c がエスケープ対象と解釈され、以下のようにエスケープされることがある。
これをShift-JISとして解釈すると以下のようになる
これを元の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