プロが教える店舗&オフィスのセキュリティ対策術

PHP+MySQLで掲示板のようなものを作成しています。
投稿の際、HTML形式が利用できるようにしたいと思っています。

概ね完成したのですが、HTML形式で投稿できるということは、PHPやjavascriptのコードを投稿すれば、それらの機能も利用されてしまうことに気がつきました。

たとえば、投稿フォームから
<?php
//悪意のあるコード
?>
と入力すれば、悪意のあるコードが実行されてしまいます。

そこで、投稿された部分のPHPやjavascriptだけを無効にする方法はないのでしょうか?
あるいは$や{や;など、PHPやjavascriptなどで使用する記号を受け付けないようにすればいいのでしょうか?

うまく説明できないので詳細は割愛しますが、「HTMLでの投稿をやめる」という選択ができないので悩んでいます。

どのような対処をすればいいのか、ご教授願います。
説明不足な点がありましたら、ご指摘いただければ補足します。
よろしくお願いいたします。

A 回答 (8件)

属性に関してはチェックせず、タグそのものが許可されていれば、そのまま残ります。

したがって、<button>などで、onClick属性とかにjavascriptのコードを入れられると、危ないですね。
    • good
    • 0
この回答へのお礼

思い通りのことが実現できました!!
ありがとうございました。
buttonなどは許可せず、divやpやspanなど、体裁を整えるものだけを許可したいと思います。

お礼日時:2008/12/05 17:56

HTML Purifier というライブラリが、ほとんど解決してくれます。



<script>はもちろん、属性(onclickなど)もちゃんと解析して排除してくれます。
セキュリティというものに完璧はないので、おそらく抜け道は存在するはずです。ただ自分で小手先の知識でやるよりは、こういう専門に作られた方が安全だとは思います。

他の方がおっしゃってるように、PHP側でeval()しない限りPHPコードは実行されないのでご安心を。

参考URL:http://htmlpurifier.org/
    • good
    • 0
この回答へのお礼

ありがとうございます。
便利なライブラリがたくさん出回っていてびっくりします。

前にも書きましたが、PHPの勉強を兼ねておりますので、自分で考えながら作ってみたいと思います。

お礼日時:2009/01/13 01:19

ググったらこんなのはありましたね。



function escapeJavascript_r($deep=false){
$search = array ('@<script[^>]*?>.*?</script>@si','@([\r\n])[\s]+@si');
$replace = array ('','');
if ($deep) {
$search[] = '/[\s]+on[\w]{2,15}=[\"|\'][^>]*?[\"|\']/im';
$replace[] = '';
}
return preg_replace($search, $replace, "".$this->v."");
}
    • good
    • 0
この回答へのお礼

再度ご回答ありがとうございます。
残念ながら、複雑すぎて今の私には理解不能です。(^^ゞ

今回は、strip_tagsを使って必要なものだけを許可する、という方針で進めようと思っています。
ありがとうございました。

お礼日時:2008/12/07 00:33

適当に書いてみましたが動作の保証はありません。


XSSについて理解が漠然としすぎな感もしますし
もしお仕事なら htmlspecialchars 使っとくのが無難な気がします。

function escapeJavaScript($html)
{
$html = preg_replace('/((?:\G|<)[^>]*?)(javascript:)/i', '\\1_\\2', $html);
$html = preg_replace('/((?:\G|<)[^>]*?)([^a-zA-Z])(on[a-zA-Z]+)/i', '\\1\\2_\\3', $html);
$html = preg_replace('/<(script)/i', '&lt;\\1', $html);
return $html;
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
XSS(クロスサイトスクリプティング)というのですね。(^^ゞ
これをキーワードに探してみれば、よりよい方法がみつかるかもしれません。

ソースまで作っていただきありがとうございました。

ちなみにPHPの勉強をかねて、趣味でやってます。(^^ゞ

お礼日時:2008/12/07 00:31

お礼の中で、気になる点がいくつかあったので書かせて貰います。


<?php
$hoge = '<?php echo"hogehoge";?>';
echo $hoge;
?>
上のPHPコードを実行すると、どうなるでしょう?

2行目のecho $hoge;はサーバー上で実行されますが、その変数$hogeに格納されている<?php echo"hogehoge";?>は、ただの文字列です。
そのままブラウザに渡されますが、ブラウザ上ではPHPは動作しません。
HTML内にただ<?php echo"hogehoge";?>が残るだけです(表示はされず、コメントとして扱われると思います)。

$hogeに入れる値は、ファイルやDBから取得した場合でも同様です。

通常の掲示板の作り方では、ユーザーがPHPコードらしき文字列を投稿することはできますが、その文字列をPHPコードとして動かすことはできません。
わざわざ、(少々苦心した上で)ユーザーが投稿した文字列をPHPコードとして動作するように作り込みすることは可能です。
可能ですが、わざわざそんなことします?
普通に作れば、ユーザーの投稿した文字列がPHPコードとして動作することはありません。

というのが、No.4の方の最後の2行の意味ですね。

ま、strip_tagsで<?php ~ ?>も削除でしょうけど。

mb_eregiで、大文字小文字を区別しないマッチもできますよ。
http://jp.php.net/manual/ja/function.mb-eregi.php


他には、いくつかHTMLタグを使った嫌がらせを紹介。
開始タグのみを書いて終了タグを書かずに、以降のレイアウトを崩す嫌がらせ。
<font size=100> 大きいサイズを指定してレイアウトを崩す
<font color=#FFFFFF> 背景色と同一の色で書いて、文字を見えなくする
縦横のサイズを大きく指定して、レイアウトを崩す嫌がらせ
<div style="width:1000px;"></div> 幅指定を大きくして、レイアウトを崩す
<p><p><p><p><p><p><p><p><p><p><p><p><p><p><p>たくさん改行することで、無駄に縦に長い空白を作成する。

HTMLタグを許可するって事は、色々なHTMLタグを使った嫌がらせにも対応する必要があるって事で御注意。
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございます。
説明不足&知識不足でうまく伝わらない部分もあると思いますがご容赦ください。

先ほど、投稿フォームから
<?php
$hoge = '<?php echo"hogehoge";?>';
echo $hoge;
?>
を送信したところ、ブラウザには何も表示されませんでした。
ソースを見れば4行のコードがそのまま記述されていますが、ブラウザには表示されません。
このコードが実行されてしまうかもしれないと、私が勘違いをしていたようです。(^^ゞ

PHPやjavascriptなどは、HTML内に埋め込んで動作させることができるので、PHPなどを含むHTMLが投稿された記事を表示させると、PHPなどが実行されてしまう・・・と思っていました。

> 普通に作れば、ユーザーの投稿した文字列がPHPコードとして動作することはありません。
たぶん、普通に作っているはずです・・・。(^^ゞ

後半に記述されたような「消去すれば解決できる嫌がらせ」は気にしていません。
PHPなどが実行され、DBのデータを抜き取られたり、公開ディレクトリより上に置いてある設定ファイルを覗かれたり、といった情報漏洩や、無限ループを仕掛けられてサーバーに高付加をかけるといった、取り返しのつかない事態を避けたいと考えています。

実ファイルに書き込んだコードと、スクリプトで自動生成したコードでは挙動が違うことがわかりました。
私が気にしていた「悪意のあるコード」は実行されないようですね。

ありがとうございました。

お礼日時:2008/12/06 00:45

入力が予定されるHTMLの内容にもよるかと思います。


日記投稿レベルであればJavaScriptのダイアログなどを利用して
独自のフォーマットで保存してやるとか。
リンク [link=http://domain.dom/]サイト名[/link]
文字色 [color=red]文字[/color]

様々なHTMLが入力されるのであれば、
<script></script>
<* on[a-zA-Z] ..
<a href="javascript: ..
あたりを正規表現なりで除去する必要があります。

もしくは上記のような記述が見受けられれば
「悪意のあるコードが記述されている可能性があります。」
と1回警告を出したのち自己責任で見てもらうとか・・・

> <?php 悪意のあるコード ?>
print などで出力する分には実行されませんが、ファイルを書き出して
phpで走らせたりphpのコードとして評価させるのでしょうか?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

独自フォーマットも考えましたが、今の自分の知識レベルでは難しいので断念しました。(^^ゞ
また、<Script>や<sCrIpT>などと大文字小文字を混在させるパターンや、<script >などと余分なスペースを入れるパターンなど、工夫をすれば無限大の可能性があると思い、現実的ではないような気がします。

最後の二行の意味がわかりませんが、ユーザーがPHPコードを投稿できるということはとんでもないことだと思いました。
一番怖いのは、公開ディレクトリより上の階層に入り込まれたり、DBを覗かれたりする可能性も出てくることです。
説明不足でもうしわけありません。

お礼日時:2008/12/05 18:05

umotaさんの回答だと、HTMLも禁止されてしまいますね。



strip_tagsという関数があります。
これは、許可するタグ以外をすべて消します。
問題は、許可するタグをすべて列挙する必要があることです。

たとえば、<p>、<strong>、<font>だけを許すのでしたら、
$strippedString = strip_tags($inputString, '<p><strong><font>');
のように書きます。

HTMLのタグもフォームなど危険なものもありますので、記述が面倒かもしれませんが、この方法で許可するものだけを残すことをお勧めします。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
なるほど。便利な関数があるものですね。

下記のようにclassやidを追加したタグはどうなるのでしょうか?
<p class="midashi">


strip_tagsについて調べてテストしてみようと思います。

お礼日時:2008/12/05 15:58

phpを使っているならば htmlentities 関数で変換する。


例えば "<?php" は "&lt;?php" となるので実行できません。

参考URL:http://jp2.php.net/manual/ja/function.htmlentiti …
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
htmlentitiesを通すとHTMLタグも使えなくなるので、残念ながら今回の主旨からはずれてしまうんです・・・。

お礼日時:2008/12/05 15:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!