Welcome to Tech Athletes | テック・アスリート   Click to listen highlighted text! Welcome to Tech Athletes | テック・アスリート

【2026年版】Webアプリケーションセキュリティ完全入門|XSS・SQLインジェクション・CSRF・認証の脆弱性と対策

なぜWebセキュリティを学ぶべきか

2026年、サイバー攻撃は年間数千万件を超え、企業・個人への被害は拡大し続けています。エンジニアにとってWebセキュリティの知識は「あればいい」ではなく「必須」のスキルです。本記事では、最も頻出する脆弱性と具体的な対策コードを解説します。

1. XSS(クロスサイトスクリプティング)

攻撃の仕組み

XSSは、攻撃者が悪意あるJavaScriptコードをWebページに注入し、サイト訪問者のブラウザで実行させる攻撃です。Cookieの盗取・フィッシング・マルウェア配布などに悪用されます。

// 脆弱なコード例
const name = req.query.name;
res.send(`<h1>Hello, ${name}!</h1>`); // XSS脆弱性!

// 安全な対策:エスケープ処理
import { escape } from 'html-escaper';
const safeName = escape(req.query.name as string);
res.send(`<h1>Hello, ${safeName}!</h1>`);

// React/Next.jsでは自動でエスケープ
// JSXの{変数}は自動エスケープされる(危険なのはdangerouslySetInnerHTML)
function Welcome({ name }: { name: string }) {
  return <h1>Hello, {name}!</h1>; // 安全
}

XSS対策まとめ

  • ユーザー入力を必ずHTMLエスケープする
  • Content Security Policy (CSP) ヘッダーを設定する
  • dangerouslySetInnerHTMLの使用を避ける
  • HTTPOnly Cookie を使用してJavaScriptからCookieにアクセスさせない

2. SQLインジェクション

攻撃の仕組み

SQLインジェクションは、ユーザー入力をSQL文に直接組み込む脆弱なコードを悪用し、データベースを不正操作する攻撃です。

// 脆弱なコード(文字列連結)
const query = "SELECT * FROM users WHERE email='" + email + "'";
// email = "' OR '1'='1" と入力されると全ユーザーが取得される

// 安全な対策:プリペアドステートメント(Prismaの例)
const user = await prisma.user.findFirst({
  where: { email: email } // Prismaは自動的にプリペアドステートメントを使用
});

// Drizzle ORM の例
const result = await db.select()
  .from(users)
  .where(eq(users.email, email)); // 型安全かつSQLインジェクション対策済み

3. CSRF(クロスサイトリクエストフォージェリ)

CSRFは、ユーザーが意図せず悪意あるサイトから、ログイン済みサービスへリクエストを送らされる攻撃です。

// Next.js でのCSRF対策例
import { csrf } from 'csrf-csrf';

const { generateToken, validateRequest } = csrf({
  getSecret: () => process.env.CSRF_SECRET!,
  cookieName: 'x-csrf-token',
  cookieOptions: {
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
  },
});

// APIルートでの検証
export async function POST(request: Request) {
  // CSRFトークンを検証
  const isValid = await validateRequest(request);
  if (!isValid) {
    return Response.json({ error: 'CSRF validation failed' }, { status: 403 });
  }
  // 処理続行...
}

4. 認証・認可の脆弱性

よくある認証の問題と対策

脆弱性問題対策
弱いパスワードブルートフォース攻撃に弱いレート制限・CAPTCHA導入
セッション固定攻撃ログイン後もセッションIDが変わらないログイン後にセッションを再生成
JWTの鍵管理弱い署名鍵の使用256bit以上の強力な鍵を環境変数に
平文パスワード保存DBが漏洩したら終わりbcrypt/argon2でハッシュ化
// 安全なパスワードハッシュ化(argon2)
import { hash, verify } from '@node-rs/argon2';

// パスワード保存時
const hashedPassword = await hash(password, {
  memoryCost: 19456,
  timeCost: 2,
  outputLen: 32,
  parallelism: 1,
});

// パスワード検証時
const isValid = await verify(hashedPassword, inputPassword);

5. HTTPセキュリティヘッダーの設定

// next.config.js でのセキュリティヘッダー設定
const securityHeaders = [
  {
    key: 'X-DNS-Prefetch-Control',
    value: 'on'
  },
  {
    key: 'Strict-Transport-Security',
    value: 'max-age=63072000; includeSubDomains; preload'
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff'
  },
  {
    key: 'X-Frame-Options',
    value: 'SAMEORIGIN'
  },
  {
    key: 'Content-Security-Policy',
    value: "default-src 'self'; script-src 'self' 'nonce-{nonce}'"
  },
];

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ];
  },
};

セキュリティチェックリスト

  • ✅ すべてのユーザー入力をバリデーション・サニタイズ
  • ✅ プリペアドステートメントまたはORMを使用
  • ✅ HTTPSの強制
  • ✅ セキュリティヘッダーの設定
  • ✅ 依存関係の定期的なアップデート(npm audit)
  • ✅ 環境変数にシークレットを保存
  • ✅ レート制限の実装
  • ✅ エラーメッセージに内部情報を含めない

まとめ:セキュリティはコストではなく投資

Webセキュリティの脆弱性は、ひとたび悪用されれば企業の信頼を失い、莫大な損害をもたらします。本記事で紹介したXSS・SQLインジェクション・CSRF・認証の脆弱性と対策を実装し、セキュアなWebアプリケーション開発を心がけましょう。セキュリティは最後に追加するものではなく、設計段階から組み込むべきものです。

投稿者 kasata

IT企業でエンジニアとして勤務後、テクノロジー情報メディア「Tech Athletes(テック・アスリート)」を運営。プログラミング、クラウドインフラ(AWS/GCP/Azure)、AI活用、Webサービス開発を専門とする。エンジニア・ビジネスパーソン向けに、実際に使ってみた経験をもとに信頼できる技術情報を発信中。資格:AWS認定ソリューションアーキテクト、Python 3 エンジニア認定試験合格。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Click to listen highlighted text!