質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

Q&A

3回答

3925閲覧

MysqlのPDOで動的プレースホルダーのエスケープ方法を知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

0グッド

1クリップ

投稿2016/07/26 09:53

編集2016/07/26 17:50

PHPでmysqlの接続にPDOを利用しています。

そこでプレースホルダーについてですが、
調べると動的プレースホルダー静的プレースホルダーの2種類があり、
セキュリティ上静的プレースホルダーを利用するのが推奨されているというのがわかりました。
私は動的プレースホルダー使用したいと考えております。

###質問
動的プレースホルダーを利用する場合、SQLのエスケープ処理はどのような方法があるのでしょうか?
テンプレの様な方法があれば、教えて頂きたいなと思っております。

理由としては、万が一SQLにエラーが発生した時や、開発中に実際に発行したSQLを確認する際に、
独自のログファイルに出力したいと思っております。
静的プレースホルダーでもmysqlのログファイルを見ればいいと言う事もありますが、
デバッグや調査のやり易さ的に独自のログファイルに出力したいのです。

PHPのフレームワークやWordpressなど多くのソフトは動的プレースホルダーを採用しておりますので、
それほど重大なセキュリティの問題は可能性として低いのかなと思っております。

拙い説明かとは思いますが、皆様のお知恵を拝借できたら幸いです。

それでは、どうぞ宜しくお願い致します。

>>追記
ご教授いただきたいことを簡潔にいいますと、
静的or動的プレースホルダーのどちらであっても、
実際に発行したSQL文を独自のログファイルに出力できるようになりたいです。

可能であればですが、
ベストな方法は静的プレースホルダーの実行したSQL文を独自のログファイルに出力したいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

PDOを例に取ると、quoteメソッドを用いるとエスケープをしてくれます。しかし、quoteにもbindParam/bindValueにもパラメータがあり、それらが厳密に一致しているかという問題があります。私が過去に調べたところでは、必ずしも一致していないようでした。
そうすると、PDOの動的プレースホルダをquoteメソッドでシミュレートしてみても、実は微妙に異なるという可能性があります。
ログの目的にもよるでしょうが、実際に生成されたSQL文とログのSQL文が違っていると、トラブルシューティングの手助けになるどころか障害になる可能性が高いでしょう。「間違っているかもしれない」ログというものは、役に立たないと思います。
そうなると、動的プレースホルダが生成したSQL文を何らかの方法で「横取り」することになるでしょうが、それはPHPを改造することになり、かなり難易度が高いと思います。
従って、MySQLのログを何らかの方法で扱いやすくすることを考えた方がよいのではないでしょうか?

投稿2016/07/31 12:20

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

動的プレースホルダーを利用する場合、SQLのエスケープ処理はどのような方法があるのでしょうか?

PDOを利用する場合、

php

1PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, [true または false]);

の一文を実行する(あるいは実行しない)とき以外、実装時にどちらのプレースホルダーを使用しているかを意識する必要は ほぼ(※)ありません。
http://php.net/manual/ja/pdo.setattribute.php

また、動的プレースホルダーを利用する場合でも、自前でエスケープする必要はありません。
ご自分で検証してみるとよく分かりますが、以下の引用文に
「動的プレースホルダーは例外」
などの記述がないことからも、それが分かります。
http://php.net/manual/ja/pdo.quote.php

SQL ステートメントにユーザーの入力値を埋め込むための PDO::quote() を使用する代わりに、 バインドパラメータを用いて SQL を準備するための PDO::prepare() を使用することが強く推奨されます。

http://php.net/manual/ja/pdo.prepare.php

PDO::prepare() と PDOStatement::execute() をコールすることで、(中略)パラメータに手動でクオートする必要がなくなるので SQL インジェクション攻撃から保護する助けになります。

静的or動的プレースホルダーのどちらであっても、実際に発行したSQL文を独自のログファイルに出力できるようになりたいです。

tanat様のコメントにある通り、一般クエリーログに全てのクエリが記録されます。

手元に環境がないため未検証ですが、静的プレースホルダーを使用していたとしても、一般クエリーログにクエリとパラメータの双方が記録されるようです。
http://stackoverflow.com/questions/210564/getting-raw-sql-query-string-from-pdo-prepared-statements
http://dev.mysql.com/doc/refman/5.6/ja/c-api-prepared-statement-function-overview.html
※「プリペアドステートメントのロギング」という項を参照

何の目的で

独自のログファイルに出力

したいかにもよりますが、まずは一般クエリーログで代替できないか、検討してみてはいかがでしょうか?
そうすれば、独自に仕組みを実装する必要がなくなるからです。


※ 私が把握している限りでは、以下くらいです。

http://php.net/manual/ja/pdo.prepare.php

エミュレーションモードが有効になっていない限り、 ひとつのプリペアドステートメントの中で、同じ名前のパラメータマークを 複数使用することはできません。


ちなみに、動的プレースホルダーを使用する際のリスクとその対策は、以下などがあります。
(他にもあるかもしれません)
http://blog.tokumaru.org/2011/08/pdo.html
http://blog.tokumaru.org/2013/12/pdo-and-mysql-allow-multiple-statements.html

投稿2016/07/27 17:20

KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/07/28 01:38

ご意見ありがとうございます。
guest

0

動的エスケープはちょっとしたミスが即脆弱性に繋がるため、
私の価値観としては全くお勧めできませんが、
方法としては
PDO::quote
正しく使えばOKです。

投稿2016/07/26 10:47

編集2016/07/26 10:57
tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/07/26 17:52

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

2016/07/26 19:33

全クエリを記録したいなら、一般クエリログ *MySQLのバージョンによって設定が違ったりするので注意 https://dev.mysql.com/doc/refman/5.6/ja/query-log.html エラーが起きた時に何が起きたかを知りたいなら、 http://piyopiyocs.blog115.fc2.com/blog-entry-657.html 例外で補足してcatchして確認 どうしても独自のロガーを使いたいのであれば、 PDOを継承してexecute()のタイミングで各パラメータをログるような仕組みを実装という感じでしょうね
退会済みユーザー

退会済みユーザー

2016/07/27 02:32

なるほど、了解です。 静的プレースホルダーでログを出力するには独自に仕組みを実装するしかなさそうですね。 アドバイスありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問