SQLインジェクションとは?仕組みと対策を解説

SQLインジェクションとは?仕組みと対策を解説

SQLインジェクションとは、Webアプリケーションが受け取った入力値を安全に処理せず、そのままSQL文の一部として扱ってしまうことで、意図しないデータベース操作につながる脆弱性です。

対策の中心は、入力値をSQL文へ文字列連結しないことです。 プリペアドステートメント(パラメータ化クエリ)を使い、SQLの構造とデータを分離することで、入力値がSQL命令として解釈されにくくなります。

30秒でわかる結論

  • SQLインジェクションは、入力値がSQL文として解釈されることで起きる脆弱性
  • 原因は「ユーザー入力をそのままSQL文字列へ連結する」実装にあることが多い
  • 最重要対策はプリペアドステートメント・パラメータ化クエリ
  • 入力チェックだけ、エスケープだけ、WAFだけでは十分とは限らない
  • データベース接続ユーザーには必要最小限の権限だけ与える
  • WordPressで独自SQLを書く場合は、WordPress APIや $wpdb->prepare() を使う
  • WordPress利用者は本体・テーマ・プラグイン更新とWAFも併用する

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

SQLインジェクションは、Webアプリケーションとデータベースの間でSQL文を組み立てる処理に問題があるときに起こる代表的なインジェクション脆弱性です。

初心者向けに言い換えると

本来は「検索キーワード」「ユーザーID」などのデータとして扱うべき入力が、誤ってSQL命令の一部として解釈されてしまう問題です。

OWASPでは、信頼できないデータがSQL構文の一部になることで、データの閲覧・変更などにつながる可能性があると説明しています。

SQLとは?

SQLは、MySQLやMariaDB、PostgreSQLなどのリレーショナルデータベースへ命令を送るための言語です。

SQLが行う処理の例

  • データを検索する
  • データを追加する
  • データを更新する
  • データを削除する

WordPressも投稿、ユーザー、設定などのデータをデータベースへ保存しており、必要に応じてSQLを通じて読み書きします。

SQLインジェクションはなぜ起きる?

典型的な原因は、ユーザーが入力した値をSQL文字列へ直接連結してしまうことです。

危険な考え方のイメージ

SQL文 = "SELECT ... WHERE name = '" + ユーザー入力 + "'"

このようにSQLの構造と入力値が混ざると、入力内容によってSQL文の意味そのものが変わる可能性があります。

攻撃文字列を覚える必要はない

防御側で重要なのは、どんな特殊文字列が使われるかを暗記することではありません。「入力値がSQL構造へ入り込めない実装」にすることが根本対策です。

どんな入力欄が関係する?

SQLインジェクションは、検索ボックスやログインフォームだけで起こるわけではありません。 入力値がSQLへ使われる場所なら、さまざまな経路が対象になります。

確認対象の例

  • 検索フォーム
  • ログインフォーム
  • 問い合わせフォーム
  • URLパラメータ
  • APIリクエスト
  • 管理画面の入力項目
  • 他システムから受け取るデータ

「外部ユーザーが直接入力する画面だけ見ればよい」とは限りません。 OWASPも、別サービスや保存済みデータなど、信頼できない値がSQL構築へ入るケースを含めて対策するよう案内しています。

SQLインジェクションで起こり得る被害

脆弱性の内容やデータベース権限によって影響は変わります。

被害 内容
情報漏えい 本来表示されないデータが取得される
データ改ざん 保存データが変更される
データ削除 重要データが失われる
認証への影響 認証ロジックが不正に回避される可能性
サービス停止 DB障害やデータ破損によりサービスへ影響

影響範囲は、アプリケーションがデータベースへどの権限で接続しているかによっても変わります。

最重要対策はプリペアドステートメント

OWASPが最優先の対策として推奨しているのが、プリペアドステートメントとパラメータ化クエリです。

SQLの構造と入力データを分離する

SQL文の形を先に固定し、ユーザー入力は「データ」として別に渡します。 これにより、入力値がSQL命令の構造を変更しにくくなります。

安全な考え方

SELECT ... WHERE name = ?
↓
? の部分へ値をデータとして渡す

