アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。PHP(&mySQL)初心者です。
基本的な事かもしれませんが、自分で調べてもよくわからないので、どなたかご教示いただけないでしょうか。

下記のような2つのファンクションが定義されているとします。

<?php
function h($value) {
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
?>

<?php
function dec($hd_value) {
return htmlspecialchars_decode($hd_value);
}
?>

フォームから受け取った文字列を「h()」で処理した上で、DB(mySQL)に格納し、ブラウザで表示するときは、DBから受け取った文字列を「dec()」で元に戻しています。

通常は、これで問題ないのですが、文字列に「<br/>」のようなHTMLタグと「<jpSampleTag=lnum1>」のような独自のタグ(のようなもの)が混在してた場合、ブラウザでの表示時に「<jpSampleTag=lnum1>」が無視されて表示されません。

一応、「dec(h($value))」のように、入れ子にすると「<jpSampleTag=lnum1>」の部分も表示されることがわかったのですが、今度はhtmlのタグのヤマ括弧まで「&lt;」のようなhtmlエンティティに変換されてしまい、改行などができずに困っています。

htmlタグだけを復元する方法はないものでしょうか?

あるいは、DBに文字列を格納する段階で、なにか別の処理をした方がいいのでしょうか。

どなたか良い方法をご存知の方がいらっしゃいましたら、ご教示いただけないでしょうか。
よろしくお願いします。

A 回答 (7件)

根本的なところから間違っています。



まず、formから入力されたHTMLタグを(DB経由するかどうかさておき)、HTMLとして出力するというのは普通のプログラムではやらない、かなりセンシティブなことで、そのへんで見かけるセキュリティの説明ではそういうプログラムを想定して書いてません。

まず、普通のプログラム、「フォームからテキストデータを入力してDBに格納し、また、DBから読んだデータを(HTMLタグで無い)テキストデータとしてHTMLの中に組み込んで表示する」場合は、

1.MySQLに格納する時点で、mysql_real_escape_string ないし同等の機能でSQLインジェクション攻撃を防ぐ
2.HTML中にデータとして出力する時点で、htmlspecialchars をつかってクロスサイトスクリプティング攻撃を防ぐ

この2点だけです。

で、あなたのしたいように、HTMLタグとして出力したいのであれば、2の代わりに、
2’.出力しようとしているデータに対して、HTMLタグの構文解析を(ブラウザ並に)厳密に行って、安全なタグのみ出力し、危険なタグがあればエラーにする(エラーを早期に出したければDB格納前にも両方で行う)

というちょっと初心者には不可能と思えることにチャレンジする必要があります。
    • good
    • 0
この回答へのお礼

セキュリティ上の注意点をわかりやすく要約してしていただき、ありがとうございました。

出力時に安全なタグのみ検出して、HTMLタグとして利用するための簡便な方法がないということが確認できただけでも収穫です。

初心者が知らないだけで、実は簡単な方法があるのでは、と心配していました。

お礼日時:2011/10/29 12:22

No6です。



>初心者が知らないだけで、実は簡単な方法があるのでは、と心配していました。

そうですね。正規表現とかで簡便にやろうとすると必ず穴が残りそうです。

安全にやるには、HTMLを解析するライブラリ( http://www.php.net/manual/ja/refs.xml.php ) を使うのが良いかと。「PHP HTML解析」で検索するとサンプルとか見つかると思います。

タグを順番に見てって、使ってよい物だけ判断。
「これとこれはだめ。他はよい」というブラックリスト方式じゃ無くて、「これとこれだけはよい。他は全部だめ」という方式にしましょう。
タグ名だけじゃ無くて属性名にもおなじく、「このタグの場合は、これとこれの属性だけはよい。他は全部だめ」と。
    • good
    • 0
この回答へのお礼

度々のアドヴァイスありがとうございます。

PHP(&mySQL)そのものに慣れたら、ライブラリにも徐々に手をつけていこうかと思っていました。
これがよいきっかけになるかも知れません。

でも、そのまえにクラスの概念とかを勉強しておかなければならないような気が…
いままでVBAしか知らなかったので、そこらへんがよくわかっていません。
あれも、一応オブジェクト指向の言語のはずなんですが。

お礼日時:2011/10/29 21:10

>一応、「dec(h($value))」のように、入れ子にすると


無意味ですね。
dec(h($value))は$valueを何も処理せずに、表示させたのとまったく同じです。
無駄に処理して、レスポンスを遅くしている分タチが悪い。


質問を読んでみると、何がしたいのかってのが、固まってないように思えますね。
ユーザーに入力欄(textarea?)を提供して、取得したデータをDBに格納、そしてそれを表示させたいってのは判ります。

その際の仕様として、<br />等のHTMLタグを入力していた場合、表示の際には反映させたいという事なのでしょうが。

その場合には問題があって、
『<script>~</script>』
あるいは
『<form action="別のサイト">~</form>』
などが入力されるなど、いわゆるクロスサイトスクリプティング(XSS)と呼ばれる攻撃の標的になる可能性があります。

これが、「表示時点で入力された改行を反映させたい」というだけなら、nl2brというPHP関数が使えます。

たとえば<font color=#FFFFFF>ホゲホゲ</font>
というタグも【安全に】使いたい、というならそれなりに複雑に構文解析する関数を自作しなければなりません。
(というか、結構あちこちで転がってますが)

とりあえず、XSS対策として入力されたタグはすべてhtmlエンティティに変換する、表示の際にnl2brで改行コードだけは<br />に変換して改行させる、という仕様をお奨めします。

参考URL:http://ja.wikipedia.org/wiki/クロスサイトスクリプティング
    • good
    • 0
この回答へのお礼

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

初心者は、「何ができるのか」ということばかりに目が行ってしまいがちなのですが、セキュリティについても一通りのことは把握していなればならないということがわかりました。

今のところは、無理をせず、改行コードだけに対応するようにしようかと思います。

お礼日時:2011/10/29 12:28

もし文意が、


独自のタグ<jpSampleTag=lnum1>だけをこの見た目の通りにブラウザに表示したい、
ということであれば、
独自のタグ<jpSampleTag=lnum1>だけhtmlspecialchars()を通してからブラウザ出力するようにすれば良いかと思います
    • good
    • 0
この回答へのお礼

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

この独自タグ(のようなもの)ですが、非常に種類がたくさんある上に、イコールやかっこの後ろの部分は変数になっていて、これも50種類以上のあります。

更に、タグが入れ子になっている場合もあり(例えば「<jpSampleTag(<aaBranch=<bName(num1)>>,2,3)>」こんな感じです)、タグ部分だけを抽出するのは非常に困難かと思われます。

できたとしてもレスポンスが遅くなるのでは、と心配になりますが、そこは初心者にはよくわからない部分です。

いずれにせよ、「独自タグの部分だけ抽出して処理」という手法は、今の私には手におえそうにありません。

お礼日時:2011/10/29 21:26

ANo.2です



ANo.1さんの回答を読んで、やっと「やりたいこと」が分かってきました(汗)。いわゆるBBコードみたいなものを想定しているということでいいんでしょうかね。

であれば、ANo.1さんが書かれたように「<>」でなく(一般的なBBコードが採用しているように)「[]」などを使うべきです。

http://ja.wikipedia.org/wiki/BB%E3%82%B3%E3%83%B …
    • good
    • 0

DBに格納する段階でhtmlspecialcharsを通す必要はありません。

mysql_real_escape_stringを通せばいいです。

htmlspecialcharsはその内容を「htmlソースの中に」表示させるなど、あくまでもhtml内に表示するときに通すものです。なので(htmlソースとして作成したものを保存・表示するケースなど)ブラウザに「htmlとして処理してもらいたい」ケースでは使いません。


が、そもそも「フォームから受け取った文字列」を、そのままhtmlとして扱わせるのは如何なものでしょう。管理画面などから(じゅうぶんな認証を通してから)POSTされるのですかね?そうでないと相当に危ないことになりそうですが・・・

この回答への補足

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

入門書に書いてあったのを、真似しながらやっていたのですが、どこかで「htmlspecialchars」と 「mysql_real_escape_string」を間違えて覚えてしまったようです。

一応、下記のような事をやろうとしていたのですが、「2」のセキュリティ上の処理は「mysql_real_escape_string」だったんですね。

それで、作り直してどうなるかやってみます。

1. 「<jpSampleTag=lnum1>ほにゃ<br/>ほにゃ。」という文字列をフォームから受け取る
2. htmlspecialcharsで(セキュリティ上の)処理したものをDBに登録する
3. 上記で登録した文字列をDBから取得する
4. htmlspecialchars_decodeで、ヤマ括弧などをもとに戻してブラウザに表示する

補足日時:2011/10/28 16:35
    • good
    • 0

独自タグに「<>」を使うのをやめるのがベストです。

この回答への補足

早速のご回答、ありがとうございます。

独自タグの書式は、勝手に自分では変えられないのです。
なんとかならないもんでしょうか。

補足日時:2011/10/28 16:38
    • good
    • 0

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