
PHP8 上級/準上級試験の認定模擬問題として、プライム・ストラテジー様のPRIME STUDYが認定されているようです。ただ、この模擬問題には解説がありませんので解説をまとめていこうと思います。シリーズ第17回目です。

PHP初級レベルから脱却して中級/上級レベルにいきたい人にピッタリの内容ですね。
PRIME STUDY認定模擬問題のリンクはこちらです → https://study.prime-strategy.co.jp/
問題文
XSS (クロスサイトスクリプティング) に関する説明の中で、誤っているものを1つ選びなさい。
なお、すべてのコードの先頭には下記のコードが書かれているものとする。
declare(strict_types=1);
error_reporting(-1);
下記はマニュアルから一部引用した内容である。
(1)
HTML の動的な生成において、実装に問題があるとXSS 脆弱性が発生する。
そのためには、適切な引数で htmlspecialchars() 関数、または htmlentities() 関数を使う必要がある。
そのため、以下のコード
$input = "alert('test');";
$e_input = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
echo $e_input;
を実行すると
<script>alert('test');</script>
となり、必要なエスケープが全てなされているので、XSSを防ぐ事ができる。
(2)
以下のコード
$e_test = htmlspecialchars(filter_input(INPUT_GET, 'test'), ENT_QUOTES, 'UTF-8');
echo "{$e_test}
";
によって、適切に入力がエスケープされるため XSS を防ぐ事ができる。
ただし、もしパラメタ test に配列が入ってきている場合、またはパラメタ test が存在しない場合は、filter_input() 関数の戻り値の仕様が成功した場合は要求された変数の値、フィルタリングに失敗した場合に false、 あるいは変数 var_name が設定されていない場合に null を返します。
であるため、結果は次のとおりとなる。
Fatal error: Uncaught TypeError: htmlspecialchars(): Argument #1 ($string) must be of type string, null given in …
(3)
以下のコード
$val = $_GET['test'] ?? '';
if ( is_string($val) ) {
$ret = htmlentities($val, ENT_QUOTES, 'UTF-8');
echo "{$ret}
";
} else {
foreach($val as $v) {
echo "{$v}
";
}
}
をブラウザ経由で実行すると、test に文字列が入ってきても配列が入ってきても、適切に XSS 対策を行う事ができる。
(4)
$_GET[‘test’] に文字列で任意のユーザ入力が入っている (配列ではない) とした時に、以下のコード
$ret = htmlspecialchars($_GET['test'], ENT_COMPAT);
echo "{$ret}
";
をブラウザ経由で実行すると、シングルクオートが変換されないため、XSS が発生する可能性がある。この実装は適切ではない。
解説
選択肢1の解説
誤りです。
htmlspecialchars() は XSS を防ぐために有効ですが、コード内で使用されている悪意のある入力がエスケープされることに関して誤解があります。
選択肢2の解説
正しいです。
htmlspecialchars() は入力文字列を適切にエスケープしますが、filter_input() の戻り値が null である場合、htmlspecialchars() に null を渡すとエラーになります。このエラーは、htmlspecialchars() が string 型の引数を要求するためです。
選択肢3の解説
正しいです。
このコードは、$_GET[‘test’] が文字列でも配列でも適切に処理できるようにしており、XSS 対策も適切に行っています。is_string($val) を使って文字列かどうかをチェックしている点がポイントです。
選択肢4の解説
正しいです。
htmlspecialchars() を ENT_COMPAT で使用すると、シングルクオートがエスケープされません。したがって、シングルクオートを使った JavaScript のコードが実行される可能性があり、XSS のリスクがあります。ENT_QUOTES を使用するべきです。
正解選択肢
以上より選択肢1が正解となります。
コメント