アカウント名:
パスワード:
例えばOracleDBMSなんかだと, 一回構文解析したSQLはキャッシュ上に保存しておいて, 同じ字面のSQLが再発行された場合にはキャッシュ上の解析済みのコードを実行するようになっています. この効果は抜群で, 1回目には100m秒単位でかかっていた解析処理が2回目以降は10m秒未満から1m秒単位で実行可能になり, それに応じてCPU負荷も減ります.
そのため, OracleDBMSを利用したエンタープライズシステムではSQLの動的生成は論外に近く, 基本的にPreparedStatementを使ってパラメータのみを変更するのが定石になっています. 副次的に, PreparedStatementを使うと, かなりの割合のSQLインジェクションを防ぐことができるという利点もあります.
そういった開発パターンに慣れている立場から見ると, それほど容易にSQLインジェクションを可能にする環境というのがどういうものなのか, 逆に興味があります.
# 因みにOracle9iのJDBCだとバインド変数でVARCHAR2(4000)にShiftJISの2byte文字を2000文字入力できなかったりします。
それはおそらくDBの設計, さらに遡れば業務分析やシステム構成設計がまずいと思います. 平たく言えば, 使い方が悪いってやつですね. だって, バインド変数で渡さなければならないものって通常はキーパラメータですから, 普通に考えればそんなに長大なキー項目はハッシュやB+木といった一般的な検索方法では効率が悪いし, インデックスキャッシュの使用効率も悪くなって性能がた落ちっていうのが見えますから.
ただ, 上流からそういう設計でやれと言われたらやらなくちゃいけない立場も分かるし, そういうダメ設計になった理由もあらかた想像がついちゃうんですけどね.
13.2 The PreparedStatement InterfaceThe PreparedStatemtnt interface extends Statement, adding the ability to set values for parameter markers contained within the statement.
PreparedStatement を使っていても危険な場合で、自分が知っている範囲だと。
LIKE 演算子の場合は SQL インジェクションとは言わないのかもしれませんが、サーバーの負荷を上昇させたりはできなくはないと思うのですよ。
個人的にはですね。SQL インジェクション云々以前に、' を入力したらエラーになるのを仕様とか言い張るのがどうかしているんじゃないかと思うのですよ。' は入力しないで! ってマニュアルに一言書くだけじゃんと言われてしまったり。
エンタープライズシステムでは
直結していなくても, フロントエンドを一枚かましてバックでOracleなんてのは普通ですよ. いわゆる3階層(バックエンドDB, アプリケーションサーバ, Webブラウザ)構成システムってやつです. よく/.Jのコメントで「社内システムがIE6までしか対応していない」とかの話が出たらこの類と考えて良いでしょう. また保険会社なんかの小規模の代理店・取引先が多いB2Bシステムでは, 閉じたネットワークではなく通常のインターネットで接続していることも多いと思われます.
フロントエンドを一枚かましてバックでOracleなんてのは普通です
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
私は悩みをリストアップし始めたが、そのあまりの長さにいやけがさし、何も考えないことにした。-- Robert C. Pike
SQLは人が手で入力して使うツール (スコア:1)
コードにSQLの断片を埋め込んで、パラメータを文字列連結して、ランタイムでコードがSQLを生成するのは、全面的にやめるべきだと思います。
メンテナンス性の為や手抜きのために複雑な構文解析機を通して検索ロジックを実行時に機械語へビルドしている事になるわけですが、安全なサービスの構築のためにはロジックは静的に用意されているべきだと思います。
上に ORM をのっけて蓋をするのでもいいんですが、SQLという文字列でロジックをDBSに渡すというのは、無駄が多すぎる気がしてなりません。
良い解決策をもっているわけではないのですが…
Re:SQLは人が手で入力して使うツール (スコア:4, 興味深い)
例えばOracleDBMSなんかだと, 一回構文解析したSQLはキャッシュ上に保存しておいて, 同じ字面のSQLが再発行された場合にはキャッシュ上の解析済みのコードを実行するようになっています. この効果は抜群で, 1回目には100m秒単位でかかっていた解析処理が2回目以降は10m秒未満から1m秒単位で実行可能になり, それに応じてCPU負荷も減ります.
そのため, OracleDBMSを利用したエンタープライズシステムではSQLの動的生成は論外に近く, 基本的にPreparedStatementを使ってパラメータのみを変更するのが定石になっています. 副次的に, PreparedStatementを使うと, かなりの割合のSQLインジェクションを防ぐことができるという利点もあります.
そういった開発パターンに慣れている立場から見ると, それほど容易にSQLインジェクションを可能にする環境というのがどういうものなのか, 逆に興味があります.
Re:SQLは人が手で入力して使うツール (スコア:1, 興味深い)
PostgreSQLだろうがMySQLだろうがSQLServerだろうがACCESSだろうが一緒です。
# でも、その例だとPreparedStatementにつっこむSQLは動的生成してんじゃないの?
# 組み立ててなくともアドホックなクエリなんだから扱いは一緒だと思うぞ。
# 静的というならストアドなりDBMS側に持たさないと。
ところでさ、昔ながらのクラサバ構成でも入力された値をそのままSQL文に繋げて実行するなんてことはしなかったよね。
「SQLインジェクション」なる言葉ってWebアプリが流行ってから出てきただと思うのだが違う?
それ以前からありますか?
どうもDBMSが何なのか解ってない連中が使い出したあたりが根っこなのかなぁと。
# 因みにOracle9iのJDBCだとバインド変数でVARCHAR2(4000)にShiftJISの2byte文字を2000文字入力できなかったりします。
# 悲しいことにバインド変数も万能ではないです。ちゃんとドキュメントに書いてあるんですけどね。
# 10gか11gのドライバで変わってるかもしれないけど。
Re:SQLは人が手で入力して使うツール (スコア:1, 参考になる)
JDBC Thinの10.1.0.4から制限が撤廃されました。
Re:SQLは人が手で入力して使うツール (スコア:1)
それはおそらくDBの設計, さらに遡れば業務分析やシステム構成設計がまずいと思います. 平たく言えば, 使い方が悪いってやつですね. だって, バインド変数で渡さなければならないものって通常はキーパラメータですから, 普通に考えればそんなに長大なキー項目はハッシュやB+木といった一般的な検索方法では効率が悪いし, インデックスキャッシュの使用効率も悪くなって性能がた落ちっていうのが見えますから.
ただ, 上流からそういう設計でやれと言われたらやらなくちゃいけない立場も分かるし, そういうダメ設計になった理由もあらかた想像がついちゃうんですけどね.
Re: (スコア:0)
繰り返す場合、単純に構文解析のオーバーヘッドが削れて速くなると思ってるんですが。
Re: (スコア:0)
S2JDBC [seasar.org]のやりかたはどの辺だと見なされるのか興味あります。
「流れるようなインターフェース」のせいで、
生成し得るSQLのバリエーションが凄く多いうえに、
同じ検索
Re: (スコア:0)
> それほど容易にSQLインジェクションを可能にする環境というのがどういうものなのか,
> 逆に興味があります.
PreparedStatementだと安全だと思い込んでる段階で既にヤバそうだな
ま、いいけどさ
PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1)
元のコメント主とは違いますが、PreparedStatementやまっとうなO/Rマッパーを使えば起こることは無いと認識していたのですが違うんでしょうか?
不勉強で申し訳ないですが「こういうときにヤバいぞー」というのとその場合の対策が知りたいです。
Re:PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1)
JDBC4.0のSpecificationを見ると、
と定めるのみで、私の見落とし出なければ、サニタイズについては何の規定もしていません。
紳士協定的に、もしくはデファクトスタンダード的に、もう少し言うと、親切心的に、サニタイズが実装されているのだというつもりで居た方がいいってことを、元ACさんは言いたいのでなかろうかと。
具体的な行動指針にしてみると、新しいデータベースエンジンを使う時はサニタイズに関してまずはテストをすべきじゃないか…っていう問いかけですね。
Re:PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1, 参考になる)
PEAR::DBなんかは、プリペア機能のないDBの場合はそういう動きをするようです。
Re:PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1)
型付けと字句解析が緩く、マルチバイト対応の甘い言語、製品のインターフェイスには
実装上の制限などからそういうのもあるらしいですね。
>PEAR::DBなんか
納得。
>プリペア機能のないDBの場合
でも、それは無いものに対してという前提があるのに、利便上あると誤解させる機能を持たせて
誤解を招くベンダーのが悪いか、接続先DBの仕様を知らないユーザが悪いかという問題であって、
正しく実装されていないPreparedStatementの問題でアプローチを否定する理由ではないかと。
攻撃されたとしても、自社開発ではない言語標準ライブラリの脆弱性を突かれたという品質の限界
を盾に瑕疵の軽減理由になるだけでも、それを使わない理由は無いんじゃないかと思います。
もちろん、使わない理由が標準ライブラリの脆弱性を回避するために、という明らかな理由が
示された上でなら話は違うけど、そういう特殊条件でもなければ自分でシコシコ組み立てるより
ライブラリがシコシコ組み立てる擬似PreparedStatementであれ、使わない理由は小さいと思う。
Re:PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1)
PreparedStatement を使っていても危険な場合で、自分が知っている範囲だと。
LIKE 演算子の場合は SQL インジェクションとは言わないのかもしれませんが、サーバーの負荷を上昇させたりはできなくはないと思うのですよ。
個人的にはですね。SQL インジェクション云々以前に、' を入力したらエラーになるのを仕様とか言い張るのがどうかしているんじゃないかと思うのですよ。' は入力しないで! ってマニュアルに一言書くだけじゃんと言われてしまったり。
Re: (スコア:0)
参考:Java の PreparedStatement で MySQL の LIKE を扱う方法 [nilab.info]
>サーバーの負荷を上昇させたりはできなくはない
JDBCサイドでPreparedStatementとtimeoutの設定するのと、インフラ的にDDoS対策をするので充分。
もちろん、インデックスや分割などの各種チューニングは当然されているものとして。
>' を入力したらエラーになるのを仕様とか言い張るのがどうかしているんじゃないか
まあ、'でエラーはともかくRFCに併せて入力しないでと断る状況はあり
Re:PreparedStatementを使ってもSQLインジェクションの危険はあるの? (スコア:1)
てか、ストアドのパターンは想定してなかった。たしかに、ストアドでSQL文生成してるパターンもありうるよなぁ。
Re: (スコア:0)
私は未だに理解できないのですが。
Re: (スコア:0)
SaaSってるならわかりますが、それならそもそもoracle云々ってなりませんよね。
Re:SQLは人が手で入力して使うツール (スコア:1)
直結していなくても, フロントエンドを一枚かましてバックでOracleなんてのは普通ですよ. いわゆる3階層(バックエンドDB, アプリケーションサーバ, Webブラウザ)構成システムってやつです. よく/.Jのコメントで「社内システムがIE6までしか対応していない」とかの話が出たらこの類と考えて良いでしょう. また保険会社なんかの小規模の代理店・取引先が多いB2Bシステムでは, 閉じたネットワークではなく通常のインターネットで接続していることも多いと思われます.
Re: (スコア:0)
三層とか、そういう個別サーバの粒度ではなく、一つの機能を持つサーバ群をひとまとめにして見るものです。
# もしかしたら企業文化にもよるのかもしれませんが。
受発注データの転送は、全銀とか、それなりの専用線、専用ネットワークとかが普通です。少なくとも私の周りでは。
もし通販やネット取引のようにインターネットと直結しなければならないような重要度の低いシステムがある場合、一旦インターネットからデータをもらうシステムが受け取ってからHULFTのようなファイル転送システムによって別ネットワークにある会計システムなどに伝達というのが私の周りでは良く見る光景なのですが。
しかし、違う場合もあるのですか?