フルスタックエンジニアのノウハウ
2021.05.21    2022.06.11

【サイバー攻撃&対策】SQLインジェクション

この記事の動画版はこちら(画像クリックでYoutubeに飛びます)

チャンネル登録お願いします!


SQLインジェクションとは?


結論から先に言うと、


SQLインジェクションとは、プログラムがデータベースを操作する際に使用する「SQL」という命令言語を、外部から意図的に改ざんすることで、データベースに不正な命令を実行させたり、データベースから情報を抜き取ったりするサイバー攻撃手法です。


個人情報やパスワードなどの機密データが抜き取られてしまったり、重要なデータがデータベースから消去されてしまうなどの危険性があります。


SQLインジェクションの「インジェクション」とは、「注入」という意味で、元々プログラムが実行しようとしている正常なSQL命令に対して、それを改ざんするような悪意のあるSQL命令を注入することで、本来とは異なる命令をプログラムに実行させてしまうという攻撃手法になります。




具体的な攻撃手法


SQLインジェクションの具体的な攻撃手法はこのようなイメージです。


アプリが扱うデータは「データベース」の中に保存されており、プログラムはデータベースからデータを取り出したり、データを登録したり、登録されているデータを変更したりする際、SQLという命令を作成して実行しています。


SQLの基本や、具体的な書き方については、こちらで解説しているので併せて学習してみてください。


関連記事

データベース操作の基礎を学ぼう!SELECT編


関連記事

データベース操作の基礎を学ぼう!INSERT編


関連記事

データベース操作の基礎を学ぼう!UPDATE編


関連記事

データベース操作の基礎を学ぼう!DELETE編


例えば、ネットショップで注文履歴を確認できる画面では、指定された注文番号を元に、注文情報をデータベースから取得するためのSELECT文が実行されています。



末尾にある「注文番号」の部分は、URLで指定された注文番号が挿入されます。


つまり、命令文の中のこの部分だけは、ユーザーが自由にいじれる部分になります。


悪意のある攻撃者はこの事を利用し、この部分に細工した文字列を注入することで、プログラムが実行しようとしていたSELECT文を改変させて、別の命令を実行させようとします。


例えば、注文番号にこのような文字列が入力された場合。


この文字列が「注文番号」の部分に挿入されると、最終的にできあがるSELECT文はこのようになります。



このSELECT文では、「codeが12345」のデータ、または「aがa」のデータという条件になっており、後者の条件である「aがa」というのは必ず成り立つので、注文テーブルの全てのデータが抽出されてしまいます。


自分の注文データだけでなく、全ユーザーの注文データを見ることができてしまうという訳ですね。


また、例えば、注文番号にこのような文字列が入力された場合。



この文字列が「注文番号」の部分に挿入されると、最終的にできあがるSELECT文はこのようになります。



SELECT文の後に続いて、「DELETE FROM order_data;」という命令が実行されてしまい

注文テーブルの全データが削除されてしまいます。


このように、プログラムが実行するSQL命令の一部分に、その命令を改変するような文字列を注入することで、本来とは異なる命令を実行させようとする攻撃が「SQLインジェクション」です。



※なお、こういった不正なアクセスを実際のWebサイトに対して実行することは犯罪行為になりますので絶対にやめましょう。

あくまで、自分でアプリを作る際の防衛知識として学習してくださいね。



対策するには?


SQLインジェクションの対策方法としては、


まず第1に「ユーザーが指定した文字列をそのままSQLに結合しない」ということです。


SQL文に外部データを挿入する際は「プレースホルダ」という仕組みを使って行います。


プレースホルダを使うことで、挿入するデータは「命令の一部」ではなく、あくまで「値」として処理されるため、もし不正なデータが挿入された場合でも、想定外のSQL命令が実行されることはありません。


プレースホルダの実際の使い方については、こちらの動画で詳しく解説していますので、ぜひ学習してみてください。


関連記事

プレースホルダとは?SQLインジェクション攻撃を回避せよ!


処理の都合で、どうしてもSQL文に直接結合しなければならないような場合は、結合する文字列を事前にしっかりエスケープ処理して、SQL命令として認識されないようにします。


また、アプリから実行しないようなSQL命令、例えばテーブルなどを削除する「DROP」命令や、テーブルから全データを消去する「TRUNCATE」命令などは、そもそも実行できないように、データベースの権限を調整しておくと安全です。


あとは、プログラムの内部的なエラーメッセージを画面に表示させないようにしておくことも大切です。


エラーメッセージには、データベースのテーブル名やカラム名、実行しようとしているSQL文など

攻撃者にとってヒントになる情報が多く含まれています。


本番公開するWebアプリでは、こういったエラーメッセージは画面に表示させないように設定しましょう。


また、アプリ外の対策として、Webアプリケーションファイアウォール(WAF)を導入することで、不正なリクエストはアプリに到達する前に遮断してくれるので、より安全になります。


レンタルサーバーなどでも、WAFのサービスが標準で提供されていたりするので、是非チェックしてみてください。



まとめ


SQLインジェクションとは、SQLの一部に不正な文字列を挿入することで、本来とは異なる命令をプログラムに実行させてしまう攻撃手法。


情報漏洩や、重要なデータの改ざんや消去などが行われてしまう危険性がある。



対策としては


・SQLを組み立てる際は、プレースホルダを使うこと。


・どうしても直接結合する必要がある場合は、エスケープ処理をしっかり行うこと。


・権限を設定して、不必要な命令は行えないようにすること。


・攻撃者のヒントとなるエラーメッセージは表示しないようにすること。


・WAFを導入すること。



・SQLインジェクション:不正な文字列挿入によるSQL改ざん⇒不正な命令の実行
・情報漏洩、データの改ざん、消去の危険性
・対策①:プレースホルダを使う
・対策②:エスケープ処理をしっかり行う
・対策③:内部的なエラーメッセージは表示しない
・対策④:WAFの導入



おすすめ記事