コードでセキュリティを攻略:SQLインジェクションの共有と学習

簡単に言うと、SQL(Structured Query Language)はリレーショナルデータベースと通信するための言語です。開発者、データベース管理者、アプリケーションが日々生成される膨大なデータを管理するために使用するクエリ言語です。
データは急速に世界で最も価値のある商品の一つになりつつあります。価値があるものには、悪意のある者が利益を得ようと群がってくるものです。
攻撃者は、1998年から存在する最も古く(1998年以来!)厄介なデータ脆弱性の一つであるSQLインジェクションを悪用し、世界中の何百万ものデータベースに保存された機密情報を盗み出し、改ざんしています。これは非常に巧妙な攻撃であり、データを安全に守るためには、開発者がSQLインジェクションの仕組みと防御方法を理解しておく必要があります。
そのために、SQLインジェクションの重要な3つの側面について解説します。
- 仕組み
- なぜ危険なのか
- 防御方法
SQLインジェクションを理解する
SQLインジェクションを理解する鍵は「コンテキスト」という言葉にあります。
アプリケーション内には、「データ」と「コード」という2つのコンテキストが存在します。コードコンテキストはコンピュータに実行内容を指示するものであり、処理対象となるデータとは明確に分離されています。
SQLインジェクションは、攻撃者が入力したデータが、SQLインタープリタによって誤ってコードとして解釈されることで発生します。
一例として、Webサイトの入力フィールドに攻撃者が「' OR 1=1」と入力し、それがSQLクエリの末尾に付加されるケースがあります。このクエリが実行されると、データベース内のすべての行に対して「真」が返されるため、クエリ対象のテーブルの全レコードが取得されてしまいます。
SQLインジェクションの影響は壊滅的です。ログインページで発生すれば、ユーザー名やパスワードを含むすべてのユーザーレコードが流出する可能性があります。データを抜き出す単純なクエリが成功すれば、データを改ざんするクエリも同様に実行できてしまいます。
実際にSQLインジェクションの脆弱性がどのようなものか、脆弱なコードを見て確認してみましょう。
こちらのコードをご覧ください:
String query = "SELECT account balance FROM user_data WHERE user_name = "
+ request.getParameter("customerName");
try {
Statement statement = connection.createStatement( ... );
ResultSet results = statement.executeQuery( query );
}
このコードは、クライアントからのパラメータ情報を検証せずにSQLクエリの末尾に付加しています。そのため、攻撃者が入力フィールドやURLパラメータにコードを入力すると、それがそのまま実行されてしまいます。
重要なのは、攻撃者がSELECTクエリに「' OR 1=1」を追加できることだけではありません。攻撃者はあらゆる種類のSQLクエリ(INSERT、UPDATE、DELETE、DROPなど)を操作し、データベースがサポートするあらゆる命令で拡張できてしまうのです。何が可能かを示す優れたリソースやツールが公開されています。

この問題の修正方法は後ほど学びます。まずは、どれほどの被害が発生し得るのかを理解しましょう。
SQLインジェクションがこれほど危険な理由
SQLインジェクションによって引き起こされた侵害の事例を3つ紹介します。
- イリノイ州選挙管理委員会のウェブサイトは、SQLインジェクションの脆弱性により侵害されました。攻撃者は20万人の米国市民の個人データを盗み出しました。発見された脆弱性の性質上、攻撃者はデータを改ざんすることも可能でしたが、実際には行われませんでした。
- 南アフリカのウェブホスティング企業であるHetznerは、侵害を受け、4万件の顧客記録が流出しました。SQLインジェクションの脆弱性により、データベース内のすべての顧客記録が盗まれる可能性がありました。
- 米ミネソタ州のキリスト教系金融サービスプロバイダーも、SQLインジェクションによって侵害されました。約13万人の顧客の口座番号を含む口座情報が盗まれました。
機密データは、アカウントの乗っ取り、パスワードのリセット、金銭の窃取、あるいは不正行為に悪用される可能性があります。
機密情報や個人を特定できる情報とみなされないデータであっても、他の攻撃に利用されることがあります。住所情報や政府発行の識別番号の下4桁などは、企業に対するなりすましやパスワードのリセットに悪用される恐れがあります。
攻撃が成功すると、顧客からの企業に対する信頼が失われる可能性があります。システムの復旧や規制当局による罰金には、数百万ドルのコストがかかることもあります。
しかし、必ずしもそのような結末を迎える必要はありません。
SQLインジェクションを阻止する
SQLインジェクションは、アプリケーション内の各部分を明確に区別することで防ぐことができます。コンピュータがどこまでがデータで、どこからが実行すべきコードなのかを認識できるようにするのです。これにはパラメータ化クエリを使用します。
SQLクエリでパラメータを使用すると、SQLインタープリタはそのパラメータをデータとしてのみ扱います。コードとして実行されることはありません。
例えば、「' OR 1=1」といった攻撃は機能しません。データベースは「OR 1=1」という文字列を検索しますが、データベース内にそのようなデータは存在しないためです。データベースは単に「申し訳ありませんが、見つかりませんでした」と返すだけです。
Javaにおけるパラメータ化クエリの例は以下の通りです。

