SQLインジェクション(SQLi)の歴史はInternet Explorer(Z世代によれば文明の始まり)よりも古い。SQLインジェクションによって引き起こされた侵害は何千件もあり、それを防ぐためのベストプラクティスやツールは枚挙にいとまがない。ですから、私たちはこれらの侵害から教訓を学び、SQLiはもはや問題ではないのです。
私たちは、オープンソースとクローズドソースのプロジェクトで発見されたSQLインジェクションの数を監視し、私たちが良くなっているかどうかを確認してきました。最近、MOVEitのSQLインジェクション侵害から盗まれたデータがAmazonのような企業に売られているというニュースがありました。
ネタバレになるが、SQLインジェクションを防ぐのはまだ苦手だ。
SQLインジェクションとは?
SQLiは、プログラムがSQLデータベースへのクエリに信頼されていないユーザー入力を直接使用した場合に発生する脆弱性です。悪意のあるユーザが自分のコードを挿入し、クエリを操作することで、悪意のあるユーザが個人データにアクセスしたり、認証をバイパスしたり、データを削除したりすることが可能になります。以下の例は、ユーザー・ログイン・ページに対する安全でない SQL クエリが、SQLi 認証バイパス攻撃に対してどのように脆弱であるかを示しています。
コード・インジェクションやクロスサイト・スクリプティング(XSS)など、インジェクション攻撃にはさまざまな種類がある。しかし、特にSQLiは、非常に長い間、侵害において顕著な役割を果たしており、2024年になってもまだこれについて議論する必要があるということは、多くの人にとって衝撃的なことです。
SQLi攻撃の仕組み
1.脆弱なクエリ
ユーザ入力が直接クエリに使用される脆弱なクエリの例

2.SQL インジェクション攻撃
認証ページのユーザ入力フィールドに SQL が注入される。

3.ペイロードを使用したクエリの実行
ペイロードはパスワードチェックをコメントアウトするので、 クエリはこのステップを無視する。

数字で見るSQLインジェクション
- オープンソースプロジェクトで発見された脆弱性の6.7%はSQLiである。
- クローズド・ソース・プロジェクトの場合は10%!
- オープンソースプロジェクトにおけるSQLインジェクション( SQLiを含むCVE)の総数は、 2264件(2023年)から2400件(2024年 )に増加すると予想される。
- 全脆弱性に占めるSQLインジェクションの割合は、2023年から2024年にかけて、オープンソースプロジェクトで14%、クローズドソースプロジェクトで17%減少している。
- クローズドソースプロジェクトの20%以上が、セキュリティツールの使用を開始した時点でSQLインジェクションの脆弱性を指摘されている。
- SQLインジェクションの脆弱性がある組織では、SQLインジェクションサイトの平均数は、コード内の約30カ所である。
2023年と2024年の今までに、オープンソースのパッケージで発見されたSQLi脆弱性の数をレビューした。そして、Aikido Securityによって発見されたクローズドソースプロジェクトと比較しました。驚くなかれ、クローズド・ソース、オープン・ソースの両プロジェクトにおいて、SQLインジェクションの衝撃的な件数が依然として確認されている。2024年にオープンソースプロジェクトで発見された全脆弱性の6.7%がSQLインジェクションの脆弱性であるのに対し、クローズドソースプロジェクトで発見された脆弱性の10%がSQLインジェクションの脆弱性でした。これはそれほど多くないように見えるかもしれないが、2024年になっても、我々が知っている最も基本的な脆弱性のいくつかに対処するのに苦労しているということは、率直に言って衝撃的である。
唯一の朗報は、発見された全脆弱性の割合として、この数字がオープンソースでは2023年から14%減少 し、クローズドソースプロジェクトでは17%減少して いることである。しかし、発見されたSQLiの総数は、2023年の2264件から、オープンソースプロジェクトでは2024年末までに2400件以上に増加すると予想されています。


