0

だから、バインディングに関するいくつかの記事を読んで、正直に言うと、本当の価値を理解するのに苦労している利点は理解しています. 利点は非常に明確ですが、実際の例を理解することはできません。

ユーザーが値を入力して、SQL インジェクションが発生する可能性のある場所に送信できる簡単なクエリを誰かに見せて、バインディングがそれを回避する方法を教えてください。これにより、何が起こっているのかが非常に明確になるはずです。

標準のMySqlステートメントから移行するPDOは明らかに初めてです。

また、ユーザー入力が関係する場合にのみ必要であると想定するのは正しいですか? そうでない場合は、バインドをスキップできますか?

4

1 に答える 1

1

私のプレゼンテーションSQL Injection Myths and Fallacies をご覧ください。

または、私がプレゼンテーションを行っているウェビナーの録画をご覧ください: http://www.percona.com/webinars/2012-07-25-sql-injection-myths-and-fallacies (無料ですが、登録が必要です)。

次のようないくつかの例を示します。

ユーザーがパスワードを変更できるページがあり、ユーザーが次のような URL を使用してそのページにアクセスするとします。

http://example.com/changepass.php?acctid=1234 &pass=xyzzy

(もちろん、通常は POST リクエストを使用しますが、簡単に説明するために、この GET 形式を使用します。)

そのページのスクリプトには、次のような SQL 更新ステートメントがあります。

UPDATE Accounts 
SET password = SHA2('$password')
WHERE account_id = $account_id

悪意のあるユーザーが次のようにパラメーターを巧妙に設定した場合はどうなるでしょうか。

http: //example.com/changepass.php?acctid= 1234 または TRUE 
&pass= xyzzy'), admin=('1

次に、SQL は次のステートメントを実行することになります。

UPDATE アカウント SET password = SHA2(' xyzzy'), admin=('1 ') <br> WHERE account_id = 1234 OR TRUE

パスワードを設定するだけでなく、テーブル内の別の列を設定して、ユーザー管理者権限を付与します。また、WHERE 句への挿入により、ログインしているユーザーだけでなく、サイト内のすべてのユーザーに変更が適用されます。

パラメータの値は次のとおりです。SQL 式では、1つのパラメータが常に1 つの値として扱われます。

つまり、そのパラメーターに渡す文字列にインジェクションを悪用する SQL 構文が含まれていたとしても、パラメーターを使用すると、単一の文字列または数値以外のものとして解釈できないことを意味します。ORそのため、文字列を終了したり、SQL ステートメントの構文やセマンティクスを変更するような括弧やその他のものを含めたりすることはできません。

したがって、バインドされたパラメーターを使用すると、次のようになります。

UPDATE アカウント SET password = SHA2(' xyzzy\'), admin=(\'1 ') <br> WHERE account_id = ' 1234 OR TRUE '

スペースや引用符が含まれているパスワードは変に見えるかもしれませんが、SQL の意味は変わりません。そして、WHERE 句はその文字列の整数値を使用します。これはちょうど 1234 になります。


あなたのコメントについて:

コードのすべての行をトレースしたわけではありませんが、実行のすべての段階で SQL ステートメントの文字列を値から分離したままにしていると思います。ある時点で、SQL が解析され、何らかの内部形式 (人間が判読できるテキストではない) で表されます。次に、パラメーター値がこれに結合されますが、それらは強制的に単一の構文要素になります。ポイントは、クエリが解析されたに結合されるため、パラメーター値が構文を変更する方法がないということです。

1 つの例外: 一般的なクエリ ログは、指定された実行のパラメーターと組み合わせてクエリをログに記録する目的で、値を元の SQL 文字列に補間します。ただし、この結合されたクエリ文字列は実行されません。

于 2013-08-19T03:03:56.747 に答える