重要なのは、入力値をSQL文字列へ直接埋め込まず、データベースAPIのパラメータ機能を利用することです。

プリペアドステートメントならなぜ安全?

プリペアドステートメントでは、SQLの命令部分と値部分を分けて扱います。 そのため、値として渡された文字列は基本的に「SQL構文を変更する命令」ではなく「検索・保存対象のデータ」として扱われます。

防御のポイント

危険な文字を1つずつ禁止するのではなく、「入力データがSQL文の文法へ入り込めない仕組み」にします。

入力チェックだけでは不十分

「英数字だけ許可する」「文字数を制限する」といった入力バリデーションは重要ですが、SQLインジェクションの主防御としては不十分です。

OWASPも、入力検証はパラメータ化クエリを補助する対策であり、値を検証したからといってSQLへ直接連結してよいわけではないと説明しています。

順番が重要

基本は「パラメータ化クエリ」を使い、そのうえで業務上必要な形式・長さ・範囲を入力チェックします。

エスケープだけに頼らない

特殊文字をエスケープしてSQL文字列へ入れる方法もありますが、OWASPは手動エスケープをプリペアドステートメントの代替として使うことを強く推奨していません。

データベース製品や設定によってエスケープ規則が異なるため、実装ミスが起こりやすいからです。

基本方針

「エスケープして文字列連結」より、「最初からパラメータ化クエリ」を選びます。

テーブル名や並び順はどう扱う?

パラメータ化できるのは主にデータ値です。 テーブル名、カラム名、並び順などSQL構造そのものをユーザー入力で自由に決めさせる設計は避けます。

安全な考え方

ユーザーが「新しい順」「古い順」を選択
↓
アプリ側で許可済みの選択肢へ対応付ける
↓
固定したSQL構造を使う

OWASPでは、このような構造部分はアプリケーション側で用意した許可リストから選ぶ方法を推奨しています。

データベース権限を最小限にする

SQLインジェクションそのものを防ぐ対策とは別に、万一脆弱性が悪用された場合の被害を小さくするため、DB接続ユーザーの権限を必要最小限にします。

最小権限の考え方

  • 不要な管理者権限を与えない
  • 必要なデータベースだけへアクセスさせる
  • 不要なCREATE・DROPなどの権限を持たせない
  • 複数アプリで同じ管理DBアカウントを共有しない

OWASPも、WebアプリケーションのDB接続にDBAや管理者相当の権限を与えないよう推奨しています。

WAFはSQLインジェクション対策になる?

WAFは、Webアプリケーションへ届くHTTP/HTTPSリクエストを検査し、SQLインジェクションなどの既知攻撃パターンを検知・遮断する防御層として役立ちます。

WAFだけでは根本対策にならない

アプリケーション側に脆弱なSQL実装が残ったままでは、WAFのルールをすり抜ける攻撃や誤設定の影響を受ける可能性があります。コード側のプリペアドステートメントが基本です。

安全な実装 + 最小権限 + WAF + 更新管理

WordPressではSQLインジェクションをどう防ぐ?

WordPress本体にはデータベースを安全に扱うためのAPIが用意されています。 テーマやプラグイン開発では、可能な限りWordPress標準関数を使い、独自SQLが必要な場合は $wpdb の安全な機能を利用します。

WordPress公式の基本方針

標準APIで実現できるならSQLを直接書かず、独自SQLが必要な場合は $wpdb->prepare() でクエリを準備します。

$wpdb->prepare()とは?

$wpdb->prepare() は、WordPressでSQLクエリを安全に準備するためのメソッドです。 値をプレースホルダーへ渡すことで、SQL文とデータを分離します。

WordPressでの安全な例

global $wpdb;

$sql = $wpdb->prepare(
    "SELECT * FROM {$wpdb->posts} WHERE ID = %d",
    $post_id
);

WordPress公式では、%d は整数、%f は浮動小数点数、%s は文字列など、用途に応じたプレースホルダーを利用できます。

プレースホルダーへ値を渡す

ユーザー入力を先にSQL文字列へ連結してからprepareしても、根本的な安全性は得られません。SQL構造と入力値を分けた状態で使います。

