プロが教える店舗&オフィスのセキュリティ対策術

mysql_real_escape_stringについて調べていると、私と同じことを疑問に思い質問している人がいました。

こちらのページです。
http://oshiete.goo.ne.jp/qa/4423735.html

mysql_real_escape_stringを通してDBに入れるとします。
すると、「テスト\」というデータをINSERTをするとDBには「テスト\」で入るのでしょうか?

では、mysql_real_escape_stringを通さずにdbに入れても
「テスト\」というデータをINSERTをするとDBには「テスト\」で入ると思います。

上記のとおりとした場合、PHPはどうやってmysql_real_escape_stringを通したかどうか判定しているのでしょうか?

現在、mysql_real_escape_stringを通してDBに入れると、
「テスト\\」というデータがDBに入っています。

それをどうやって戻すのか調べていて、上記の質問を見つけました。

どうぞよろしくお願いします。

A 回答 (5件)

ちょっと興味がわいたので調べてみました。



DBは以下のような感じ。

テーブル : test
フィールド : cd , value
ストレージエンジン : MyISAM

以下を実行。

<?php

/* DBコネクト絡みは省略 */

$str = ' \10,000- ';

$query = "insert into test (value) values ('" . mysql_real_escape_string($str) . "')";
$result = mysql_query($query);

$query = "insert into test (value) values ('" . $str . "')";
$result = mysql_query($query);

$query = "select * from test";
$result = mysql_query($query);
while($dt = mysql_fetch_assoc($result)) { print_r($dt); };

?>

実行結果。

Array ( [cd] => 1 [value] => \10,000- )
Array ( [cd] => 2 [value] => 10,000- )

この時の MySQLの中の test.MYD をバイナリで覗いてみる。
もう このファイルの時点で mysql_real_escape_string してない二つ目のほうには \マークがついてなかったです。

insert した時点で mysql_real_escape_string してないほうの \マークは なかった事になってしまってるみたいです。
設定によるのかもしれませんし、仕組みとかはさっぱり分かってないんですけど。
    • good
    • 0
この回答へのお礼

ありがとうございます。
上記のコードをためしたところ、同じ実行結果になりました。

でも、mysql_real_escape_stringがない場合の結果が納得いきません。
勝手に、”\”とるなよ~って言いたいです。

では、MySQLにデータを入れる場合、mysql_real_escape_stringを通せってことでしょうか?
ますますわからなくってきました。

もうちょっと調べてみます。
ありがとうございました。

お礼日時:2011/10/09 20:16

お礼ありがとうございます。


俺は ちゃんと学習した人間ではなく、結果から理解しているだけのところもありますので、話半分に聞いておいてもらえると助かります。

> 勝手に、”\”とるなよ~って言いたいです。

PHPが渡すときにやっているのか、MySQLが受け取るときにやっているのかわかりませんが、エスケープシーケンスとして処理しているって事なんだと思います。

実は ちゃんと エスケープシーケンスについて 説明しようかと思って書いていたのですが、説明が下手すぎてミスディレクションになりかねなかったので、はしょらせていただきました。
↓ ここらへんが分かりやすいかも。
http://www.phpbook.jp/tutorial/string/index4.html

> では、MySQLにデータを入れる場合、mysql_real_escape_stringを通せってことでしょうか?

元々、mysql_real_escape_string がやっている事ってのは、文字列の中の特殊な記号(上記のリンクの一覧)に、\マークを追加してるだけです。

あー、マニュアルに書いてました。
「mysql_real_escape_string() は、MySQL のライブラリ関数 mysql_real_escape_string をコールしています。 これは以下の文字について先頭にバックスラッシュを付加します。 \x00, \n, \r, \, ', " そして \x1a. 」
バックスラッシュって¥マークの事です。
円は日本の通貨ですし、何でバックスラッシュに当てちゃったかは知りませんが、そうなってます。
日本語に対応していないフォントで¥マークを打つと、左右反転したスラッシュが表示されます。

んで、さらに
「データの安全性を確保するため、MySQL へクエリを送信する場合には (わずかな例外を除いて)常にこの関数を用いなければなりません。 」
とも書かれています。

