6. 文字コードとセキュリティ
文字集合
１バイト文字集合の包含関係
ISO-8859-1
Latin-1 US-ASCII

マルチバイト文字集合の包含関係

JIS X 0201
半角カナ

UnicodeJIS X 0213 第4マイクロソフト標準キャラクタセット
JIS X 0201
JIS X 0208
半角カナ
全角カナ

Unicode当初１６ビットですべての文字を表現する予定だったが、不十分で２１ビットに拡張された。元の１６ビット範囲をBMPと呼ぶ。（U＋XXXX or XXXXXX)
文字集合間の文字割り当ての違い
文字集合
0x5C
0xA5
\ASCII%JIS X 0201
\・\ISO-8859-1\\Unicode\￥（Ｕ＋００４５）の状態で、エスケープ処理が行われた後で、バックスラッシュ（＼）に変換されると、エスケープ処理をすり抜けることになります。

文字エンコーディング
Ｓｈiｆｔ－ＪＩＳ

ラリルレロの２バイト目がＳｈiｆｔ－ＪＩＳの各バイトの分布0１バイト文字２バイト文字の先行バイト２バイト文字の後続バイト

ＥＵＣ－ＪＰ

不正なＳｈｉｆｔ－ＪＩＳ
#

#

#

#

A0

C0E0FF
Ｓｈｉｆｔ－ＪＩＳの先行バイトの後にデータがない場合（例：０ｘ８１）
Ｓｈｉｆｔ－ＪＩＳの先行バイトに続くバイトが、後続バイトの範囲にない場合（例：０ｘ８１ ０ｘ２１）

ラリルレロの４バイト目がＥＵＣ－ＪＰの各バイトの分布0１バイト文字２バイト文字の先行バイト２バイト文字の後続バイト「宴」にマッチする##「蛍」にマッチする
#

#

A0

C0

E0

FF

ＩＳＯ－２０２２－ＪＰ「ＥＳＣ＄Ｂ」でＪＩＳ X 0208に切り替え、「ＥＳＣ（Ｂ」でＵＳ－ＡＳＣＩＩに切り替える。
「インターネットでは半角カナを使うな」というのは、ＩＳＯ－２０２２ーＪＰが半角カナ（JIS X 0201）をサポートしないことに由来します。
ＵＴＦ－１６
もともと１６ビット内で設計されていたが、２１ビットに拡張された。
UCS-2 は１６ビットのスカラ値を扱う。
BMP外の文字をサポートする符号化方式がＵＴＦ-16
UTF-16でBMPをサポートするのが、サロゲートペアで、（0xD800～0xDBFF）、（0xDC00～0xDFFF）の２つの領域を予約し、組み合わせて２の20乗文字を表現する。

ＵＴＦ－８
UTF-8のビットパターン
スカラ値の範囲
UTF-8ビットパターン
０～７F
0xxxxxxx
８０～７FF110 xxxxx 10 xxxxxx
８００～FFFF
1110 xxxx 10 xxxxxx
１００００～１０FFFF
11110 xxx 10 xxxxxx

10 xxxxxx
10 xxxxxx

ビット長
７ビット
１１ビット
１６ビット
２１ビット

10 xxxxxx

UTF-8の各バイトの配置0
１バイト文字２バイト文字の先行バイト２バイト文字の後続バイト

#

#

#

#

A0

C0E0FFUTF-8の非最短形式の問題

U+007F までの文字は、２バイト以上のビットパターンを当てはめて符号化できる。

文字の途中に別の文字がマッチする問題は起きません。

「/」 の非最短形式による脆弱性１バイト
0x2F
２バイト
0xC0
0xAF
３バイト
0xE0
0x80
0xAF
４バイト
0xF0
0x80
0x80

最短形式
非最短形式0xAF

UTF-8の非最短形式による脆弱性
・ セキュリティチェックで、非最短形式 0xC0 0xAF がスラッシュ 0x2F でないと見なされる・ ファイル名などとして、非最短形式 0xC0 0xAF を使うと、スラッシュと見なされる※ UTF-8の最新規格では、UTF-8の非最短形式は処理してはならないとされています
UTF-8の非最短形式を許していた処理系
・ Java SE6 Update 10以前のJRE（Java実行環境）
・ PHP５．３．１以前の htmlspecialchars関数
その他の非正規なUTF-8
ISO/IEC 10646 Unicodeよりも広い３１ビット空間で、UTF-8符号化後の1文字が最大６バイトだったが、2006年改訂で、実質的にUnicodeと同じものとなり、UTF-8符号化後の1文字も最大４バイトとなった。
PHPの文字エンコーディング関数 mb_check_encoding
・ PHP5.3 まではUTF-8の５バイト以上の形式を正しいエンコーディングと判断
・ PHP5.4 以上は間違いと判断
サロゲートペア領域の文字の変換
・ 正しい変換 ： ①まず、UTF-32に変換 ⇒ 次にUTF－８に変換 ⇒ 結果４バイト
・ 機械的に UTF-8 に変換すると、３バイトになる※ このような文字エンコーディングに CESU-8 がある （oracleDBの内部処理で使用）
・ PHPの文字エンコーディング関数 mb_check_encoding① PHP5.2 では正しいと判断② PHP5.3.0 以降では間違いと判断

文字コードを正しく扱うために● Java と ASP.NET は入力時に文字エンコーディングの変換処理が入るので、チェックされ、不正な文字は代替文字（U+FFFD）に変換される。
● Perl （5.8以降）の場合は、decode関数による内部形式への変換時に、不正文字エンコーディングは代替文字に変換されます。
● PHPの場合には、文字エンコーディングが自動的にチェックされないので、mb_check_encoding関数により、チェックします。
● マルチバイト文字の扱いはJava、.NET、Perl（5.8以降）は問題ないが、PHPはマルチバイト文字に対応していないので、以下に従う必要があります。
①ソースコードはUTF-８で保存② php.ini の default_charset （PHP5.6以降） あるいは mbstring.internal_encoding （PHP5.5以前）を、UTF-8と設定する③文字列処理は原則 mbstring系の関数を使う④関数の引数として、正しく文字エンコーディングを指定する● HTTPレスポンスの Content-Type を正しく指定する● データベースの文字エンコーディングを正しく指定する① MySQLでは、「utf8」 は３バイトまでの形式で、BMP外の文字を含む場合は、「utf8mb4」 と指定する。
② 「尾骶骨」「𠮷」をデータベースに登録して、表示が崩れたら、Unicodeでの一貫した処理ではなく、途中にＳｈｉｆｔ－ＪＩＳ、EUC-JPの部分がある。

63-001:不正な文字エンコーディングによるXSS(正常系)【ブラウザ】【サーバ： 63/63-001.php 】

【ブラウザ→サーバ： リクエスト 63/63-001.php → レスポンス 】 （初期フォーム表示）【ブラウザ→サーバ： リクエスト 63/63-001.php → レスポンス 】 （送信クリック）

63-001:不正な文字エンコーディングによるXSS(XSS)【ブラウザ】【サーバ： 63/63-001.php 】

【ブラウザ→サーバ： リクエスト 63/63-001.php → レスポンス 】 （初期フォーム表示）【ブラウザ→サーバ： リクエスト 63/63-001.php → レスポンス 】 （送信クリック）

63-002:不正な文字エンコーディングによるXSS対策版(XSS)【ブラウザ】【サーバ： 63/63-001.php 】

【ブラウザ→サーバ： リクエスト 63/63-002.php → レスポンス 】 （初期フォーム表示）【ブラウザ→サーバ： リクエスト 63/63-002.php → レスポンス 】 （送信クリック）