WordPress標準APIを使う

投稿メタの保存、ユーザー情報、オプション設定など、WordPressには多くの操作用APIがあります。

考え方

投稿メタを保存したい
↓
独自SQLを書く
ではなく
↓
WordPress標準のメタデータAPIを使う

WordPress公式のテーマセキュリティガイドでも、WordPress関数が用意されている場合はそれを使うことが第一の方針として案内されています。

WordPress利用者はテーマ・プラグイン更新も重要

自分でSQLを書かないWordPress利用者でも、テーマやプラグイン側にSQLインジェクション脆弱性が見つかる可能性があります。

一般利用者の対策

  • WordPress本体を更新する
  • テーマを更新する
  • プラグインを更新する
  • 使わないテーマ・プラグインを削除する
  • 配布元不明のプラグインを使わない
  • レンタルサーバーのWAFを利用する
  • 定期バックアップを取る

一般利用者はSQL文を自分で修正するより、脆弱性修正版を速やかに適用できる運用の方が重要です。

SQLインジェクションとXSSの違い

SQLインジェクションとXSSは、どちらも入力処理の問題に関係しますが、狙う場所が違います。

攻撃 主に狙うもの
SQLインジェクション データベースへ送るSQL
XSS ブラウザへ出力されるHTML・JavaScript

SQLインジェクションはデータベース側、XSSは主にブラウザ側で問題が発生するため、防御方法も異なります。

SQLインジェクションとCSRFの違い

攻撃 考え方
SQLインジェクション 入力がSQL構造へ入り込む
CSRF ログイン済みユーザーに意図しない操作を実行させる

どちらもWebアプリケーションの脆弱性ですが、成立条件と対策は別です。

入力サニタイズだけで防げる?

入力値を整形・検証するサニタイズやバリデーションは重要ですが、それだけをSQLインジェクション防御の中心にしてはいけません。

役割を分ける

  • バリデーション:入力が業務上正しい形式か確認
  • パラメータ化:SQL構造と値を分離
  • 最小権限:侵害時の影響を限定
  • WAF:不審なHTTPリクエストを追加で遮断

1つの対策ですべてを防ぐのではなく、複数層で守ります。

データベースをroot権限で使わない

Webアプリケーションからデータベースへ接続するとき、DB管理者相当の強い権限を与えるべきではありません。

SQLインジェクションが成立した場合でも、接続ユーザーが必要最小限の権限しか持っていなければ、被害範囲を限定できる可能性があります。

「動くから管理者権限」は避ける

開発時に権限不足エラーを避けるため管理者権限を与えると簡単に動くことがありますが、本番環境では必要な操作だけ許可する設計にします。

エラーメッセージの公開にも注意する

本番サイトで詳細なデータベースエラーやSQL文を画面へ表示すると、内部構造に関する不要な情報を外部へ見せる可能性があります。

本番環境での考え方

  • 詳細エラーはログへ記録する
  • 一般ユーザーには必要最小限のエラー表示にする
  • デバッグモードを常時公開しない
  • ログへのアクセス権も制限する

脆弱性診断では何を確認する?

自社開発のWebアプリでは、コードレビューやセキュリティ診断でSQLの組み立て方を確認します。

防御側の確認ポイント

  • ユーザー入力を文字列連結していないか
  • プリペアドステートメントを使っているか
  • 動的なテーブル名・並び順を許可リストで管理しているか
  • DBユーザー権限が必要最小限か
  • テーマ・プラグイン・ライブラリが最新か
  • WAFやログ監視が有効か

攻撃手順を本番環境で試すのではなく、許可されたテスト環境・診断手順で確認します。

SQLインジェクションが疑われるときの対応

改ざんや不審なDB操作が疑われる場合は、原因確認と封じ込めを優先します。

1
不審な挙動・時刻を記録
2
必要に応じて公開範囲を制限
3
Web・WAF・DBログを保全
4
脆弱なコード・プラグインを修正/更新
5
DB認証情報・権限を見直す
6
バックアップと整合性を確認

ログを消してから直さない

