
MySQL、ブラインド SQL インジェクションにより情報漏洩が発生 45
ストーリー by reo
餅は餅屋だけに餅に弱い 部門より
餅は餅屋だけに餅に弱い 部門より
MySQL.com と関連するサイトが米国時間 27 日にクラックされ、情報が漏洩した模様。手法はブラインド SQL インジェクションによるものと考えられている (Techie Buzz の記事、本家 /. 記事より) 。
被害に遭ったのは本家 MySQL.com の他、フランス、ドイツ、イタリアの MySQL のサイト。漏洩した情報には MySQL 関係者の Email アドレスや認証情報の他、顧客情報や内部ネットワーク情報も含まれているという。また XSS 脆弱性についても詳細に報告されており漏洩がさらに拡大する恐れもあるとのことで、さらには Sun.com にあるデータベースの内容も既にクラックされている報告もある。
今のところ MySQL からはこの件に関するニュースリリースが出ていないが、是非とも MySQL の矜恃 (そういうものがあるのなら) を賭して対策を施して欲しいものである。
っていうか、これ (スコア:4, 興味深い)
「ブラインド」SQLインジェクションって、区別するものなのかな?SQLインジェクションそのものだと思うんだけど。SQLインジェクションの種類わけならそれでもいいと思うんだが、何か別物のように聞こえてしまって/扱っているようで、違和感感じました。
PHPのソーシャルアプリを使っている人間に聞いたら、PDOでPlaceFolderを使ったクエリ作成(prepare使うやつ)は、使わないんだとか。PDOって処理速度が重いので、PV稼がなくてはいけないソーシャルアプリには不適切なんだとか。教科書どおりなら、SQLインジェクション防ぐのはprepare()が有効だと思うんだが・・・
-- gonta --
"May Macintosh be with you"
Re: (スコア:0)
さすがPHPer、期待に違わぬ残念さ。
Javaで速度を稼ぐためにPreparedStatementをやめたなんて話は聞いたことがないなあ(検索条件が動的に変化するので使えなかったということはあるけど)。むしろかえってparseが必要な分遅くなるとしか思えないんだけど。
実はDBMSがなんちゃってPreparedStatementしか用意されていないMySQLだったなんてオチはないよね。
Re:っていうか、これ (スコア:1)
たとえばJAVA屋さんだとDBコネクションをプーリングするのが常識みたいになってますけど、
ソーシャルアプリ業界ではプーリングするのは逆にご法度みたいな部分があったり
ジャンルによってノウハウって違いますからね。
DBあんまり詳しくないんでまちがってたらすいませんけど、毎回DB接続をオープン、クローズしてたらprepared statementでのSQL解析をするぶん速度は落ちるのではないでしょうか?
そういう意味ではPrepare statementやめて生SQL生成してそれ投げるというのはわかる気はしますね。
月間一億PV程度のしょぼいサイト(秒間最大200PVくらい)までしか扱ったことない私はprepare statement使っても問題ないとは思いますが、ソーシャルアプリとか秒間数千から数万のクエリさばく世界ですからね。
中途半端な知識の人間が根拠なしにPreparedStatementをやめたなんていってるとはおもえないんですけど・・・
Re:っていうか、これ (スコア:2)
prepared statement ってクエリキャッシュに載せるために使うものでコネクションプーリングとはあまり関係ないと思ってたんですがあってますかね?
「毎回DB接続をオープン、クローズした時のSQL解析」を高速化するためのの物という把握でした。
DBは幾らか分かるんですが、アプリは素人なんで変なコト言ってるかもしれませんけど…。
Re:っていうか、これ (スコア:1)
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=5374&forum=12 [atmarkit.co.jp]
> PreparedStatementによりプリコンパイルされたSQLは
> コネクションをクローズした後もキャッシュされているのでしょうか?
コネクションクローズしたあともプリコンパイルされたSQLが保持されているということであれば納得です!
違うなら生SQLの方がはやいですよね??
Re: (スコア:0)
> 違うなら生SQLの方がはやいですよね??
なんで?
Re:っていうか、これ (スコア:1)
【プリコンパイルあり】
prepared,execute(プリコンパイルされたSQL) 2回通信または2回実行
【プリコンパイルなし】
execute(生SQL) 1回通信または1回実行
だとおもうんですが?ちがいますか?
Re: (スコア:0)
そもそもどうしてstatementがキャッシュされることがないなんて非現実的な仮定にこだわるんですか? 性能が重要なサーバじゃなかったの?
Re:っていうか、これ (スコア:1)
ぼくが書いた内容をちゃんと読んでますか?
こだわるってるんじゃなくてわからなくてずっと質問してるんですが・・・
質問してる人間に質問で返すなと・・・
PDOでコネクションクローズしたあとでもstatementがキャッシュにのっているのであればおっしゃるとおりだと思います。
ただ、コネクションクローズしたあとでもstatementのキャッシュがつかえるのかどうかそこがわからんのです。
そしてその部分はだれも教えてくれない・・・
Re: (スコア:0)
毎回コネクションクローズしてたらそのコストがでか過ぎて、
preparedだろうとそうでなかろうと大した差がない。
そもそもプーリングがご法度って本当なの?
ソース出してくれませんかね?
Re:っていうか、これ (スコア:1)
もう他の人がだしてるよ・・・
Re: (スコア:0)
Re:っていうか、これ (スコア:1)
ソーシャルアプリ界隈って言ったのが癪に障ったのかえらく叩かれてしまいました。
ソーシャルアプリに限らずPHPの高負荷サイトでpconnect使わないのは比較的常識の部類だと思ってたんですけどね(グッドノウハウなのかバッドノウハウなのかはさておいてね)。
それにしても「使う技術によってノウハウは違うよ」って言っただけのつもりだったのに何でこんなに叩かれたんだか・・・
Re: (スコア:0)
なら最初からPHP+MySQLの話と書けばいいのに。
それに叩かれてるのはpconnectじゃなくてprepared statementの話だよね。
prepared statementでなく、生文字列を組み立てて速度を稼ぐのは明らかにバッドノウハウ。
他のツリーにもあるけど、PDOとMySQLの実装がバカなのが原因。
Re: (スコア:0)
Re:っていうか、これ (スコア:2)
>PHPの高負荷サイトでpconnect使わないのは比較的常識の部類
それは比較的常識に考えていいけど、まぁバッドノウハウの類だな。
pconnect 自体が単なる永続的接続で、にコネクションプールと呼べる物じゃ無いって事を忘れてるよ。
Re: (スコア:0)
そういう当てこすりをしたいなら、技術論の場には出てこないほうがいいんじゃないかな。
多くは技術的に正しいか正しくないかを論議しようとしてるよね。
#1926755 の論点を洗うと、
1. コネクションプーリングはソーシャルアプリ界隈ではご法度
2. Prepared Statementを使うとSQLのパースは遅いのではないか
の二点になると思うけど、これでいい?
1に関して繋がっているのは #1926785 #1926836 #1927085 で叩きになってるようには見えないけどどうかな。
#1926793 の「本当にこれ合ってるの?」に対して反論が出てきてないのが気になる。
#1927085 の通りだとするとMySQL特有で、PHP+Pos
Re:っていうか、これ (スコア:1)
http://srad.jp/security/comments.pl?sid=527293&cid=1926729 [srad.jp]
で、私の意見は「使う技術によってノウハウは違うよね?」「詳細聞かずに残念いっちゃだめだよ」の2点ですよ?
他の発言に関しては質問してる内容を質問でかえされたから私はこう思ってるんだけど違うのかな?って考えをいっただけで議論するつもりはないですよ・・・
そんな議論ができるほど立派なエンジニアではないですから・・・
> 叩きが入っているようには見えないんだがどう?
その後馬鹿馬鹿言われてたので、たたかれたと表現しましたけどね・・・馬鹿とかいわれなければたたかれたとは言いませんよ。それとも馬鹿と相手に対して言い放つのは議論であって叩いてないということでしょうか?
Re:っていうか、これ (スコア:1)
逆。prepared statementを使うとクエリキャッキュがきかない
http://dev.mysql.com/doc/refman/5.1/ja/query-cache-how.html [mysql.com]
Re:っていうか、これ (スコア:2)
http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache.html [mysql.com]
Re:っていうか、これ (スコア:2)
読んでみたら、もう少しバージョンによる制限がきつかったようで。
http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache-operation.html [mysql.com]
とあるので、5.1.21以降であれば普通に使えるように読めますが、いかがでしょう?
# しかし、キャッシュが使用されない場合の注意書きが多いですね…
Re: (スコア:0)
Re:っていうか、これ (スコア:2)
色々コメントついてるけど論点がずれてない?
別にprepared statement が重要な訳じゃないと思うけど。
要はエスケープ処理を確実にする為なんだからプレースフォルダを解決する関数ひとつ作ればいいだけじゃん。
1っ箇所だけならまず間違えないし、prepared statement 使ってる人なら簡単な説明で理解してくれるはずだし。
Re: (スコア:0)
これってどんな理由でご法度にしているのでしょう。
効率性の問題ではないように思えるのですが。
Re: (スコア:0)
自己レス。
元ネタはきっとこの辺ですね。
Lampで作るソーシャルアプリの負荷対策~アプリとインフラの調和のテクニック~ [slideshare.net]。
DB接続への待ち行列を少なくすることが重要な負荷対策であると。
接続だけして作業してないコネクションがDBの負荷に影響を与えるのだろうかと。
メモリ増やしてDB側の接続上限を上げればよいだけに見えますが、少し実験してみないと分からないところで。
Re: (スコア:0)
RDMS の機能の半分を占める (!) コネクション認証/識別を使用してない、ってことと等価ですからねえ。
計測してみたよ (スコア:0)
論より証拠で、JavaでPreparedStatementを使う場合と、そうでない場合を比較してみました。
単純なSELECT文で、以下の条件で10000回ループさせました。
1. PreparedStatementをループの外で生成して使い回し
2. 1回ごとにPreparedStatementを生成
3. 1回ごとにSQLを生成して、executeQueryで生のSQLを実行
1.が速いのは当然として、2と3のどちらが速いかが問題だと思いますが、結果としては平均で、
1. 403ms
2. 7124ms
3. 7523ms
となりました。つまり、PreparedStatementを使わない理由はないということです。
Java+Oracleでのテストなので、PHP+MySQLがヘボイ実装という可能性はありますが:P
Re:計測してみたよ (スコア:1)
比較するならば Java+MySQL で同じテストをしてみましょう。
Re: (スコア:0)
さらに、PHP(ウェブ)の場合リクエストごとに接続するのがスタンダードだから、毎回Prepare作成しないといけない。
一度Prepareしたものを同スクリプト内で再利用する機会はほとんどない。
ローカルアプリのように起動したら終了するまで接続を維持するようなものならいいですけど、ウェブのようなものには向いてないような気もする。
ただの勉強不足ですけど。
Re:計測してみたよ (スコア:2)
DBMSの物とバージョン、使ったライブラリを明示するべきかと
Re:計測してみたよ (スコア:1)
ちょっと気になったので、PHP上でDBおよび接続手段を変えて測ってみました。
FreeBSD 7.2-RELEASE/amd64上で、PHP 5.3.6、MySQL 5.1.33、PostgreSQL 8.4.6 を使ってます。
integer な主キーに対するSELECTを1万回実行した時の、1回あたりの処理時間(マイクロ秒)
(接続は、単なるDBへの接続と切断を1万回実行)
PostgreSQL はprepareしておいた方が速いですが、MySQL は毎回生SQL文を生成してもほとんど同じ。
MySQL PDO だけは、毎回prepareしても似たような数値なので、内部で自前でSQL文を組み立ててるんだと思います。
まあ、エスケープ処理のアルゴリズムさえ間違えてなければ、その方が速いし悪いことじゃないとは思いますが…釈然としない…
あと、こうしてみると PostgreSQLは接続にかかる時間が桁違いですね。
これだと、Webアプリケーションでコネクションプーリングしたくなるのも納得です。
あくまで私の知識の範囲内ですが…… (スコア:0)
プリペアードクエリ:クライアント側で利用選択する機能。
実行計画を事前に作成し、実際にいれる値だけを変えて連続実行
→ どちらかというと実行計画の使いまわしより
プレースホルダによる自動エスケープの恩恵が大きい。
ステートメントキャッシュ:サーバ側自動機能。
プリペアードクエリの実行計画をキャッシュ。
→ あまり意味がないとのことでサーバ側で無効にされている
クエリキャッシュ:サーバ側自動機能。意外とパフォーマンスに影響
問い合わせで同じデータを返すものをキャッシュ。
→ パラメータ付きのプリペアード
Re: (スコア:0)
ちょっと想像してみたら分かることですが、
まともな実装なら明らかにPreparedStatementの方が速いですね。
パラメータが変わっても同じSQLとみなされるので、SQLのパース作業が2回目以降は不要になるし。
# 検索条件が動的に変わる場合も、?付きの条件を動的に生成すべきですね
Re: (スコア:0)
PHPを下に見てる割にはJavaの事しか語れないんだね。
そもそも言語も実装も異なるのに、PHPで使用していない機能をJavaで語っても仕方ないでしょうが。
PHPもMySQLもよく分かりませんって素直に言えよ。
Re: (スコア:0)
Re: (スコア:0)
・SQLがキャッシュされないので遅い
・SQLインジェクション脆弱性を防げない
つこと。
ootoriはたしかにバカだが、本当にバカなのはPDOとMySQLの実装者で、全世界のPHPユーザが迷惑してる。
FUD? (スコア:1)
ソース見たけど、mysql_stmt_prepare()呼んでるよ。
php-5.3.6/ext/pdo_mysql/mysql_driver.c
Re: (スコア:0)
PHP+MySQLの組み合わせはほとんど使ったことないけど
要するに、PHP+PDO+MySQLの組み合わせでは、いくらprepareを使用しても、exeture時に?をPHP側で文字列置換したSQLをDBに投げるだけなので
・SQLがキャッシュされないので遅い
・SQLインジェクション脆弱性を防げない
これマジ?
でも生SQLに展開されるのならMySQLのクエリキャッシュ(笑)は有効になるんじゃ?
Re: (スコア:0)
MySQL関係なくね?
それともOracle(wなら賢くキャッシュしてくれたりSQLインジェクションを防いでくれるのかよ。
Re: (スコア:0)
簡単に言うと直書きされたSQLを勝手にバインド変数に置き換えてからキャッシュ探してくれる。
逆にバイント変数使っても変数の中身見て実行計画変更する機能まである。
Re: (スコア:0)
昔DB2使ってたけど当然のようにキャッシュもインジェクション防ぐ機能もあるよ。
むしろエスケープ(笑)とかしてるほうが珍しい。
正直な感想 (スコア:0)
そもそも (スコア:0)
種種雑多なデータを一つのDB(?)で管理してることが間違いじゃないの?
認証情報や顧客情報や内部ネットワーク情報なんて外部からアクセス制限
もなしにアクセスできちゃうのが間違いじゃ?
こういった情報は特定のプログラムからしかアクセスできないとか
プログラムの実行自体にも認証が必要とか、なんか色々あると思うん
だけど。
ずいぶん昔、企業のホームページ用のサーバーでカタログ請求した
ユーザーのメールアドレスはそのサーバーに保存せずローカルに接続された
別のサーバーに転送して元のサーバーには置かないようににしてあった。
大事なデータの取り扱いってこういうことだと思う。
Re: (スコア:0)
それをしてたって話でしょ(?)