【PHP】htmlspecialchars関数でエスケープ処理をしてください【XSSの防止】

どーも、服のサイズがMからLになったヨシダです。
やせよ…

みなさん!エスケープ処理してますか!(アントニオ猪木風に)
エスケープ処理とは、マークアップ言語やプログラミング言語、スクリプト言語等で文字列を扱う際に、その言語にとって特別な意味を持つ文字や記号を、別の文字列に置き換えることです。
これをしないと、クロスサイトスクリプティング(XSS)が行えちゃいますから、システムに色々問題が発生してしまいます。
まあ、実際にどのようなことが起こるかは見てみないとわかないですよね。
百聞は一見にしかずって言うし。

てことで、以下の環境で掲示板を作成してみました。

OS CentOS
Web Server Apache
言語 PHP
データベース MariaDB

 

できたのがこんな感じです…

 

検証用掲示板アプリの投稿一覧・入力フォーム画面

 

「送信」を押したら、上に書き込まれて行きます。
例えば、下のように書き込んで

 

検証用掲示板アプリに名前と内容を入力した画面

 

ここから「送信」をポチっとな。

 

検証用掲示板アプリに投稿が2件登録された画面

 

いえええええええええええええええい!!!(サンシャイン池崎風に)
(しょぼいとか言わないで)

ちゃんとデータベース(MariaDB)にも書き込まれています。

 

MariaDBでthread1テーブルの内容をSELECTした結果画面

 

特に問題ないんじゃねーの?と思うかもしれませんが、問題ありありなんですよ。
この掲示板は、まだそのエスケープ処理がされていません。

では、ここにスクリプト

を書き込んでみましょう。

 

検証用掲示板アプリにXSSペイロードを入力した画面

 

「送信」をポチっとな。

 

XSS脆弱性によりアラートダイアログが表示された画面

 

あべし!(北斗の拳風に)
スクリプトが発生してしまいましたね。
これがクロスサイトスクリプティング(XSS)です。
このサイトに訪れれば、誰でもこのアラートが発生してしまいます。
アラートじゃなくて、違うページに飛ばすスクリプトだったりもできますし、色々できちゃいますので、非常に危険です。

この「スクリプト」をスクリプトとしてではなく、文字列として出力するために、エスケープ処理を行います。
現状、以下のようにPHPで文字を出力しています。

 

掲示板アプリの投稿表示部分のPHPソースコード

 

これでは、データベースに保存した文字をそのまま出力しちゃってるのがわかります。
そりゃあ、XSSが発生してまいますよ。
ここで、登場するのが「htmlspecialchars」です。
PHPの関数のひとつです。

使い方は「htmlspecialchars(エスケープする文字列, エスケープの種類, 文字コード);」になります。

基本的に第二引数のエスケープの種類は「ENT_QUOTES」を指定します。
ENT_QUOTES を指定することで、下記のようにエスケープを行ってくれます。

「ENT_QUOTES」以外にも「ENT_COMPAT」や「ENT_NOQUOTES」等複数ありますが、「ENE_QUOTES」よりエスケープしてくれる文字が少ないので使用する機会はほぼないです。

コードを書く時に、毎回長い「htmlspecialchars(エスケープする文字列, エスケープの種類, 文字コード);」を記述すると見づらくなってしまうので、短い関数名にしてしまうのが一般的です。
具体的には以下のコードになります。
—-

function h($s) {
return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}

—-
というわけで、出力するところを下のように書き換えてみました。

 

XSS対策としてhtmlspecialcharsを実装したPHPソースコード

 

これで試しにもう一度スクリプト

を書き込んでみます。

 

XSS対策後、スクリプトタグがそのまま表示される掲示板画面

 

まあ、この時点で

がちゃんと出力されてますが(笑)

「送信」をポチっとな。

 

XSS対策後、スクリプトタグが無害化され表示された掲示板画面

 

O〜〜〜K〜〜〜!!!(狩野英孝風に)
ちゃんとアラートのスクリプトが発生せずに、文字として出力されていますね。

このエスケープ処理は非常に大切なのに、ちゃんと実装されていないページが多すぎます。
例えば、お問い合わせページの確認画面とかは多いですね。
入力フォームにスクリプトをいれて確認ページに移動してみると、発生しちゃったりね。

システムエンジニアさんは、この処理をお忘れなく!

今日の記事は色々すべってましたね。

記事内にでてきた

htmlspecialcharsによりエスケープされたscriptタグの表示例

こちらは、実際には

scriptタグがHTMLエンティティに変換されたソースコード表示

このように記述しないといけませんよ。

ありがとうございました。