ほとんどの開発フレームワークには、SQLインジェクションに対する防御機能が組み込まれています。
.NETファミリーのEntity Frameworkのようなオブジェクト関係マッピング(ORM)は、デフォルトでクエリをパラメータ化します。これにより、特別な対応をしなくてもSQLインジェクションを防ぐことができます。
ただし、使用しているORMの仕組みを理解しておく必要があります。例えば、Javaの世界で人気のあるORMであるHibernateも、誤った使い方をすればSQLインジェクションに対して脆弱になる可能性があります。
クエリのパラメータ化は最初にして最善の防御策ですが、他にも方法はあります。ストアドプロシージャもSQLパラメータをサポートしており、SQLインジェクションの防止に利用できます。ただし、ストアドプロシージャも正しく構築されていなければ効果がない点に注意してください。
// ここも必ずバリデーションを行うこと
String custname = request.getParameter("customerName");
// 攻撃を検知するためにバリデーションを実行
String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";
PreparedStatement pstmt = connection.preparedStatement( query );
pstmt.setString(1, custname);
ResultSet results = pstmt.executeQuery( );
入力値は常にバリデーション(検証)とサニタイズ(無害化)を行ってください。「OR 1=1」のような文字列は、アプリケーションの正当なユーザーが入力するものではないため、許可する必要はありません。ユーザーにエラーメッセージを表示するか、処理を行う前に該当する文字列を取り除いてください。
とはいえ、バリデーションとサニタイズだけに頼ってはいけません。巧妙な攻撃者はその回避策を見つけ出します。これらは優れた多層防御(DiD)戦略ではありますが、パラメータ化こそがあらゆるリスクを網羅する確実な方法です。
もう一つの優れた多層防御戦略は、データベースにおける「最小権限の原則」の適用と、入力値のホワイトリスト化です。最小権限の原則を強制することで、アプリケーションがデータベース内で持つ権限を制限できます。万が一攻撃者にアクセスされたとしても、被害を最小限に抑えることができます。
OWASPが提供する SQLインジェクション対策チートシートでは、さまざまな言語やプラットフォームにおける脆弱性の対処法が紹介されています。さらに一歩進んで、お好みの言語でSQLインジェクションの課題に挑戦してみませんか?まずは人気の高い以下の課題から始めてみましょう。
学習の始まり
SQLインジェクションの理解と修正に必要な手順について、大きな進歩を遂げましたね。素晴らしいです!
SQLインジェクションがどのように発生するかを解説しました。通常、攻撃者が入力値を利用してデータベースクエリを操作し、悪意のある目的を達成しようとします。
また、SQLインジェクションの脆弱性が悪用された場合に生じる被害についても見てきました。アカウントの乗っ取りや数百万ドルの損失など、悪夢のような高額な損害につながる可能性があります。
SQLインジェクションを防ぐ方法も確認しました:
- クエリのパラメータ化
- ORM(オブジェクト関係マッピング)やストアドプロシージャの使用
- ユーザー入力の検証とホワイトリスト化
あとはあなた次第です。実践こそが習得への近道です。SQLインジェクションに関する学習リソースを確認し、プラットフォームの無料デモを試してみませんか?Secure Code Warriorへの道が大きく開けるはずです。
AI主導の開発をリリース前にガバナンスする
AIを活用したリスク測定、コミット時のセキュアコーディングポリシーの強制、そしてSDLC全体を通じたセキュアなデリバリーの加速を実現します。
他のブログ記事を見る
セキュアコーディング、AIガバナンス、ソフトウェアリスク管理に関する専門的なコンテンツをご覧ください。
%252520%252520(3).avif)
Supercharged Security Awareness: How Tournaments are Inspiring Developers at Erste Group
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Security as culture: How Blue Prism cultivates world-class secure developers
Learn how Blue Prism, the global leader in intelligent automation for the enterprise, used Secure Code Warrior's agile learning platform to create a security-first culture with their developers, achieve their business goals, and ship secure code at speed
AIを活用した開発をリリース前にセキュアに
開発者のリスクを可視化し、ポリシーを適用することで、ソフトウェア開発ライフサイクル全体における脆弱性を未然に防ぎます。



.avif)