よろずやIT
プログラミング

SQLインジェクション対策|プレースホルダ・エスケープの違いと限界

執筆・監修:よろずやIT編集部|編集方針を見る

結論:まずここだけ読めばOK

詳しい手順・原因は、この下で解説しています。

プログラミングのイラスト

結論: SQLインジェクションを防ぐ**根本的な対策は、プレースホルダ(パラメータ化クエリ)**です。エスケープや入力チェックは、補助にすぎず、それだけに頼ると、漏れが出やすくなります。そのうえで、データベースの権限を絞るなど、被害を小さくする対策も、重ねます。

SQLインジェクションの仕組みや被害は、SQLインジェクションとはで解説しています。この記事は、対策の具体的な方法に絞って解説します。

対策の優先順位

順位 対策 位置づけ
1 プレースホルダ(パラメータ化クエリ) 根本的な対策
2 ORMなどの、標準機能を正しく使う 根本的な対策の、一つの形
3 プレースホルダが使えない箇所を、許可リストで限定 補完
4 エスケープ処理 補助(漏れやすい)
5 入力値のチェック 補助(それだけでは不十分)
6 データベースの権限を絞る・詳細なエラーを出さない 被害の軽減

プレースホルダ・入力チェック・権限の最小化を、3つの層で重ねる図解

対策1:プレースホルダを使う

危険な書き方

入力された値を、文字列として連結して、SQL文を作る書き方です。

query = "SELECT * FROM users WHERE name = '" + name + "'"
cursor.execute(query)

この書き方では、入力値の中に、SQLとして意味を持つ文字が含まれると、「データ」が「命令」として解釈されてしまいます。

たとえば、name に ' OR '1'='1 という文字列が入ると、条件が常に真になり、意図しない情報が取り出されるおそれがあります。

安全な書き方

SQLの文と、値を、別々に渡します。

cursor.execute("SELECT * FROM users WHERE name = ?", (name,))

? の部分が、プレースホルダです。値は、データベース側で、あくまで「値」として扱われるため、入力に特殊な文字が含まれていても、命令として解釈されません。

プレースホルダの書き方(? や %s など)は、使うデータベースや、ライブラリによって異なります。公式のドキュメントで確認してください。Pythonの基本は、Pythonとはをご覧ください。

文字列連結と、プレースホルダの違いを比べた図解

対策2:ORMを正しく使う

ORM(オーム)は、プログラムの言葉で、データベースを操作できる仕組みです。通常の使い方では、内部でプレースホルダが使われます。

注意: ORMでも、生のSQL文を、文字列で連結して実行する機能を使うと、危険です。ORMの標準的な書き方を、守りましょう。ORMでよく起こる、性能の問題については、N+1問題とはで解説しています。

対策3:プレースホルダが使えない場所

プレースホルダで渡せるのは、基本的に「値」です。次のような部分には、使えません。

許可リストで限定する

使ってよい値を、あらかじめ決めておき、入力がその中にある時だけ、使います。

allowed = {"name", "created_at"}
if sort_key not in allowed:
    sort_key = "created_at"
query = f"SELECT * FROM users ORDER BY {sort_key}"

入力された文字列を、そのまま使わず、許可した値だけを、SQLに組み込むのが、ポイントです。

対策4:エスケープの限界

エスケープは、SQLで意味を持つ特殊な文字を、無害な形に変換する処理です。

そのため、エスケープは、プレースホルダが使えない場合の補助と考え、主役にはしません。

対策5:入力チェック(サニタイズ)の効果と限界

効果がある場面

こうした型や形式のチェックは、不正な入力を、早い段階で除外できます。

限界

入力チェックは、他の対策と組み合わせる、補助的な防御です。

対策6:被害を小さくする

プレースホルダを使っていても、設計の漏れに備えて、被害を小さくする対策を、重ねます。

AIが書いたコードを使う時

AIが生成したコードには、手軽さを優先して、文字列を連結したSQLを書く例が、混ざることがあります。生成されたコードは、次を確認してから、使ってください。

振り返ると

SQLインジェクション対策の基本は、プレースホルダを使い、SQLの文と値を分けて渡すことです。エスケープや入力チェックは補助、データベースの権限を絞る対策は被害の軽減、と役割を分けて、重ねることで、守りが強くなります。

関連記事:SQLとは

関連記事:PHPとは

関連記事:パスワードのハッシュ化とは?

あわせて読みたい:WAFとは、XSSとは

PRフロントエンド開発のためのセキュリティ入門 知らなかったでは済まされない脆弱性対策の必須知識 【電子書籍】[ 平野昌士 ]

フロントエンド開発のためのセキュリティ入門 知らなかったでは済まされない脆弱性対策の必須知識 【電子書籍】[ 平野昌士 ]

¥2,970

楽天で見る
SHAREXLINEはてブ

よくある質問

Q.入力値から「'」を取り除けば、防げますか?

A.それだけでは、不十分です。特定の文字を取り除く方式は、想定外の入力や、文字コードの扱いなどで、すり抜けられることがあります。根本的には、SQLの文と値を分けて渡す、プレースホルダを使うのが基本です。

Q.ORM(フレームワークのデータベース機能)を使えば、安全ですか?

A.通常の使い方であれば、内部でプレースホルダが使われるため、安全性が高くなります。ただし、ORMでも、生のSQL文を、文字列で連結して実行すると、同じ危険が生じます。公式のドキュメントで、安全な書き方を確認してください。

Q.プレースホルダは、どこにでも使えますか?

A.いいえ。プレースホルダで渡せるのは、基本的に『値』の部分です。テーブル名や、列名、並び順の指定などには、使えません。そのような場合は、あらかじめ決めた、許可リストと照合して、使える値を限定します。

Q.AIが書いたコードも、確認が必要ですか?

A.必要です。AIが生成したコードに、文字列の連結でSQLを作る書き方が含まれることがあります。生成されたコードは、プレースホルダが使われているかを、必ず確認してください。

関連記事

最新のIT関連書籍 トップ10

PR / 楽天市場の売れ筋ランキングを定期的に取得しています。価格は変動する場合があるため、購入前に各ストアでご確認ください。