Skip to Content
ドキュメントWebコースバックエンド・DB🔒 SQLインジェクションを理解して対策する

🔒 SQLインジェクションを理解して対策する

このページで学ぶこと

  • SQLインジェクションとは何かがわかる
  • 実際に攻撃を体験して危険性を実感できる
  • Prisma を使えば自動的に安全である理由がわかる

SQLインジェクションとは

SQLインジェクション は、ユーザーの入力を通じて悪意のある SQL を実行させる攻撃です。

攻撃者が入力: ' OR '1'='1

実行されるSQL: SELECT * FROM users WHERE email = '' OR '1'='1'
plaintext

OR '1'='1' は常に true なので、すべてのユーザーのデータが取得されてしまいます。


攻撃を体験してみよう

脆弱なコードを書く

まずわざと脆弱なコードを書いて、SQLインジェクションを体験しましょう。

// ⚠️ app/api/vulnerable-search/route.js(脆弱なコード — 絶対に本番で使わない)
import { NextResponse } from 'next/server'
import { prisma } from '../../../lib/prisma'
 
export async function GET(request) {
  const { searchParams } = new URL(request.url)
  const email = searchParams.get('email')
 
  // ❌ 危険:ユーザー入力をSQLに直接埋め込んでいる
  const result = await prisma.$queryRawUnsafe(
    `SELECT * FROM users WHERE email = '${email}'`
  )
 
  return NextResponse.json(result)
}
javascript

以下のURLにアクセスしてみましょう(localhost:3000 で開発サーバーが動いている状態で)。

# 通常のリクエスト
http://localhost:3000/api/vulnerable-search?email=test@example.com

# 攻撃リクエスト(シングルクォートを入れる)
http://localhost:3000/api/vulnerable-search?email=' OR '1'='1
plaintext

2番目のURLで全ユーザーのデータが返ってきたら、攻撃成功です。
実際の攻撃では、パスワードのハッシュや個人情報が丸ごと盗まれます。


Prisma は自動で安全

Prisma の通常の操作は**プレースホルダー(パラメータ化クエリ)**を使うため、SQLインジェクションが起きません。

// ✅ 安全(Prismaの通常操作)
const user = await prisma.user.findFirst({
  where: { email: userInput }  // userInput がどんな文字列でも安全
})
javascript

内部では以下のようなSQLが実行されます。

-- プレースホルダーを使ったSQL(安全)
SELECT * FROM users WHERE email = $1
-- $1 に userInput の値が別途渡される
sql

$1 と値を分離して渡すため、値の中に SQL の記号が含まれていても、SQL として解釈されません。


$queryRaw を使うときの注意

複雑な条件で生のSQLを書きたいときは $queryRaw を使います。
この場合もテンプレートリテラル(タグ付きテンプレート)を使えば安全です。

// ✅ 安全(テンプレートリテラルを使う)
const result = await prisma.$queryRaw`
  SELECT * FROM users WHERE email = ${userInput}
`
 
// ❌ 危険($queryRawUnsafe に直接文字列を渡す)
const result = await prisma.$queryRawUnsafe(
  `SELECT * FROM users WHERE email = '${userInput}'`
)
javascript

対策まとめ

状況対応
通常のCRUD操作Prismaの通常操作を使えばOK(自動で安全)
生のSQLを書きたい$queryRaw + テンプレートリテラルを使う
$queryRawUnsafeユーザー入力を絶対に渡さない

Prisma を使っている限り、通常の操作では SQLインジェクションは起きません。
安心して開発に集中してください。

ただし、「生のSQL($queryRawUnsafe)を使わなければいけない状況」になったら必ずプレースホルダーを意識してください。


確認しよう

  • 脆弱なエンドポイントを作り、SQLインジェクションを体験した
  • Prismaの通常操作がなぜ安全かを説明できる
  • プレースホルダー(パラメータ化クエリ)とは何かを説明できる

AIに聞いてみよう

「SQLインジェクション以外にもDBに関連するセキュリティリスクにはどんなものがありますか?」


次のステップ

Supabase Authで認証・認可を実装する

Last updated on