SQLインジェクション対策
インジェクション攻撃を防止します
「SQLインジェクション対策」はCoddyKit上の無料Cyber Security Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCyber Security Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Cyber Security Academyコースには全4レッスンが含まれています。
SQLインジェクションとは
SQLインジェクション(SQLi)は、信頼できないユーザー入力がSQLクエリに直接連結されたときに発生します。攻撃者は、アプリケーションが単なるデータとして扱うフィールドにSQL構文を紛れ込ませ、クエリの意味を変えます。
データベース全体の漏えい、ログインの回避、データの破壊につながる可能性があるため、現在も最も被害の大きいWeb脆弱性の一つです。
脆弱なクエリ
典型的な誤りは、文字列を連結することです。入力がtomであればクエリに問題はありませんが、細工された入力によってロジックが書き換えられます。
- シングルクォートによって、文字列が途中で閉じられます。
- その後のすべてが実行可能なSQLになります。
query = "SELECT * FROM users WHERE name = '" + userInput + "'";
// userInput = tom' OR '1'='1
// becomes: SELECT * FROM users WHERE name = 'tom' OR '1'='1'認証の回避
ログインフォームは主要な攻撃対象です。常に真になる条件を挿入し、残りの部分をコメントアウトすることで、攻撃者はパスワードなしでログインできます。
--という並びによって残りの節がコメントアウトされるため、パスワードの確認が無視されます。
-- attacker enters in the username field:
admin' --
-- resulting query:
SELECT * FROM users WHERE user = 'admin' --' AND pass = '...'パラメーター化クエリ
主な防御策はパラメーター化クエリ(プリペアドステートメント)です。SQLの構造はデータとは別に送信されるため、入力は常に値として扱われ、コードとして扱われることはありません。
データベースドライバーは、?プレースホルダーを指定された値に安全にバインドします。
-- Python (sqlite3 / psycopg)
cur.execute(
'SELECT * FROM users WHERE name = ? AND pass = ?',
(username, password)
)Javaのプリペアドステートメント
主要なプログラミング言語には、パラメーター化の仕組みがあります。Javaでは、Statementで文字列を組み立てる代わりにPreparedStatementを使用してください。
バインドされたパラメーターは割り当てられた場所から抜け出せないため、ここでは構造上インジェクションが不可能です。
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM users WHERE name = ?");
ps.setString(1, userInput);
ResultSet rs = ps.executeQuery();ストアドプロシージャ
ストアドプロシージャは、内部でパラメーター化された入力を使用していれば役立ちます。ただし、連結によって動的SQLを組み立てるストアドプロシージャには注意してください。同じように脆弱です。
- 安全: プロシージャにパラメーターを渡す。
- 危険: プロシージャ内で連結した文字列を
EXEC()で実行する。
入力検証と許可リスト
検証は有効な第2の防御層です。悪い文字を禁止しようとする拒否リストではなく、許可リスト(既知の安全なパターンだけを受け入れる仕組み)を使用してください。
たとえば数値IDのフィールドでは、クエリに到達する前に数字以外の入力を拒否する必要があります。
if not user_id.isdigit():
raise ValueError('invalid id')
# only then use the valueエスケープは最後の手段
引用符を手作業でエスケープする方法は壊れやすく、エラーの原因になります。データベースごとにエスケープ規則が異なり、エッジケース(エンコーディングの細工や二次SQLインジェクション)を見落とす可能性があります。
パラメーター化クエリを優先してください。特定の識別子をORMやドライバーでパラメーター化できない場合に限り、エスケープを使用します。
DBアカウントに最小権限を適用する
アプリケーションのデータベースユーザーに最小権限を適用し、インジェクションが成功した場合の被害を抑えてください。
- 必要なテーブルに対して、
SELECT、INSERT、UPDATEだけを付与します。 - アプリケーションでスーパーユーザーや
rootアカウントを決して使用しません。 DROP、FILE、管理者権限を拒否します。
GRANT SELECT, INSERT, UPDATE ON appdb.orders TO 'webapp'@'%';
REVOKE DROP, ALTER ON appdb.* FROM 'webapp'@'%';ORMとクエリビルダー
最新のORM(Hibernate、Sequelize、Django ORM、SQLAlchemy)はデフォルトでパラメーター化を行うため、インジェクションのリスクの大部分を取り除けます。
開発者が生SQLに切り替えたり、クエリビルダーで文字列補間を使ったりすると、危険が再び生じます。生SQLモードであっても、値は必ずバインドされたパラメーターとして渡してください。
多層防御
単一の対策だけでは十分ではありません。複数の防御層を組み合わせてください。
- あらゆる箇所でパラメーター化クエリを使用する(主要な対策)。
- 入力検証と許可リスト。
- 最小権限のDBアカウント。
- 既知のパターンを検知するWebアプリケーションファイアウォール(WAF)。
- SQLやスタックトレースを決して漏えいさせないエラー処理。
簡単な確認
主な防御策についての理解を確認しましょう。
まとめ
SQLインジェクションの仕組みと、その防止方法を学びました。
- SQLiは、信頼できない入力をクエリに連結することで発生します。
- パラメーター化クエリが主な防御策です。
- 許可リストによる検証、最小権限のDBアカウント、WAFを追加します。
- 手作業によるエスケープと、ストアドプロシージャ内の動的SQLは避けます。
多層防御によって、一つのミスが侵害につながるのを防げます。
よくある質問
「SQLインジェクション対策」レッスンは無料ですか?
はい。「SQLインジェクション対策」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Cyber Security Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Cyber Security Academyコースには全4レッスンが含まれています。
「SQLインジェクション対策」で何を学びますか?
インジェクション攻撃を防止します ブラウザで直接実行するハンズオンコードでCyber Security Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Cyber Security Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのCyber Security Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「SQLインジェクション対策」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このCyber Security Academyレッスンでコードを書いて実行できますか?
はい。すべてのCyber Security Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- SQLインジェクション対策
- アクセス制御と暗号化
- 監査とモニタリング
- バックアップと復旧のセキュリティ