SQLインジェクションの防止
どうやら、SQLインジェクションを防ぐ方法について、インターネット上にはまだ十分な情報がないようだ:
1.プリペアド・ステートメントとパラメータ化クエリの使用
このブログ記事の冒頭の例では、信頼できないユーザー入力を直接クエリで使用しているため、脆弱なコードを示しました。これを避けるためには、プリペアド・ステートメントを使うべきである。これにより、コマンドとデータストリームが分離され、問題が完全に解決される。素晴らしい解決策だが、常に可能とは限らないし、使われるわけでもない!
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
user_id = 5 # 安全な入力例
# パラメータ化クエリを使用した安全なクエリ
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id))
2.サーバーサイドの入力/スキーマ検証
入力バリデーションはSQLiを防ぐのに効果的である。例えば、もしあなたのAPIがメールアドレスやクレジットカード番号を期待するのであれば、そのような場合のためにバリデーションを追加するのは簡単です。
3.SAST と DAST ツールを使って SQLi を発見する。
SQLiの最も恐ろしい要素のひとつは、敵に発見されやすいことである。その理由の一つは、DASTのようなツールが自動的にSQLiを発見することができるからです。これを利用し、開発プロセスにこれらのツールを導入することで、早期に発見することができます。
Aikido ような次世代SASTツールは、プラットフォーム内から問題を自動修正することもできる。

4.アプリ内ファイアウォールの実装
アプリ内ファイアウォールは、アプリケーション内のトラフィックとアクティビティを監視し、インジェクションやSQLiを含む攻撃を検出することができます。アプリケーション内部に設置され、予想されるクエリをトークン化し、クエリのコマンド構造を変更するリクエストをブロックできるため、従来のWAFよりも効果的です。
Aikido 新発売のための恥知らずなプラグイン: Zenは、実行時に安心のアプリ内ファイアウォールです。Zenを入手すれば、クリティカルなインジェクション攻撃やゼロデイ脅威がデータベースに到達する前に、リアルタイムで自動的にブロックしてくれます。
5.可能な限り動的SQLを避ける
文字列の連結による動的なSQL生成は、SQLインジェクションに対して非常に脆弱です。可能な限り、静的で事前に定義されたクエリやストアドプロシージャに固執し、SQL構造についてユーザが生成したコンテンツに依存しないようにしてください。
6.リストアップとエスケープを許可する
動的なテーブルを問い合わせる場合や、ユーザ定義のカラムや方向で並び替えを行う場合など、動的SQLを避けられない場合があります。そのような場合は、正規表現による許可リストかエスケープに頼るしかありません。 エスケープとは、'>'のようなコードで使われる危険な文字を含むユーザー入力を、安全な形に変換することです。その前にバックスラッシュを追加したり、シンボルコードに変換したりします。これはデータベースの種類によって異なるだけでなく、charsetなどの接続設定にも依存することに注意してください。
SQLiの終焉はあるのだろうか?
発見されたSQLi脆弱性の数がいくらか大幅に減少しているという事実には期待が持てるが、ゲーム『DOOM』以前の脆弱性がいまだにこのような重大な脅威となっていることに落胆せざるを得ない。実際のところ、これ以上良くなるとは思えない。私たちがより速くコーディングするためのツールを導入するにつれ、開発者は核となるコーディングの原則に触れなくなってきており、これらのAIツールは、インジェクション脆弱性を含む脆弱なコードを提案するのが下手なことで有名だ。
とはいえ、悲観的な話ばかりではない。こうした脆弱性を発見し、修正する上ではるかに効果的な新世代のSASTツールには、脅威の状況を劇的に変える力がある。
とりあえず、これで失礼する:
Aikido AI SAST AutofixによるSQLインジェクションの発見と自動修正
Zenをチェックアウトし、インジェクション攻撃を未然に防ぐ
ボーナス:SQLの歴史
アプリケーションのセキュリティについて話し始めて以来、私たちはSQLインジェクションについて話してきました。2003 年の最初の OWASP トップ 10 チャートでは、SQL インジェクションは 7 位に選ばれました。最初の 最初の大規模攻撃SQLインジェクションが関与した最初の大規模な攻撃として記録されているのは、アパレル企業Guessが標的にされ、クレジットカード番号が流出した事件である。それ以来、SQLインジェクションはセキュリティ・ヘッドラインの常連となっている。
