重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

PHPのSQLインジェクションですが、sprintf内でクォートをしてあるとそれで大丈夫なのでしょうか?
以下のようなコードがあり、nameは画面入力なのでSQLインジェクションが起こるのでは?
と作成者に確認したところ、"%s"してあるから大丈夫との返事をもらいました。
ネット調べるとmysql_real_escape_stringでエスケープしてから"%s"で変換すれば大丈夫といった内容は見つけたのですが、mysql_real_escape_stringなど不要との返事をもらいました。
なぜ?と聞くとそういうものだとしか回答がありません。

sprintf('UPDATE users SET name = "%s" WHERE id = %d', name, id);

結局上記のコードでSQLインジェクションは解消されているのでしょうか?

A 回答 (3件)

sprintfを使っただけでは対策されず、mysql_real_escape_stringも必要となります。

もっとよいのはsprintfもmysql_real_escape_stringも使わず、プレースフォルダを使ってSQLを呼び出すことです。

では、どうしてsprintfを使うとSQLインジェクション対策になるという話が出てきたかですが、ひょっとすると、数値の場合のことを言っているのかもしれません。この場合は、以下でSQLインジェクション対策になります。%dで受けることで、データが強制的に整数に変換されるので、攻撃の余地がなくなります。

sprintf('SELECT * FROM users WHERE ID = %d', $id); // IDが整数の場合

しかし、%sで受ける場合は、入力文字列はそのままSQL文の一部になりますので、SQLインジェクション攻撃が可能となります。そのため、mysql_real_escape_stringは必須です。

参考文献として、IPAの「安全なSQLの呼び出し方」のURLを添付しますね。少し難しいですが、SQLインジェクションの解説としてはとても詳しいです。

参考URL:http://www.ipa.go.jp/security/vuln/websecurity.h …
    • good
    • 0
この回答へのお礼

やはりプレースフォルダがいいのですね!
わかりやすい回答ありがとうございます!!
参考文献もとても助かりました。

お礼日時:2012/12/09 14:08

>エスケープとしてこれで対策になっているのでしょうか?


なっていない。
>文字列を""付きでsprintfするだけでなぜ対策になるのかわからないのです。
俺もわかりません。ド素人が作ったソースなのでしょう。

>作成者はPHPではこれでいいと言っています。
よくない。
PHPにおいてもプレースホルダを使うのが一般的になっている。

また、
>ネット調べるとmysql_real_escape_stringでエスケープしてから"%s"で変換すれば大丈夫といった内容は見つけたのですが、mysql_real_escape_stringなど不要との返事をもらいました。
http://php.net/manual/ja/function.mysql-real-esc …
mysql系の関数はすでにPHPにおいては非推奨の関数になっている。
使うべきはmysqliや汎用のDBドライバとなるPDOを利用すべき。
    • good
    • 0
この回答へのお礼

ずばりな回答ありがとうございます。
上記のような内容を伝えたのですが、
自分の作ったソースはとにかく変えたくないようで、
他のひとに作り直してもらうことになりそうです。

お礼日時:2012/12/09 14:07

今時のSQLインジェクション対策はプレースホルダが常識。


未だにエスケープ処理って何年前の対策方だよ。?そんな対策方は2000年頃かな?

この回答への補足

自分はJavaしか知らないのでプレースフォルダのイメージでしたが、作成者はPHPではこれでいいと言っています。
エスケープとしてこれで対策になっているのでしょうか?
文字列を""付きでsprintfするだけでなぜ対策になるのかわからないのです。

補足日時:2012/12/08 23:36
    • good
    • 0

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