コンテンツへスキップ →

PHPで呼び出した文字列内の特殊文字で、JavaScriptエラーが出る場合の対処法

例えばPHPにてデータベースに入っている文字列を呼び出して、その文字列をJavaScriptで使おうとした際に、「’」シングルクォーテーションや「”」ダブルクオーテーションなどが入っていると、上手く動作しないことがあります。

例えば、JavaScriptの変数にvar a=[“<? echo $data[0]; ?>”,”<? echo $data[1]; ?>”];のようにしていた場合、$data[0]の中にダブルクオーテーションがあれば、動きません。こんな時は、あらかじめPHP側でHTMLエンティティに変換すると解決します。

$data[0]=preg_replace("/&/","&",$data[0]);
$data[0]=preg_replace("/'/","'",$data[0]);
$data[0]=preg_replace("/"/",""",$data[0]);

2013/3/4追記

セキュリティコンサルトの徳丸さんより、XSSのご指摘をいただきました。ありがとうございます。

たしかに、以下のコードは脆弱性がありました。

<?
$data[0]="</script><script>alert(1)//";
$data[0]=preg_replace("/&/","&amp;",$data[0]);
$data[0]=preg_replace("/'/","&#039;",$data[0]);
$data[0]=preg_replace("/"/","&quot;",$data[0]);

$data[1]="');alert('XSS";
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
function test(){ }
var a=["<? echo $data[0]; ?>"];
</script>
</head>

<body>
<a href="javascript:test('<? echo htmlspecialchars($data[1]); ?>')">リンク</a>

</body>
</html>

これをブラウザ開くと、Scriptが実行されてしまいます。最初にhtmlspecialcharsを使うことを考えたのですが、上記のリンクをクリックすると分かるように、これもScriptが実行されてしまい、安全ではありませんでした。

<?
// 文字列をすべて uXXXX 形式に変換
function unicode_escape($matches)
{
	$u16 = mb_convert_encoding($matches[0],'UTF-16','UTF-8');
	return preg_replace('/[0-9a-f]{4}/','u$0',bin2hex($u16));
}

// 英数字とマイナス、ピリオド以外を uXXXX 形式でエスケープ
function escape_js_string($s)
{
	return preg_replace_callback('/[^-.0-9a-zA-Z]+/u','unicode_escape',$s);
}

$data[0]="</script><script>alert(1)//";
$data[1]="');alert('XSS";
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
function test(){ }
var a=["<? echo escape_js_string($data[0]); ?>"];
</script>
</head>

<body>

<a href="javascript:test('<? echo htmlspecialchars(escape_js_string($data[1])); ?>')">リンク</a>

</body>
</html>

そして、これが解決策です。徳丸さんが書かれている「体系的に学ぶ 安全なWebアプリケーションの作り方」113Pに記載されているUnicodeエスケープを使っています。これで不正なスクリプトは実行出来ません。unicode_escapeとescape_js_stringを使って、英数字以外を/uXXXXというUNICODE形式にエスケープしています。

さらに詳しくは以下、徳丸さんの本は詳しくて参考になります。

[sc name=”engeneer”]

SPONSER

SHARE

YouTube

PROFILE

入江 慎吾
個人開発クリエイター。MENTAなどをはじめ、これまでに30個ほどのサービスやアプリをつくりました。最近は生成AIに夢中。コンサル、開発のご依頼はこちらまで。 (詳しいプロフィール)

カテゴリー: 開発奮闘記