http://php.net/manual/ja/function.mysql-real-esc …

んー、この結果から考えると MySQLのほうで削ってるっぽいですね。

結局、無駄に長くなってしまってすみません。m(_ _)m
    • good
    • 0
この回答へのお礼

追加のなが~い説明ありがとうございます。
とても感謝しております。

mysql_real_escape_string は、sqlインジェクションを防ぐためにとても大切です。
そのため、いつもなら質問して、1つで回答があったらおしまいにしているのですが、セキュリティに関することなので、ちょっとでも情報を集めようと思っているので、まだ質問をしめきっておりません。あらかじめご了承ください。

phpで作るプログラムって、どれも似たような物になります。
その都度、同じようもものを書くの画面どうなので、テンプレートみたいなものを作ろうと思っています。

その作っているテンプレートのプログラムですが、記載していただいたサンプルによると、”\”をデータとしても入力しても、DBには”\”が1つしか入りません。

しかし、今回書いたプログラムはなぜか”\\”になって困っております。

ここでソースをさらせばいいのですが、今回のテンプレートはフレームワークを使って作っているために、ソースをコピペできません。

また、そのフレームワークも、cakephpみたいなものなら、それなり情報が集まると思うのですが、cakephp自体が複雑で覚えるのが面倒なので、”ちいたん”という小さなフレームワークを使って作っているので情報が余りなくて困っております。

フレームワークなんか使わずに、一から書けばいいのですが、プログラムは趣味なので書く度にスタイルが変わります。

プログラムを書いていると一度は経験すると思いますが、たとえ自分か書いたプログラムでも時間がたてば、他人の書いたプログラムです。

その都度、読み直すのが面倒なので、他人の決めたルールでテンプレートを作ろうと思って、フレームワークを使いました。

また何か情報がありましたらよろしくお願いします。
ありがとうございました。

お礼日時:2011/10/10 20:56

> しかし、今回書いたプログラムはなぜか”\\”になって困っております。



cakephp も ちいたん ですらも挫折した俺なので、あんまり言えませんが、多分フレームワーク側で追加してるんじゃないですかね?
フレームワークのほうを覗いてみたわけでもありませんし、フレームワークに渡さない書き方をしているのかも知れないので、何ともいえませんけど。

俺は 記憶がかなり怪しくなってるので、後から見た時に分かるようREM満載で書いてます。
さらにフレームワークも扱えないので、ネイティブでゴリゴリ書く事が多いです。

さすがに 面倒な事になると、PEARとか 他のライブラリとか使ったりしますけど、基本、作業効率とか気にしません。

あと昔読んだ誰かのブログか何かに、ある特定の条件で mysql_real_escape_string が セキュリティとして役に立たなくなるような事が書いてあったのがあった気がします。
情報ソースを見つけることができなかったのと、記憶が怪しすぎるのとで 前回書きませんでしたが、そういったことを言っていた人がいた。ぐらいには覚えておいてもらえると良いかもしれません。
数年前のものですし、確か、「あるエンコードである文字を」といった感じだったと思うので、今は 特に問題ないのかもしれません。

また微妙な情報ですみません。

この回答への補足

コードをぶつ切りにして、print_r()した結果、なぜ"\"が"\\"になるのかわかりました。
なんと、ちいたんが sql を作る直前にエスケープしていました。
恐るべし、ちいたん

ところで、なんで私が ちいたん がエスケープしていないかと思ったかというと、こちらのページを見たからです。
http://php.cheetan.net/community/forum/categorie …

こちらのサイニタイズの意味を、エスケープの事だとおもい、それに対してちいたんの開発者が、適宜必要な修正をお願い致しますなんて書いてあるので、自分でエスケープ処理が必要だと思い込んでいました。

今回の結果から分かったことは、mysqlに入れる場合、mysql_real_escape_stringを絶対通さなければいけないことがわかりました。
通さないと、勝手に"\"が削除されることがわかりました。

ありがとうございました。

補足日時:2011/10/11 01:32
    • good
    • 0
