one's way blog

ワクワクを生み出せるWebエンジニアを目指して。

PHPのプリペアドステートメントで実行させるSQLを確認してみた

f:id:seintoseiya:20151002165853p:plain
PHPでユーザ入力値を使ってDB操作をする際に、プリペアドステートメントを使うと安全だ。
と色んなサイトに載っています。
実際にPHPマニュアルにも明記されています。

アプリケーションで明示的にプリペアドステートメントを使用するように すれば、SQL インジェクションは決して発生しません (しかし、もし信頼できない入力をもとにクエリの他の部分を構築している のならば、その部分に対するリスクを負うことになります)。

今回はプリペアドステートメントで実際に実行させるSQLをクエリログ上で確認したいと思います。

SQLインジェクションとは

SQLインジェクションとは悪意のあるユーザから入力フィールドなどから、
アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃の事です。

例えば、以下の様なSQLがあったとして、

SELECT * FROM login WHERE pass='abcde'

abcdeの部分をユーザ入力値から取得している場合、次の様な値を入力フォームに入れられると問題が生じる。

' or 'A' = 'A

と入力されると、

SELECT * FROM login WHERE pass='' or 'A' = 'A'

というSQLが発行され、loginテーブルの内容が全て表示されてしまいます。

プリペアドステートメントはこれの対処法です。

SQLログを確認

前置きが長くなりましたが、実際に実行されたSQLを確認してみましょう。
前回作ったログインシステムを使って確認します。
ログの出力方法(MAMP)はこちらをご覧ください。

入力フィールドに以下の値を入力して実行します。

' or 'A' = 'A
ログ
SELECT * FROM login WHERE user = 'user01' AND pass = '\' or \'A\'=\'A'

'の前に\が代入され、エスケープされていることがわかります。
結果はそんなパスワードは存在しないので、ログインはできません。

他にも気にするべき事はあると思いますが、
「ユーザからの入力値でDBを操作する場合は、プリペアドステートメントを使う」という事は覚えておいた方が良いでしょう。