XSSを防ごう(PHP)
関数htmlSanitizingは、1番目の引数に無害化したい文字列、2番目の引数は属性値用にするかどうか(true=する、false=しない)を指定すると、無害化した文字列が返る。ちなみにタグは全削除されるようにしてます。
■サンプルソース
<?php
/**
* sanitize for html
* @return (string) converted string for HTML
*/
function htmlSanitizing($value, $attribute = false){
if(!is_array($value)){
if($attribute === true){
if(preg_match('/^javascript:/i', preg_replace('/[\x00-\x20\x22\x27]/', '', $value))){
$value = preg_replace('/^javascript:/i', '',preg_replace('/[\x00-\x20\x22\x27]/', '', $value));
}
$value = htmlspecialchars(strip_tags($value), ENT_QUOTES);
return $value;
}
else{
$value = htmlspecialchars(strip_tags($value), ENT_QUOTES);
return $value;
}
}
else{
foreach($value as $key => &$val){
$val = htmlSanitizing($val, $attribute);
}
unset($val);
return $value;
}
}
?>
■おまけ
再帰してるところで、array_mapを使おうとしたのだが、var_dumpをしたところ、連想配列のキーが削除されてしまったので、foreachとリファレンス(参照渡し)で代用することにした。
■追記
/**
* sanitize for html
* @return (string) converted string for HTML
* @param (array)
* [attribute] => (bool)
* [striptags] => (bool)
* [escape] => (string) 'entities' or 'chars'
* [quotes] => ENT_COMPAT, ENT_QUOTES or ENT_NOQUOTES
*/
function htmlSanitizing($value, $arg = array()){
if(!is_array($value)){
$attribute = (isset($arg['attribute']) && $arg['attribute'] === true)? true : false;
$striptags = (isset($arg['striptags']) && $arg['striptags'] === true)? true : false;
$escape = (isset($arg['escape']) && $arg['escape'] === 'entities')? 'entities' : 'chars';
$quotes = (isset($arg['quotes']) && $arg['quotes'] !== '')? $arg['quotes'] : ENT_QUOTES;
$value = ($striptags)? strip_tags($value) : $value;
$value = ($escape === 'entities')? htmlentities($value, $quotes) : htmlspecialchars($value, $quotes);
if($attribute){
if(preg_match('/^javascript:/i', preg_replace('/[\x00-\x20\x22\x27]/', '', $value))){
$value = preg_replace('/^javascript:/i', '',preg_replace('/[\x00-\x20\x22\x27]/', '', $value));
}
}
return $value;
}
else{
foreach($value as $key => &$val){
$val = htmlSanitizing($val, $arg);
}
unset($val);
return $value;
}
}
コメントの返事を書いてる時に、いろいろと考えてみまっしたー。。。三項演算子が嫌いな方はいるかもしれませぬが、こんなんドウでしょうか?
TrackBack URL :
Comments (4)
はじめまして。
いつも興味深く拝見しております。
こちらの関数は具体的にどの文字列が無効化対象でしょうか?
#なんとなく、以下かなぁ?くらいしか分かりませんでした。
#・PHPが判断するHTMLタグ
#・半角&
#・半角”
#・半角’
#・半角<
#・半角>
#・javascript:
コメントありがとうございます!
タグを取り除いた後、
ご指摘の通り
「&」「>」「<」「"」「’」をサニタイジングしてます。
最後に、
URL内の「javascript:」を削除してます。
※style属性のexpression等は除去できません。
最初はhtmlentitiesを使ってましたが
使用上htmlspecialcharsに変更しました。
あと、文字列としてタグが残るのが
使用上困る為、striptagsを使用してます。
引数等で指定できるようにしておくと便利かもしれませんね~
URL内の「javascript:」は
引数次第で取り除くようになってます
この関数を参考にさせて頂こうと思います。
ご丁寧にありがとうございました。