この回答へのお礼

追加情報ありがとうございます。

昔、cakephpを知ったとき「なんてすばらしいシステムだ~」と感動しました。
そこで、本を2冊も買って勉強しました。

実際にcakephpを使って見た感想ですが、ちょっと変わったことをしたいと思うと、情報が無くてとても大変な思いをしました。
また、久しぶりにcakephpを使おうとすると、すっかり忘れていて、また一から勉強する必要があり効率がわるかったです。

そこで、コードが少ない ちいたん を使うことにしました。
でも、ちいたん でも問題がなかったわけではありません。

今回、phpのバージョンを5.3にしました。
すると、ちいたん から警告みたいなものがでました。

たぶんphp4でも使えるようになっているため、問題が発生しているのではないかと思います。

たとえば、
=& new クラス名
のコードから警告が出ています。

たぶんクラスは参照渡しなのに、&を付けているからだと思います。
そこで、警告が出ているコードの&を取りました。

次にphpは、オーバーロード?の概念が他の言語と違うようで、引数の数が違うところから警告が出ていました。
そこをコメントアウトしました。

すると、警告が出なくなりました。

でも、これらの対策は、私がそのように思うだけで、本当に対策として正しいかわかりません。

そんなこともあり、問題が複雑になっています。

ちいたんは、私が見る限り、エスケープ処理を自動でしていません。
だから自分でする必要があるのですが、ちいたんは、フォームからのデータが連想配列で送られます。
そこで、foreachして一括でエスケープ処理するようにしたのですが、その辺に問題が発生しているようなので、今、分析中です。

ところで、私もPEARは使っていました。
またsmartyなんかも使っていました。
しかし、今はどちらも廃れたようなイメージがあるのですがどうでしょうか?

phpは、バージョンが上がるたびに苦労しているので、なるべくライブラリは使わないようにしています。

>ある特定の条件で mysql_real_escape_string が セキュリティとして役に立たなくなる

mysqlの文字化けを防止するために、クエリの前に"SET NAMES utf8"を突っ込むんだ場合でしょうか?

今回、テスト環境を作るにあたって、xamppを使いました。
しかし、mysqlの文字コードの設定がうまくいかず、文字化けで苦しみました。
そこで、"SET NAMES utf8"を突っ込んで対策しました。
最初は、mysqlの設定で何とかするつもりでしたが、挫けてしまいました。

只今、コードをぶつ切りにして、原因を追究しています。

あ~、なんか、いやになってきたな~

お礼日時:2011/10/10 23:05

あー、何度もすみません。



> phpで作るプログラムって、どれも似たような物になります。

これで、思い出したのですが、昔プログラマの事を「知的単純労働者」だったか「知的肉体労働者」とか言っていた人がいました。

> プログラムは趣味なので書く度にスタイルが変わります。

これも、とてもよく分かります。
俺も 書いた時期によって コードの書き方が 違ってて、昔書いたものなんか すっごい しっかり書いていたりして、俺の劣化具合が伺えて 黄昏たくなる時があります。

今度は情報ですらなくてすみません。
同感できる部分が多かったので なんとなく つい。

この回答への補足

さらに ちいたん についてわかったことがありました。
ちいたん のバージョンアップの変更履歴を見ていると、バージョン0.7.9.9で、「modelに一部自動エスケープを追加」となっていました。
Σ(゜Д゜;)アラマッ

