• 締切済み

関数htmlspecialcharsと関数sqlite_escape_stringの扱い方

いつもお世話になっております。 環境:PHP5/SQLite3 関数 htmlspecialchars 関数 sqlite_escape_string サイトのセキュリティを考慮し、 上記2関数をなんとなく利用しているのですが、 この「なんとなく」を卒業したいと思っています。 アドバイスして頂きたい内容を書きますと、下記のようになります。 ---------------------------------------- 上記の2関数のうまい使い分けと言いますか、 「こういう時にはこっち!ああいう時には、あっち! んでもって、 これこれこういう時には、どっちも使え!」 ---------------------------------------- というようなアドバイスを期待しております。 DBのクエリ文に使用しないような場合でも、 sqlite_escape_string関数で浄化しておいて損はないように思うのですが、 そういう使い方だと何か問題はありますでしょうか。 (無視できるような小さな問題であれば、気にしないつもりです。) 浄化能力を包含関係で考えると、 htmlspecialchars ⊂ sqlite_escape_string と私は考えていますが、違いますでしょうか。 それと、これらの関数の、 使うタイミングと使う際の注意事項 についても、あれこれお話し頂けると嬉しいです。 具体例(コードorシチュエーション)を示して頂けると助かります。 他にも、こんな関数でも浄化できます、 というようなアドバイスも大歓迎です。 と、とても抽象的な質問文になりましたが、、、 どなたか、「ワンポイントアドバイス」でも結構ですので、 どうか宜しくお願い致します。

  • march4
  • お礼率83% (628/754)
  • PHP
  • 回答数2
  • ありがとう数4

みんなの回答

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

そこまで考えられたら問題ないと思いますよ 一つ付け加えるならhtmlspecialchars は不可逆変換なので変換したら元には戻せません("<<"も"<&lt;"も同じ結果になるので多対1の変換になります) 自分の場合はこういう不可逆変換は処理が必要になる直前に行うようにしています(いつ仕様が変わって元データが必要になっても困らないように)

march4
質問者

お礼

htmlspecialchars()は処理後、 "<<"も"<&lt;"も同じ結果になる多対1の不可逆変換なので変換したら元には戻せない というアドバイス、ありがとうございます。 私にはない視点でしたので大変参考になりました。 >自分の場合はこういう不可逆変換は処理が必要になる直前に行うようにしています こちらもスクリプト設計の参考にさせて頂きます。^^

  • UmJammer
  • ベストアンサー率58% (115/196)
回答No.1

全く目的の違う関数で、包含関係にはありません。 マニュアルを熟読するのがよいでしょう。 http://jp.php.net/manual/ja/function.sqlite-escape-string.php http://jp.php.net/manual/ja/function.htmlspecialchars.php

march4
質問者

お礼

