Skip to content

Commit

Permalink
Merge pull request #955 from EC-CUBE/seasoft-script_escape
Browse files Browse the repository at this point in the history
script_escape パフォーマンス改善
  • Loading branch information
seasoftjapan committed Jul 4, 2024
2 parents 4ba247b + 0dded83 commit 202f3bd
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 31 deletions.
65 changes: 36 additions & 29 deletions data/smarty_extends/modifier.script_escape.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,45 @@
*/
function smarty_modifier_script_escape($value)
{
if (is_array($value)) return $value;
// パフォーマンス低下を軽減するため文字列以外は処理しない。
// TODO: Stringable なオブジェクトも対象とするのが安全かもしれない。しかし、この modifier は、default_modifiers に設定しているため、影響が見通せない (文字列として返して良いのか不確か)。
if (!is_string($value)) return $value;

$pattern = "<script.*?>|<\/script>|javascript:|<svg.*(onload|onerror).*?>|<img.*(onload|onerror).*?>|<body.*onload.*?>|<iframe.*?>|<object.*?>|<embed.*?>|";
static $pattern;
if (is_null($pattern)) {
$pattern = "<script.*?>|<\/script>|javascript:|<svg.*(onload|onerror).*?>|<img.*(onload|onerror).*?>|<body.*onload.*?>|<iframe.*?>|<object.*?>|<embed.*?>|";

// 追加でサニタイズするイベント一覧
$escapeEvents = array(
'onmouse',
'onclick',
'onblur',
'onfocus',
'onresize',
'onscroll',
'ondblclick',
'onchange',
'onselect',
'onsubmit',
'onkey',
);
// 追加でサニタイズするイベント一覧
$escapeEvents = array(
'onmouse',
'onclick',
'onblur',
'onfocus',
'onresize',
'onscroll',
'ondblclick',
'onchange',
'onselect',
'onsubmit',
'onkey',
);

// イベント毎の正規表現を生成
$generateHtmlTagPatterns = array_map(function($str) {
return "<(\w+)([^>]*\s)?\/?".$str."[^>]*>";
}, $escapeEvents);
$pattern .= implode("|", $generateHtmlTagPatterns)."|";
$pattern .= "(\"|').*(onerror|onload|".implode("|", $escapeEvents).").*=.*(\"|').*";

// 正規表現をまとめる
$attributesPattern = "/${pattern}/i";

// 置き換える文字列
$convert = '#script tag escaped#';
// イベント毎の正規表現を生成
$generateHtmlTagPatterns = array_map(function($str) {
return "<(\w+)([^>]*\s)?\/?".$str."[^>]*>";
}, $escapeEvents);
$pattern .= implode("|", $generateHtmlTagPatterns)."|";
$pattern .= "(\"|').*(onerror|onload|".implode("|", $escapeEvents).").*=.*(\"|').*";
$pattern = "/{$pattern}/i";
}

// マッチしたら文字列を置き換える
return preg_replace($attributesPattern, $convert, $value);
// - preg_replace は、(たとえ置換が発生しなくても) preg_match より重い。置換が発生する頻度は極めて低いはずなので、preg_match で事前判定する。
if (preg_match($pattern, $value)) {
// 置き換える文字列
$convert = '#script escaped#';
$value = preg_replace($pattern, $convert, $value);
}

return $value;
}
4 changes: 2 additions & 2 deletions tests/class/modifier/Modifier_ScriptEscapeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function scriptNoEscapeProvider()
public function testメールテンプレート_エスケープされる($value)
{
$ret = smarty_modifier_script_escape($value);
$pattern = "/#script tag escaped#/";
$pattern = "/#script escaped#/";
$this->assertRegExp($pattern, $ret);
}

Expand All @@ -72,7 +72,7 @@ public function testメールテンプレート_エスケープされる($value)
public function testメールテンプレート_エスケープされない($value)
{
$ret = smarty_modifier_script_escape($value);
$pattern = "/#script tag escaped#/";
$pattern = "/#script escaped#/";
$this->assertNotRegExp($pattern, $ret);
}
}

0 comments on commit 202f3bd

Please sign in to comment.