原因調査が必要な場合、先にログや証跡を保全してください。企業サイトで情報漏えいの可能性がある場合は、社内のセキュリティ担当や専門家へ連絡します。

一般的なWordPress利用者は何をすればよい?

自分でプラグインやテーマを開発していない場合、SQLコードを直接確認する必要は通常ありません。

一般的なWordPress利用者

優先度:更新管理

本体・テーマ・プラグインを更新し、不要なものを削除します。

レンタルサーバー利用者

優先度:WAF

サーバー会社がWAFを提供しているなら基本的に有効化を検討します。

テーマ・プラグイン開発者

優先度:安全なDB API

WordPress APIと $wpdb->prepare() を利用します。

独自Webアプリ開発者

優先度:設計から対策

全SQLアクセスをパラメータ化し、DB権限も最小化します。

やってはいけない対策

危険文字をブラックリストで全部禁止する

文字の禁止だけでは抜け漏れが起きやすく、正常入力まで壊す可能性があります。パラメータ化を基本にします。

WAFがあるからコードを直さない

WAFは追加防御です。脆弱なSQL実装は修正してください。

ユーザー入力を自作エスケープして連結する

データベースごとの仕様差や実装ミスがあるため、標準のパラメータ機能を利用します。

DB接続を管理者権限にする

侵害時の被害範囲が大きくなります。必要最小限の権限を設定します。

本番で詳細なSQLエラーを公開する

内部構造を外部へ見せる可能性があります。詳細はログで確認します。

教科書判定

教科書判定

SQLインジェクション対策は「入力をSQL文へ直接混ぜない」が最優先

初心者は、SQLインジェクションを「ユーザー入力がSQL命令として解釈されてしまう脆弱性」と理解すれば十分です。

開発者はプリペアドステートメント・パラメータ化クエリを基本にし、DB権限の最小化、入力検証、WAFを組み合わせてください。

WordPress一般利用者は、自分でSQLを書かなくても、本体・テーマ・プラグインを最新に保ち、レンタルサーバーのWAFを利用することが重要です。

FAQ

Q.SQLインジェクションはWordPressでも起こりますか?

可能性はあります。WordPress本体だけでなく、テーマ・プラグインの独自データベース処理に脆弱性が見つかる場合があります。更新を継続し、不要な拡張機能は削除してください。

Q.入力欄の特殊文字を禁止すれば防げますか?

それだけでは十分ではありません。主対策はプリペアドステートメント・パラメータ化クエリでSQL構造と入力値を分離することです。

Q.WAFを有効にすれば安全ですか?

WAFは有効な追加防御ですが、アプリ側の脆弱性を修正する代わりにはなりません。安全なSQL実装、更新管理、最小権限と組み合わせます。

Q.WordPressで独自SQLを書くときはどうすればよいですか?

まずWordPress標準APIで実現できないか確認し、独自SQLが必要なら $wpdb->prepare() などWordPress公式の安全なDB APIを利用します。

Q.SQLインジェクションとXSSは同じ攻撃ですか?

異なります。SQLインジェクションは主にデータベースへ送るSQL、XSSは主にブラウザへ出力されるHTML・JavaScriptに関係する脆弱性です。

まとめ

この記事の結論

  • SQLインジェクションは入力がSQL構造へ入り込む脆弱性
  • 最重要対策はプリペアドステートメント・パラメータ化クエリ
  • 入力チェックやエスケープだけに依存しない
  • DB接続ユーザーは必要最小限の権限にする
  • WAFは追加の防御層として利用する
  • WordPress独自SQLでは $wpdb->prepare() を使う
  • 一般利用者は本体・テーマ・プラグイン更新を続ける

SQLインジェクション対策で最も重要なのは、攻撃文字列を覚えることではありません。 ユーザー入力がSQLの命令部分へ入り込めないよう、最初から安全なデータベースAPIを使って設計することです。 WordPress利用者も、更新管理とWAFを組み合わせて脆弱性を悪用されにくい状態を保ってください。

次に読む

「XSSとは?クロスサイトスクリプティングの仕組みと対策」「WAFとは?仕組み・必要性・注意点を解説」もあわせて確認してください。