アドバイスありがとうございます。 早速、マニュアルを再度読んできました。 ご指摘の通り、確かに両関数は包含関係にはなさそうですね。 htmlとして処理・表示させる際に、 htmlタグとしてではなく、その記号本来の形で出力したい場合には、 htmlspecialchars()で変換してやる必要があるわけですね。 一方、 sqlite_escape_string()は、 sqliteにおけるSQL文の中で問題を起こしそうな記号やら書式に対し、 適切にエスケープを行ってくれる関数のようですね。 両関数とも、正常な処理または表示をするという目的のために、 問題を起こす可能性のある記号に対し、変換処理を行う という意味では共通しているなと感じました。 ただ、両者では、目的が異なるため、変換のしかたが異なるようですね。 例えば、シングルクオート「'」への処理において見てみると、 それぞれ、 htmlspecialchars()では、 ''' (シングルクオート) は '''に、 sqlite_escape_string()では、2重にされてエスケープ、 されるようですね(設定によっては、異なる場合もありますが)。 よって、 例えば、GETか何かで値(文字列)を受け取り、 それをSQLデータベースへいったん入れ、さらに、それを取り出して、HTML出力する、なんて場合には、 両関数どちらも使うことになりそうですね。 なんだか、モヤモヤが晴れてきました。 上記のようなシチュエーションにおける、 処理の方法としては、 htmlspecialchars()→eslite_escape_string()→DB処理→HTML出力 というフローの他に、 eslite_escape_string()→DB処理→htmlspecialchars()→HTML出力 というフローも考えられますが、これらは 目的によって、使い分けられるものだと思います。 ただ、どちらでも問題ないという場合には、 どちらの方が、よりメリットがありそうでしょうか。 前者だと、DBにインサートするデータ量が若干増えますが、 呼び出しの際に毎回htmlspecialchars()処理をする必要がないので処理が比較的速そうです。 一方、後者はその逆となりそうです。 (大差ないかもしれませんが。苦笑) ひとまず、こんなことを考えました。 上記を踏まえた上で、 何か「忠告しておきたいこと」などがありましたら、 どなたか、どうかご教授下さい。 よろしくお願いします。

関連するQ&A

  • sqlite_escape_stringのアンエスケープ方法

    sqliteのエスケープ方法としてPHPマニュアルでは sqlite_escape_string() を利用することが望ましいと 記述されています。 実際にsqlite_escape_string() を使用してDBに格納するのは 問題ないのですが、データを取り出したときに エスケープされたままで出てきます。 アンエスケープする方法はどのようなものでしょうか? str_replace("'","''",取り出した文字列); とかではないですよね・・・。

    • ベストアンサー
    • PHP
  • pg_escape_stringとhtmlspecialcharsの記述の仕方について

    お世話になります。フォームで入力した値をpostでPHPに送ってます。 その際にセキュリティを考えてpg_escape_stringとhtmlspecialchars関数を使用したいのですが、簡単な記述方法が分かりません。 今現在は下記のようにしてます。 $tesuto=pg_escape_string(@$_POST["tesuto"]); $tesuto="'" .htmlspecialchars($tesuto) ."'"; フォームで入力する項目が20箇所あるので、これをスマートに 記述する方法は無いでしょうか?よろしくお願いします。

    • ベストアンサー
    • PHP
  • $_GETで受け取った値に対して、htmlspecialchars()した時の謎なふるまいについて。

    //(環境)PHP5、SQLite3、Firefox <?php echo $_GET["page"];  //(1)何も出力されない。 $_GET["page"] = htmlspecialchars(sqlite_escape_string($_GET["page"])); echo $_GET["page"];  //(2)<br>と出力されてしまった。 ?> 上記スクリプト index.php に対し、 ブラウザURL記入欄にて、 http://example.com/index.php?page=<br> と、ゲットで値「<br>」を与えたURLを打ち込んだところ、 上記ソースのコメントに書いたような出力結果となりました。 私の予想では、 (1)では、<br> を、 (2)では、&lt;br&gt; を、 それぞれ出力するものと思っていましたが、結果は全く違いました。 これはなぜなのでしょう? さらに、 上記において、 $_GET["page"] = htmlspecialchars($_GET["page"]); としても、結果は同じでした。 ------------------------------ また、 $_GET["page"] = htmlspecialchars(sqlite_escape_string($_GET["page"])); の場合に、 ゲットで渡す値を「<br>」から「<'br'>」へ変えてみると、 (1)では、<'br'>を、 (2)では、<''br''>を、 それぞれ出力しました。 ------------------------------ どなたか、分かりましたら教えて下さい。 よろしくお願い致します。

    • ベストアンサー
    • PHP
  • htmlspecialcharsの正しいタイミング

    htmlspecialcharsを使うタイミングがいまいちわかりません。 調べてみると、html出力時だということがわかりました。 mysqlを使った場合は以下の手順、 、 (1)フォームの内容をmysql_real_escape_stringしてデータベースに保存 (2)データベースから取り出すとき、htmlspecialcharsして出力する。 だとわかりましたが、ここで疑問点があります。 これまで掲示板などをデータベースを使わずファイル保存で作る場合、 (1)フォームの内容をhtmlspecialcharsしてファイルに保存 (2)foreachですべて表示 というやり方をしていましたが、正しくは、 (1)htmlspecialcharsせず、そのままファイルに保存 (2)foreachで表示するとき、htmlspecialcharsする という順序なのでしょうか?? わかりにくくて申し訳ないのですが、ご教授ください。 よろしくお願い致します。

    • ベストアンサー
    • PHP
  • 「addslashes」と「htmlspecialchars」について

    「addslashes」と「htmlspecialchars」について、いくつか分からない点があるので、教えてください。 ■質問1. http://kezy.org/2009/10/04/php-get-post 関数化している例が掲載されているのですが、このやり方を真似してもよいものでしょうか? http://kmaebashi.com/zakki/zakki0042.html ここでは、それぞれの処理の直前に行うべきと書かれていて、 また別のサイトでも、用途に沿った処理方法で、と書かれているのですが、 「addslashes」と「htmlspecialchars」を一つの関数にまとめることは、次のどれに当たるでしょうか? ・別に問題ない ・奨励はしないけど、間違いではない ・止めたほうがよい ※二つを関数化すると、便利だと思うのですが、必要ないところにもサニタイズ処理等がかかるのかな、と思い、そこら辺が問題ないかよく分からなかったので、質問しました。 ■質問2.MySQLを利用する場合は、「addslashes」より、「mysql_real_escape_string」を利用したほうがよいのでしょうか? 両者の違いは何でしょうか? ■質問3.プリペアド・ステートメントを使うのであれば、該当フォーム部分については、別にSQLインジェクション対策をしなくてもよいのでしょうか? あるいは、プリペアド・ステートメントを利用しても、あくまでも攻撃を受ける可能性が下がるだけ(?)なので、「addslashes」をしとくべきなのでしょうか? ※なんでもかんでもやればいいってものでもないのかな? と思い、質問しました。

    • ベストアンサー
    • PHP
  • mysql_real_escape_stringについて

    PHPとMYSQLで連携させ組んでおります。文字コードはutf-8で改行コードはLFです。 ざっくりですが流れとしてはフォームからユーザーが入力した値を mysql_real_escape_stringしデータ登録しているのですが改行文字に問題があります。 ※改行文字は\r\nでも\rでも最終的に\nになるように統一しております。 それを踏まえて単純に登録する値を静的に以下のように作成します。 $val1 = mysql_real_escape_string("あああ\nいいい''ううう"); $val2 = "あああ\nいいい''ううう"; phpmyadminからテーブルを開きエクスポートしSQLを確認すると $val1は(1, 'あああ\\nい\\''\\''いい')となり $val2は(2, 'あああ\nい''''いい')となっています。 これは当然の動きかとは思うのですが改行文字\nが\\nになるのを防げないものかと 悩んでいるのですがこれは無理でしょうか? mysql_real_escape_stringしない場合エスケープもされないのでそのままの状態なのですが データを登録する場合やselect文でWHERE句を用いる場合セキュリティ的に外すことも できないもの(かと思い込んでいる)でどうしていいかわからない状態です。 知識もあいまいなもので無理なものだとわかればすぐにでも諦めがつくのですが なにかいい方法があるのでは・・・と淡い期待を持っており質問させて頂きました。 宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 括弧内の処理の順序

    プログラムを見ていて気になった点があります。 htmlspecialchars(mysql_real_escape_string(stripslashes($_POST["inp01"])),ENT_QUOTES) 上記の書き方の場合、処理される順番は 内から「stripslashes」→「mysql_real_escape_string」→「htmlspecialchars」になるんでしょうか? 逆に 外から「htmlspecialchars」→「mysql_real_escape_string」→「stripslashes」 でしょうか。 また処理の順番ですが、 「htmlspecialchars」→「stripslashes」→「mysql_real_escape_string」が正しい形でしょうか。

    • ベストアンサー
    • PHP
  • PHP ver5~の、SQLインジェクション対策

    PHP Version 5.4.7 において、 SQLインジェクション対策として、 sqlite_escape_string()を使おうとしたら、 undefinedとエラーを吐かれたため、 sqlite_escape_string()の代わりとして、 SQLite3クラスの、 SQLite3:: escapeString を使おうと思っていますが、 問題ありますでしょうか。

    • ベストアンサー
    • PHP
  • mysql_real_escape_stringについて\r\nが付くのは?

    $sql = INSERT INTO users (logid, passwd) VALUES ( "'" . mysql_real_escape_string($_POST['id']) "','" . mysql_real_escape_string($_POST['pas']) . "';" とすると全POSTデータの先頭に「\r\n」が付与されてしまいます。 INSERT INTO users (iogid, passwd) VALUES ('\r\n 入力されたID', '\r\n 入力されたパス') こんな感じになってしまいます。 SQL実行時にデータベースに入ってしまっているのか、 phpMyAdminで確認すると、文章内に改行が入ってしまっているみたいで、表のレイアウトがガタガタになっています。 SQLインジェクション対策に必要だと参考書には表記されているのですが、あまりにデータベースが見にくいので、私の使い方が間違っている様な気がします。 (1)\r\nが先頭に付与されるのは正しいのでしょうか? (2)データベースにSQLで\r\nをINSERTしると、データも\r\nが入ってしまうのでしょうか? (3)PHP + MySQLでSQLインジェクション関数はmysql_real_escape_stringだけなのでしょうか? なにぶん超初心者なので、ご教授の程よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • sqlite_query()に関する質問

    ブラウザからポストでSQL文を受け取り、それをもとにDBを作成するスクリプトを考えています。 スクリプトの実行権限は、ページにログインできたユーザ(サイト管理者)のみ与えられています。 では、質問に移ります。 スクリプトに渡される$_POST['sql']の値が、クエリ文の言語仕様的に正しい書式ではなかった場合、 $sql = sqlite_escape_string($_POST['sql']); sqlite_query('hoge',$sql); の結果は、 Warning: sqlite_query() [function.sqlite-query]: near "なんたら~": syntax error in /なんたら~ といったエラーを吐き、 さらに、ファイルサイズ0の余計なクズファイルが作成されてしまうのですが、、 このクズファイルが結果的に作成されないように設計するには、どのようにしたら良いでしょうか。 私なりに2つの方法を考えてみましたので、アドバイスを頂けると嬉しいです。 (1) $_POST['sql']の時点で正規表現をもとに、SQL文の書式が正しいかチェックをし、 誤った書式のSQL文をsqlite_query()に渡すことを回避する方法。 ※私の能力的に、希望とする正規表現を正確に考え出すことができるか、はなはだ怪しいため、 できれば、避けたい方法です。 (2) 正規表現を使った方法だと、やや繁雑になりそうなので、それはやめにし、 ひとまず、SQL文の正誤を問わず、sqlite_query()を実行させ、 その結果、クズファイルが出来てしまうようなら削除する、といった方法。 ※クズファイルが生成されたかどうかのチェックは、 生成されたファイルのファイルサイズ == 0? をもとに行います。 ※ただし、私の利用するサーバの仕様上、 クズファイルは 所有者=「apache」 として作成されてしまうため、 もしかしたら、スクリプトからは削除できないかもしれません。 その場合には、こちらの方法は廃案となります。汗 (3) その他の方法(オススメの方法がありましたら、是非教えて下さい!) 以上、どなたか、ご助言よろしくお願い致します。

    • ベストアンサー
    • PHP

専門家に質問してみよう