電子書籍の厳選無料作品が豊富!

こんにちは。PHPとMySQLで自作ブログを作ろうと試みているのですが、
セキュリティを意識した中で、HTMLタグの取り扱いに困っております。

プログラム全体の流れとしては、

記事投稿ページ→MySQLに保存→ブログ記事として出力

といった感じです。

例えば、記事投稿ページの<textarea>の中で、
<b>テストテスト</b>といった文があったとします。

XSSを防ぐために、htmlspecialchars()でエスケープすると、
MySQLには、&lt;b&gt;テストテスト&lt;/b&gt; と保存されます。

MySQLから記事に出力したときに、太字となった「テストテスト」ではなく、
「<b>テストテスト</b>」とそのまま表示されてしまいます。

記事の出力時に、html_entity_decode()で戻してやればいいかとも思いましたが、
それでは、そもそもXSSを防げない気がします。

一般のブログサービスでは、どうやってデータベースにHTMLを保存しているのでしょうか?

解決するいい方法があればどなたか教えてください。

A 回答 (3件)

様々な方法がありますが、PHPに限らず一般的には次のような手順を踏みます。



(1) まず、ユーザーにどのようなHTMLを使わせたいかを厳密に正確に決めます。たとえば、太字を使わせたいので<b>だけを許可するのであればそのように定義します。(逆に禁止タグを決める方法もありますが、相当のスキルが無いと危険なのでよした方がよいでしょう)

(2) ユーザーの投稿テキストを受け取ったら、文字列のどこに(今の例だと)<b>と</b>があるのかを正確に把握します。そして「ここに"<b>"があるよ」とマーキングしておきます。他のタグは残すも良し、削除するも良しです。この処理はDBにテキストを格納する前でも、DBの内容を表示する直前でもいいです。

(3) 最終的に投稿を画面に表示する時、<b>と</b>の位置はマーキングで分かっていますから、それらはHTMLタグとして表示します。そしてそれ以外の部分は、(PHPの場合なら)htmlspecialchars()でエスケープして表示します。

このようにすれば、必要なタグだけをHTMLとして表示し、それ以外の部分は適切にXSSを防ぐことが出来るというわけです。ちょっと難しいかもしれませんがお分かりいただけるでしょうか?

とはいえ、これを自分でキッチリ開発するのはかなり骨が折れます。特にいろんな種類のHTMLを書かせたい場合は挑戦してもセキュリティホールを作ってしまう可能性が高いでしょう。ライブラリを探した方が良いです。さて、実は私はもう長い間PHPを使っていないため、ここからはGoogle検索結果だけを頼りに書いてしまいますが、以下のライブラリは広く使われていて信頼できるようです。

HTML Purifier
http://htmlpurifier.org/
http://phpspot.org/blog/archives/2007/03/htmlxss …

また、HTMLの代わりにHTMLに似た別の言語を使って対応するというのは、英語圏の掲示板/ブログソフトウェアではわりと一般的なようですね。これはPEARにもライブラリがあるようです。

BBCode
http://pear.php.net/HTML_BBCodeParser
http://ja.wikipedia.org/wiki/BB%E3%82%B3%E3%83%B …
    • good
    • 0
この回答へのお礼

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

なるほど、ホワイトリストのような物を作って、その中で決められたタグだけをマーキングして、その他をエスケープ処理するということですね。
確かにそれならXSSも防げる上に、使いたいHTMLタグも実行できますね!
これは考えませんでした。目からウロコです(涙)

ちなみにマーキングというと、例えば<b>を(b)などに変換しておけばいいのでしょうか?

ご紹介いただいたライブラリはすごいですね!
無理に自作で作るよりも、こうした便利なライブラリを使いこなせるようになる方が
結局はいいかもしれませんね。試してみます!

お礼日時:2010/05/13 00:08

>> 一般のブログサービスでは、どうやってデータベースにHTMLを保存しているのでしょうか?


>> 解決するいい方法があればどなたか教えてください。

既に求める回答は得られているようですが、いくつか紹介だけ。。

単にブログといっても、誰に書き込み権限を与えるかに依ります。
本文への書き込みを管理者にしか与えていないものでは、特にHTMLのサニタイジングを
施していない物も少なくありません。
不特定多数に書き込み権限がある場合や書き込み者が不明なコメント、トラックバックなどは当然
サニタイジングを施します。

不特定多数の人に書き込みを許可している物の代表として、掲示板などが有りますが
いたずら防止も兼ねて、BBcode(Bulletin Board Code)を使う場合も有ります。
http://ja.wikipedia.org/wiki/BB%E3%82%B3%E3%83%B …
htmlタグはすべてエスケープ処理してしまい、BBcodeのうち
許されたタグだけは表示時にhtmlタグに変換するという方法です。
オープンソースで開発されている掲示板などに多く使われています。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
BBcode、Wikipediaの説明をよく読んでみましたが、
大変勉強になりました。

確かに掲示板はブログよりもさらに危険そうですし、
「HTMLタグをまず全てエスケープ処理してしまい、
許可したタグだけをHTMLタグに再変換する」
というのは、非常に効率的な方法ですね。

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

お礼日時:2010/05/15 02:28

問題箇所の切り分けが大切だと思います


XSS対策が必要なのは表示の時でDB登録の時ではない
ということ。
DB登録の時に必要なのはSQLインジェクションであってクロスサイトスクリプトじゃない
って事。
簡単に言えばDB登録の時は
SQLインジェクション対策を施した文字列を登録して
表示するときはXSS対策した
HTMLを表示してあげれば良いと思いますが。
No1さんの言うとおりXSS対策すべき部分・XSS対策すべきタグの
選定・切分けもいりますし結構危険ですよ。
    • good
    • 0
この回答へのお礼

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

確かに、XSS対策は、DBから表示するときでいいような気がします。
そう切り分けると、余計な処理が省けそうですね。
ご指摘ありがとうございます。

選定・切り分けは大変そうなので、
やはりライブラリに頼るのが一番安全で確実な気がしてきました。

お礼日時:2010/05/13 00:17

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