いったい、今までの苦労はなんだったんだろうと思います。
最初からめんどくさがらずに、コードを自分でぐりぐり書いてテストをしていれば、もっと早く原因が分かったのですが・・・
(´・ω・`)ショボーン

私がめんどくさがったために、貴重な時間を割いていただくことになり、誠に失礼しました。
本当にありがとうございました。

補足日時:2011/10/11 01:41
    • good
    • 0
この回答へのお礼

>これで、思い出したのですが、昔プログラマの事を「知的単純労働者」だったか「知的肉体労働者」とか言っていた人がいました。

確かに、プログラムといえば、単純作業も多いです。
そのため、他人のコードをコピペで済ますこともよくあります。
また、日本ではプログラマの地位が低いのではないでしょうか?
そのために、日本から新しいものが出にくい環境になっているとおもいます。
仕事で搾取され、さらに休みの日までプログラムを書こうと思う人は少ないでしょうから。
ネットなどで、プログラマの仕事を、ドカタになぞらえたような表現をよく目にします。

今回、phpで、エクセルを読み込むのに、PHPExcelってライブラリをつかいました。
しかし、日本語の情報が少なくて大変苦労しました。

また、他のライブラリの場合、言語設定で日本語がないってのもよくあります。
なんか、日本だけこの世界で取り残されているようなきがします。

お礼日時:2011/10/10 23:18

「どこでやめたらいいのか分からないメール状態」になっている事に一抹の不安を感じつつも、答えれるところだけピックアップして答えたいと思います。



> ところで、私もPEARは使っていました。
> またsmartyなんかも使っていました。
> しかし、今はどちらも廃れたようなイメージがあるのですがどうでしょうか?
smarty は かじった事すらないので、分からないのですが、PEARは「廃れた」というよりかは「枯れた」という感じかもしれません。
俺が PEAR で 使ってるのは、Postfixとかからパイプされてきたメールソースを解析する PEAR::Mail関係のものだけです。
もう数年も前から使用していますが、今も安定して動いてくれています。

ライブラリはメールライブラリのQdmailを好んで使用しています。

> mysqlの文字化けを防止するために、クエリの前に"SET NAMES utf8"を突っ込むんだ場合でしょうか?
んー、正直自信はないんですけど、「PHPのスクリプトの文字コードとMySQLの文字コードが違った場合」とかだったかもしれません。
あと SET NAME を投げるより mysql_set_charset 使ったほうがいいらしいです。PHPのバージョン依存しますけど。
↓詳しくは こちら。
http://www.phppro.jp/phptips/archives/vol42/1

> また、日本ではプログラマの地位が低いのではないでしょうか?
これに関しても その地位にいたことがないので、正直分かりません。
ただ「ブラック会社に勤めてるんだが、もう俺は限界かもしれない」というのを観た時は「これは酷い」と思いました。
まぁ、ブラック会社だからだろうとは思いましたが。

> また、他のライブラリの場合、言語設定で日本語がないってのもよくあります。
> なんか、日本だけこの世界で取り残されているようなきがします。
正直、これも仕方がないかなって諦めてます。
日本語化されてるのは、日本の有志が作ってくれたものがほとんどで、海外の人がデフォルトで日本語も対応してくれるってのは少ない気がします。
日本以外の世界地図を見ると、やっぱり日本って極東の島国ですから。

> 今回の結果から分かったことは、mysqlに入れる場合、mysql_real_escape_stringを絶対通さなければいけないことがわかりました。

俺も ちゃんとしたものに使う場合は、mysql_real_escape_string は概ね必ず使ってます。
ただ、関数の名前自体が長すぎて視認性が悪いので、以下のような関数にしちゃってます。
function SX($str) { return(mysql_real_escape_string($str)); }

同様に HTMLも 関数にしちゃってます。
function HX($str) { return(htmlspecialchars($str , ENT_QUOTES)); }

関数にする事によって 負荷的に悪いんじゃないの?という疑問もありつつも気にしてません。

あと、そちらみたいに ちゃんと自分の調べた事も教えてくれる質問者は とてもうれしいです。
回答したのに何の反応もないと「結果どうなったんですか~~?」と思いつつも、記憶から消えていく事になります。

基本的にベストアンサーが欲しいわけではありませんので、このまま閉じないままでもいいのですけど、できれば解決したのであれば、閉じて欲しいなとは思います。

あ~ぅ、また長文になってしまいました。(; ̄ー ̄A アセアセ
    • good
    • 0
この回答へのお礼

ありがとうございます。

質問したことにたいして、お返事が頂けるかとおもい、質問を締め切っておりませんでした。
本当に、お手数をおかけしました。
いろいろと勉強になりました。
もちろん、ベストアンサーです。
ありがとうございました。

お礼日時:2011/10/11 11:14

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