PHPとmysqlで質問です。


現在、PHPでつくったページがありまして、
【セキュリティー対策↓】
function h($value) {
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

【出力↓】
<p><?php echo h($post['sample']); ?></p>

↑mysqlのvarchar(1000)が出力されます。

【質問】
リンク先などを↑の文で出力するときどのように対応を一般的にとるのでしょうか?
htmlspecialcharsがあるのでタグが出力されません。
かといって、htmlspecialcharsを取るとセキュリティー上よくないと認識しています。

一般的にmysdqlのデータからタグを出力するときどのような対応をとるかご教授いただきたいです!

情報が足りない場合は、ご質問いただければすぐに補足欄に載せたいと思います。
何卒、宜しくお願いします。

回答の条件
  • 1人10回まで
  • 登録:
  • 終了:2014/05/31 12:14:49
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答2件)

id:pogpi No.1

回答回数428ベストアンサー獲得回数59

データベースにデータを格納する時点で、タグを取り除いておくべきだと思います。

id:TransFreeBSD No.2

回答回数668ベストアンサー獲得回数268

ポイント100pt

よくあるのは次の三種でしょうか。
はてなはすべて実装してます。

1. URLがあればリンクにする

文中にURLがあるとそれをリンクにする方法です。
この方法が採用されているところは多いと思います。
実装には次の二つがあると思います。

  1. ぽけっとしすてむさんの様に、一旦htmlspecialcharsで処理した後、preg_replaceなどで戻す方法
  2. preg_splitなどでURLとそれ以外に分割して、それぞれ処理する方法

下記の様に探せば1の方法が色々出てきます。
https://www.google.co.jp/search?q=url%E3%83%AA%E3%83%B3%E3%82%AF%E5%8C%96+php
それぞれ若干違ったりしますが、httpsやftpの対応とか記号等でどれを許容するかとかあります。厳密に言えばもうちょっと複雑になったりします。まあ、下記でよいでしょうかね?(あんまりちゃんとチェックしてないです)
http://www.phppro.jp/qa/688
#htmlspecialcharsかけた後に上記をすればOKだと思います。
あと、下記に長いURLがあったりしますが、こういう場合に後ろを省略するとか、ドメイン部分を強調するとか、そういう処理もすることがあります。
#それも含め定番がどっかにないですかね?>誰ともなく

2. 独自もしくはよくある書式、記法を使う

はてなははてな記法を持っています。これはwiki由来で、pukiwikiやmediawikiなどもそれぞれ記法を持っています。
最近はgitなどmarkdownも多くなってる気がします。
他に古くから海外の掲示板で使われていたものにbbcodeがあります(spamがよく使っています)。
#phpだと持ってますね http://www.php.net/manual/ja/ref.bbcode.php
実装方法は必ずしもpreg_splitを使うというわけではありませんが、基本は上記1の2と同じで字句解析を行って一旦トークンに分割して、それを順次処理していく事が多いと思います。

3. 特定のタグや属性だけを使える様にする

はてなとかmediawikiとかもhtmlが書けますが、特定のタグや属性だけ使えるようになっています。
これも基本は上記2と同じで、独自記法の代わりにhtmlをパースして処理していきます。
ただ、独自記法と違い、htmlは複雑で様々な属性があります。またstyle属性を許すと表現の幅が広がりますが、同時にhtmlだけでなくcssの処理も入ってきて複雑になりがちで、思わぬ穴もあきやすいです。
参考:
http://blog.kentarok.org/entry/20070804/1186154750
http://hatenadiary.g.hatena.ne.jp/keyword/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AA%E3%83%BCXSS%E5%AF%BE%E7%AD%96?kid=247

番外:上記に加えて出力時に検査する

最後に保険として変なタグや属性、タグの綴じ忘れ等がないかチェックするライブラリなどもあったと思います。

---

セキュリティと利便性はトレードオフになりがちです。
高機能にすると複雑になりセキュリティホールがあく可能性も増えます。
あと、実装の手間も。

1はまあ大したものではないので独自実装しても良いでしょう。
ただ、これを拡張して2になっていくと言うのはありがちですが、一度始めると過去のデータがあるので途中で変更が効きません。
1以上をやるのであればこなれた既存の記法、よくメンテナンスされたライブラリを採用すると、セキュリティ的にも手間的にもお得です。
3の場合、独自実装なら間違いなく穴が開くといって過言ではないのでライブラリ必須です。

#書いてるうちにどんどん長くなっちゃった。

他1件のコメントを見る
id:akakak

A02の質問でございます。

2014/05/31 12:14:06
id:TransFreeBSD

たぶんその認識であってると思います。

2014/05/31 18:29:22
  • id:psne
    基本は「出力時」に処理します。
    htmlspecialcharsにて処理された文字列に、例外として戻したいタグをpreg_replaceやstr_replaceで戻せば良いのではないでしょうか。
    ※SQLに対しては入力時ですね。
    個人的にはタグとして出力したいデータのみ持つようにして、後からタグとして生成したいところです。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません