こんにちは。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のタグのヤマ括弧まで「<」のようなhtmlエンティティに変換されてしまい、改行などができずに困っています。
htmlタグだけを復元する方法はないものでしょうか?
あるいは、DBに文字列を格納する段階で、なにか別の処理をした方がいいのでしょうか。
どなたか良い方法をご存知の方がいらっしゃいましたら、ご教示いただけないでしょうか。
よろしくお願いします。
No.6ベストアンサー
- 回答日時:
根本的なところから間違っています。
まず、formから入力されたHTMLタグを(DB経由するかどうかさておき)、HTMLとして出力するというのは普通のプログラムではやらない、かなりセンシティブなことで、そのへんで見かけるセキュリティの説明ではそういうプログラムを想定して書いてません。
まず、普通のプログラム、「フォームからテキストデータを入力してDBに格納し、また、DBから読んだデータを(HTMLタグで無い)テキストデータとしてHTMLの中に組み込んで表示する」場合は、
1.MySQLに格納する時点で、mysql_real_escape_string ないし同等の機能でSQLインジェクション攻撃を防ぐ
2.HTML中にデータとして出力する時点で、htmlspecialchars をつかってクロスサイトスクリプティング攻撃を防ぐ
この2点だけです。
で、あなたのしたいように、HTMLタグとして出力したいのであれば、2の代わりに、
2’.出力しようとしているデータに対して、HTMLタグの構文解析を(ブラウザ並に)厳密に行って、安全なタグのみ出力し、危険なタグがあればエラーにする(エラーを早期に出したければDB格納前にも両方で行う)
というちょっと初心者には不可能と思えることにチャレンジする必要があります。
セキュリティ上の注意点をわかりやすく要約してしていただき、ありがとうございました。
出力時に安全なタグのみ検出して、HTMLタグとして利用するための簡便な方法がないということが確認できただけでも収穫です。
初心者が知らないだけで、実は簡単な方法があるのでは、と心配していました。
No.7
- 回答日時:
No6です。
>初心者が知らないだけで、実は簡単な方法があるのでは、と心配していました。
そうですね。正規表現とかで簡便にやろうとすると必ず穴が残りそうです。
安全にやるには、HTMLを解析するライブラリ( http://www.php.net/manual/ja/refs.xml.php ) を使うのが良いかと。「PHP HTML解析」で検索するとサンプルとか見つかると思います。
タグを順番に見てって、使ってよい物だけ判断。
「これとこれはだめ。他はよい」というブラックリスト方式じゃ無くて、「これとこれだけはよい。他は全部だめ」という方式にしましょう。
タグ名だけじゃ無くて属性名にもおなじく、「このタグの場合は、これとこれの属性だけはよい。他は全部だめ」と。
度々のアドヴァイスありがとうございます。
PHP(&mySQL)そのものに慣れたら、ライブラリにも徐々に手をつけていこうかと思っていました。
これがよいきっかけになるかも知れません。
でも、そのまえにクラスの概念とかを勉強しておかなければならないような気が…
いままでVBAしか知らなかったので、そこらへんがよくわかっていません。
あれも、一応オブジェクト指向の言語のはずなんですが。
No.5
- 回答日時:
>一応、「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/クロスサイトスクリプティング
ご回答ありがとうございます。
初心者は、「何ができるのか」ということばかりに目が行ってしまいがちなのですが、セキュリティについても一通りのことは把握していなればならないということがわかりました。
今のところは、無理をせず、改行コードだけに対応するようにしようかと思います。
No.4
- 回答日時:
もし文意が、
独自のタグ<jpSampleTag=lnum1>だけをこの見た目の通りにブラウザに表示したい、
ということであれば、
独自のタグ<jpSampleTag=lnum1>だけhtmlspecialchars()を通してからブラウザ出力するようにすれば良いかと思います
ご回答ありがとうございます。
この独自タグ(のようなもの)ですが、非常に種類がたくさんある上に、イコールやかっこの後ろの部分は変数になっていて、これも50種類以上のあります。
更に、タグが入れ子になっている場合もあり(例えば「<jpSampleTag(<aaBranch=<bName(num1)>>,2,3)>」こんな感じです)、タグ部分だけを抽出するのは非常に困難かと思われます。
できたとしてもレスポンスが遅くなるのでは、と心配になりますが、そこは初心者にはよくわからない部分です。
いずれにせよ、「独自タグの部分だけ抽出して処理」という手法は、今の私には手におえそうにありません。
No.3
- 回答日時:
ANo.2です
ANo.1さんの回答を読んで、やっと「やりたいこと」が分かってきました(汗)。いわゆるBBコードみたいなものを想定しているということでいいんでしょうかね。
であれば、ANo.1さんが書かれたように「<>」でなく(一般的なBBコードが採用しているように)「[]」などを使うべきです。
・http://ja.wikipedia.org/wiki/BB%E3%82%B3%E3%83%B …
No.2
- 回答日時:
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で、ヤマ括弧などをもとに戻してブラウザに表示する
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- Visual Basic(VBA) VBAにてメール作成した際、一部指定箇所のみ赤文字にしたいです。 下記の内容ですと作成されたメール本 1 2022/04/27 13:31
- PHP 入力した部分を表示させたまま(保持)するにはどうすれば良いでしょうか? 1 2023/01/25 11:14
- JavaScript ①入力フォーム→②確認表示画面→③送信完了画面のコードを書いているのです、 入力フォームから受け取っ 2 2022/05/10 16:45
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- JavaScript javascriptのちょっとした動作不良(原因は突き止めたのですが) 1 2023/06/15 19:58
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- JavaScript セレクトボックスで配列を呼び出したい。 1 2022/07/08 20:14
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
PHP Webページのタイトルを取得...
-
reuterの記事をbeautiful.soup....
-
echoで画像を呼び出すことがで...
-
正規表現でタグの置換をしたい...
-
[php][正規表現]タグ以外を削除...
-
VBAのコマンドボタンの文字列の...
-
ソースコードの1行が長いとき...
-
エスケープ文字の復帰(¥r)と...
-
文字の入力で横バー上段、中断...
-
メッセージボックスで1025文字...
-
JAVA System.out.println の ...
-
改行について
-
COBOLの改行
-
Excel関数「COUNTIF」で”文字”...
-
記号は半角と全角どちらがよい...
-
文字列型変数に1024を超えた文...
-
C# DataGridViewのセルを改行禁...
-
ダブルコーテーション(
-
ファイルから読み取った改行文...
-
delphi でのコード上でTab を入...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
reuterの記事をbeautiful.soup....
-
JSFタグのfタグとは
-
正規表現で複数行に渡る範囲を...
-
変数にHTMLを代入する場合
-
phpの正規表現でstyle="●●"を削...
-
Nvuで作成したhtmlをコピペして...
-
正規表現で指定範囲すべて除去...
-
正規表現でタグの置換をしたい...
-
Strutsでリンクを動的に生成したい
-
自分でタグ打ちして作ったペー...
-
php正規表現 相対パス→絶対パス
-
ASP.NET(C#)とhtmlの#include
-
PHPの正規表現でHTMLタグの内容...
-
csobjというタグについて
-
VBSでのhtmlタグ要素名の置換
-
htmlタグ間の特定文字置換
-
URLの連続アクセス
-
HTMLファイルの書き換え
-
htmlspecialchars関数を使いな...
-
javascriptの正規表現でhtmlか...
おすすめ情報