3
7
テーマ、知りたいこと
XSS 対策を実装しているのですが、いつエスケープしたらいいのかいろいろなご意見があるようで疑問です。
使用言語は、HTML、CSS、JavaScript、PHP、MySQLです。
背景、状況
掲示板のコメントを例にします。
保存の際は JavaScript の fetch()
を使い、PHP の PDO()
を介し、MySQL でデータベースに保存しています。
逆に出力は PHP から {"id": 1, "comment": "<p>hello</p>"}
のような JSON を echo
し、 JavaScript で HTML を生成します。
この流れにあたって XSS 対策のタイミングは下記などいくつか考えられそうです。
タイミング
➀ データベースに保存する際にエスケープした値にしておく
PHP
1<?php 2$data = ["comment" => "<p>hello</p>"]; 3$data["comment"] = htmlspecialchars($data["comment"], ENT_QUOTES, "UTF-8"); // ➀はここでエスケープ 4$stmt = $pdo->prepare("INSERT INTO comment_table (comment) VALUES (:comment)"); 5$stmt->bindParam(":comment", $data["comment"], PDO::PARAM_STR); 6$stmt->execute();
➁ データベースには素のまま保存し、PHP から echo
する際にエスケープする
PHP
1$stmt = $pdo->query("SELECT * FROM comment_table WHERE id = 1"); 2$data = $stmt->fetch(PDO::FETCH_ASSOC); // この data は ["id" => 1, "comment" => "<p>hello</p>"] のような値 3$data["comment"] = htmlspecialchars($data["comment"], ENT_QUOTES, "UTF-8"); // ➁はここでエスケープ 4echo json_encode($data);
③ データベースには素のまま保存し、PHP から echo
する際も素のまま echo
し、JSON を HTML として描画する際に JavaScript でエスケープする
JavaScript
1fetch('getComment.php') 2 .then(response => response.json()) 3 .then(data => { // この data は {"id": 1, "comment": "<p>hello</p>"} のような値 4 addNewComment(data); 5 }) 6 .catch(error => { 7 }); 8 9function addNewComment(data) { 10 const ulElement = document.querySelector('.comment-list'); 11 const liElement = document.createElement('li'); 12 liElement.className = 'comment'; 13 liElement.textContent = escapeHtml(data); // ➂はここでエスケープ 14 ulElement.appendChild(liElement); 15} 16 17function escapeHtml(unsafe) { 18 return unsafe 19 .replace(/&/g, "&") 20 .replace(/</g, "<") 21 .replace(/>/g, ">") 22 .replace(/"/g, """) 23 .replace(/'/g, "'"); 24}
いつエスケープするのがセオリーというか、安全というか、実装しやすいというか…
一体どうしたらいいのでしょうか?
回答8件
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。