第2回 SQL インジェクション その攻撃と対処 NECラーニング 山崎 明子
SQLインジェクションとは? 悪意のあるSQL文やその一部を入力することで、データベースに不正にアクセスする攻撃 SQL文やその一部の入力 プログラムのミスや開発者のセキュリティに関する意識が不足している場合に発生し、大きな被害を及ぼしますが、その攻撃がどのようであるかを知り、対処すれば比較的簡単に防ぐことのできる攻撃でもあります。 SQL文やその一部の入力 不正なアクセス
どのような問題が発生? なりすまし 情報の不正取得 データの改ざん・データの削除 コマンドの実行 権利がないのにシステムにログイン : : SQLインジェクションによって、つぎのような問題が発生します。 なりすまし ユーザー名やパスワードを知らなくても、システムを利用できたりデータにアクセスできるようになります。これにより、本来利用できないユーザーによる、システムの不正利用やデータへの不正アクセスが可能になります。 情報の不正取得 本来アクセスできないデータにアクセスし、データを不正に取得できます。これによって本来公開したくない情報が漏洩する可能性があります。 データの改ざん・削除 データの改ざんや削除を行うこともできます。重要なデータが改変されたり、削除されたりすることで、システムが利用できなくなる可能性もあります。 コマンドの実行 さらには、コマンドの実行などを行うこともできます。これにより、システムが破壊される可能性もあります。 SQLインジェクションでは、このように、重要なさまざまな問題が発生します。
どのような場所で発生? すべてのデータベースにおいて すべてのタイプのアプリケーションにおいて ユーザーの入力 特定のデータベースで発生するわけではない! すべてのタイプのアプリケーションにおいて SQLを利用するすべてのアプリケーションで発生の可能性がある 実際には、特にWebアプリケーションで問題が発生 ユーザーの入力 SQL文の全部または一部として利用 SQLインジェクションは、SQL文を実行できるすべてのデータベースマネジメントシステムで発生する可能性があります。 また、すべてのアプリケーションタイプにおいて発生する可能性があります。ただ、実際にSQLインジェクションの問題が発生している例がWebアプリケーションに多いのは、その利用ユーザーが不特定多数であったり、インターネット上にさらされているためです。特にWebアプリケーションにおいては必ずチェックすべきセキュリティ項目といえます。 基本的にユーザーが入力するデータを、システムでそのまま利用することは危険ですが、さらにそれをSQL文の全部または一部として利用する際には、このSQLインジェクションが発生することを考慮する必要があります。 SQL文
攻撃のシナリオ (1) 存在するユーザー名、パスワードを入力 Tanaka P@ssw0rd1 UsesrListテーブル 攻撃のシナリオ (1) 存在するユーザー名、パスワードを入力 Tanaka P@ssw0rd1 SELECT * FROM UserList Where UserName=‘ ’ AND Password=‘ ’ Tanaka P@ssw0rd1 この例では、入力したユーザ名とパスワードのセットが既に登録済みのユーザーのリスト「UserList」に存在するかどうかをチェックし、システムやデータへのアクセス許可が与えられるシステムになっています。 たとえば、「Tanaka」さんが、ユーザー名とパスワードを入力した場合、そのユーザー名とパスワードのセットがUserListテーブルに存在する場合には、利用できるというシステムです。 UsesrListテーブル 一致しているときに・・・ Yamada pass Tanaka P@ssw0rd1 Akiko PWD : システムにアクセスOK!
攻撃例(1) ユーザー名、パスワードがわからなくても・・・ ここに何を入力したとしても・・・ ‘ OR ‘A’=‘A と入力すると・・・ 攻撃例(1) ユーザー名、パスワードがわからなくても・・・ ここに何を入力したとしても・・・ ‘ OR ‘A’=‘A と入力すると・・・ SELECT * FROM UserList Where UserName=‘ ’ AND Password=‘ ’ この時、不正なデータが入力されることがあります。 たとえば、入力されたデータがそのまま利用されるアプリケーションである場合は、入力したデータによって、条件が常にTrueになってしまいます。 この例では、パスワードの代わりに、あるいはパスワードの入力の後に、常に値がTrueになる‘A’=‘A’が入力されていることに注目してください。 また、文字列を囲んでいる‘(シングルクォーテーション)が巧妙に対応づけられていることも確認してください。 これにより、ユーザー名とパスワードのセットがわからない場合でも、このシステムを利用することができてしまいます。 SELECT * FROM UserList Where UserName=‘XX’ AND Password=‘‘ OR ‘A’=‘A’ 常にTrue システムにアクセスできてしまう! 常にTrue
攻撃のシナリオ(2) 存在する検索データをユーザーが入力 1003と、入力・・・ strSQL = 攻撃のシナリオ(2) 存在する検索データをユーザーが入力 1003と、入力・・・ strSQL = “SELECT * FROM OrderDetail WHERE OrderID = ‘ “ + + “ ‘ “; このシナリオでは、ユーザーが入力した顧客IDと一致するデータを取得します。ここでは、指定した顧客IDのデータだけが取得できるように見えます。 strSQL = “ SELECT * FROM OrderDetail WHERE OrderID = ‘ 1003 ‘ “; ターゲットデータを取得!
攻撃例(2)-1 検索データとして悪意のあるデータを入力 1003‘ OR 1=1 -- と入力・・・ ‘ を無効に True True strSQL = “SELECT * FROM OrderDetail WHERE OrderID = ‘ “ + + “ ‘ “; しかし、ここで、IDに続いて、結果がTRUEになる式をOR(論理和)を追加して入力することで、すべてのデータが取得できてしまいます。この時、SQL文の最後に、--(ハイフン2つ)を入力していることに注目してください。これはコメントアウトを意味します。これにより、その後の’(シングルクォーテーション)がコメントアウトされ、SQL文として文が成立してしまっていることがポイントです。 ‘ を無効に strSQL = “ SELECT * FROM OrderDetail WHERE OrderID =‘1003‘ OR 1=1 - - ‘ “; True すべてのデータを取得できてしまう!! True
攻撃例(2)-2 検索データとして悪意のあるデータを入力 1003‘; DROP TABLE OrderDetail -- と入力・・・ ;(セミコロン)があるため、 検索後に次のコマンドを実行 strSQL = “ SELECT * FROM OrderDetail WHERE OrderID =‘1003‘ ; DROP TABLE OrderDetail -- ‘ “; 同様に、このコメントアウトとさらに、SQL文を複数接続するための ;(セミコロン)を利用しています。 これにより、SELECT文に続いて、DROP(テーブルの削除)コマンドを実行しています。 テーブル丸ごと 削除!!
攻撃例(2)-3 検索データとして悪意のあるデータを入力 1003‘; exec xp_cmdshell('fdisk.exe') -- と入力・・・ ;(セミコロン)があるため、 検索後に次のコマンドを実行 strSQL = “ SELECT * FROM OrderDetail WHERE OrderID =‘1003‘ ; exec xp_cmdshell('fdisk.exe') --‘ “; さらに、;(セミコロン)に続いて、Windowsのシステムコマンドを実行しています。これでは、権利さえあれば、どんな処理でもできてしまいます。これによって、システムが破壊されることも考えられます。 やりたい放題!!
効果的な対策 入力された特殊文字を制御文字ではなく、文字列定数として扱うようにする 具体的な対策(1または2のいずれかを行う) パラメータ化クエリまたはストアド プロシージャを使用 アドホッククエリ(動的 SQL) を使用しない 特殊文字のエスケープ処理 ただし、すべての特殊文字をエスケープすることは困難 推奨 SELECT * FROM UserList Where UserName=@UName AND Password=@Pwd SQLインジェクションに対する効果的な対策は、シングルクォーテーションやセミコロンなど、入力された特殊文字を制御文字ではなく、文字列定数として扱うようにすることです。 そのための具体策としては、ここにあげた2つのいずれかを行う必要があります。 ひとつめは、アドホッククエリを使用せず、パラメータ化クエリ、またはストアドプロシージャを利用することです。これにより、プレースフォルダに入力されたデータを割り当てることで、単なる文字列定数や数値定数とみなすことになり、SQLインジェクションを防ぐことができます。 ふたつめは、特殊文字をエスケープ処理し、特殊な意味を持たせないようにすることです。ただし、このやり方の場合、データベースマネジメントシステムなどの違いがあるため、それを的確に把握することが困難であり、見落としなどが発生する可能性があります。そのため、ひとつめのやり方が推奨されます。 SELECT * FROM UserList Where UserName= ? AND Password= ? プレースフォルダ プレースフォルダ
高度な対策 LIKE句のワイルドカード LIKE句にプレースフォルダがある場合、これらは特殊な意味を持つ % _ 任意の数の任意の文字 _ 1文字の任意の文字 LIKE句にプレースフォルダがある場合、これらは特殊な意味を持つ ただの文字として扱いたい場合は、エスケープする必要がある % → \% _ → \_ SQL文のLIKE句では「%」と「_」はワイルドカードを表す特殊文字です。この2つの文字はパラメータ化クエリやストアドプロシージャを利用したとしても,ただの文字としてではなくワイルドカードとして扱われます。 そのため、LIKE句で,この2つの文字をワイルドカードとしてではなくただの「%」や「_」の文字として扱いたい場合は,次のようにエスケープする必要があります。 「%」→「\%」 「_」→「\_」
基本的な対策 必要最低限の権利で実行する エラーを表示しない 管理者レベルのアカウントを使用してデータベースに接続しない ユーザー入力を信頼しない 入力データのうち不要なものを削除する 有効であることがわかるまでは、利用しない 直接入力ではなく、できる限り選択式にする 開発におけるセキュリティの基本 必要最低限の権利で実行する 管理者レベルのアカウントを使用してデータベースに接続しない 不必要な権限を与えない これにより多くの問題を解決できる エラーを表示しない 最小限の例外情報のみを明らかにする あらたな攻撃の糸口をつかまれないように・・・ SQLインジェクション固有の対策に加え、基本的な対策を併せて行うことを推奨します。 まず、ユーザーの入力を信用してはいけません。さまざまなユーザーがさまざまなデータを入力することをあらかじめ予想し、ユーザが入力したデータをそのまま利用することはせず、必要なものだけを取り出し、あるいは有効だと確信できるデータだけをアプリケーションで利用するようにします。また、データを入力させる代わりに選択式にすることも効果的です。これらは、開発におけるセキュリティの基本といえます。 次に、必要最低限の権利で実行するようにします。データの削除やファイルシステムの破壊は、そもそもその権利がなければ、たとえ攻撃を受けたとしても実行はされません。常に、そのシステムを実現するための最低限の権利でアプリケーションを実行するようにします。 また、エラー表示はさまざまな開示したくない情報を開示することになることがあります。エラー情報はそのままエコーせず、必要な情報のみをユーザーに提供するようにします。それにより新たな攻撃の糸口をつかまれないようにすることができます。
効果的でない対策 基本的な対策だけを行うこと クライアントサイドのみのチェック 多層防御が重要 入力されたデータをクライアントサイドでチェックしても、サーバーへ送信される際に改ざん 最後に、SQLインジェクションの攻撃における、効果的でない対策としては、ひとつ前のスライドで紹介した「基本的な対策」のみを行うことをあげることができます。基本的な対策は、効果的な対策を補完するものではありますが、それだけで攻撃に対処できるというものではありません。セキュリティの基本的な考え方である多層防御の考えに基づき、効果的な対処と併せて基本的な対策を行ってください。 また、クライアントでデータをチェックしたとしても、サーバーへ送信されるまでに改ざんされる可能性があります。クライアントサイドでチェックしたとしても、サーバー側で必要なチェックは行うべきです。
SQLインジェクションのまとめ その攻撃を知り、適切に対処することが重要 効果的な対策 すべてのデータベースアクセスで起こる すべてのアプリケーションタイプで発生する 効果的な対策 パラメータクエリまたはストアドプロシージャを利用 基本的な対策との多層防御も大切 SQLインジェクションの攻撃を理解し、適切な対処をすることでリスクを軽減できます。 SQLインジェクションの効果的な対策と、基本的な対策の多層防御を行うことを忘れないでください。
リファレンス 開発者のためのセキュリティサイト MSDNデベロッパーセキュリティセンター 開発者向け セキュリティ オンライン セミナー http://www.microsoft.com/japan/msdn/security/ 開発者向け セキュリティ オンライン セミナー http://www.microsoft.com/japan/msdn/security/seminars/ アプリケーションセキュリティの基礎 実践! セキュアなコード記述 Part 1 実践! セキュアなコード記述 Part 2