Webセキュリティ完全ガイド【2026年版】OWASP Top 10の脆弱性を理解し安全なWebアプリを構築する

なぜWebセキュリティを学ぶ必要があるのか

2026年も依然としてサイバー攻撃は増加し続けており、Webエンジニアにとってセキュリティの知識は欠かせません。IPAの報告によると、不正アクセスによる被害の多くは、既知の脆弱性への対策不足が原因です。この記事では、Webアプリケーションの主要な脆弱性と対策を実践的に解説します。

OWASP Top 10(2021年版)を理解する

OWASP(Open Web Application Security Project)が定期的に発表する「OWASP Top 10」は、Webアプリケーションにおける最重要セキュリティリスクのリストです。

A01: アクセス制御の不備

最も深刻なリスク。認証済みユーザーが許可されていないリソースにアクセスできてしまう問題です。

// 悪い例:IDをそのままURLパラメータに使用
app.get('/api/users/:id', async (req, res) => {
  const user = await User.findById(req.params.id);
  res.json(user); // 他のユーザーのデータも取れてしまう
});

// 良い例:ログインユーザーのIDと一致するかチェック
app.get('/api/users/:id', authenticate, async (req, res) => {
  if (req.params.id !== req.user.id) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const user = await User.findById(req.params.id);
  res.json(user);
});

A02: 暗号化の失敗

機密データの平文保存や不適切な暗号化が原因で情報漏洩が起きます。

// 悪い例:パスワードを平文で保存
const user = { password: req.body.password }; // 絶対NG

// 良い例:bcryptでパスワードをハッシュ化
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12;
const hashedPassword = await bcrypt.hash(req.body.password, SALT_ROUNDS);

// 検証時
const isValid = await bcrypt.compare(inputPassword, hashedPassword);

// HTTPSの強制(Express例)
app.use((req, res, next) => {
  if (!req.secure) {
    return res.redirect(301, 'https://' + req.hostname + req.url);
  }
  next();
});

A03: インジェクション(SQLインジェクション・XSS)

最も有名な脆弱性。ユーザー入力をサニタイズせずにSQLや HTMLに埋め込むことで攻撃されます。

// 悪い例:SQLインジェクション
const query = `SELECT * FROM users WHERE email = '${email}'`;
// email に ' OR '1'='1 が入ると全件取得される

// 良い例:プリペアドステートメント使用
const result = await db.query(
  'SELECT * FROM users WHERE email = $1',
  [email]
);

// XSS対策:出力時のエスケープ
import DOMPurify from 'dompurify';
const safeHTML = DOMPurify.sanitize(userInput);

// Content Security Policy(CSP)ヘッダーの設定
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'nonce-" + nonce + "'"
  );
  next();
});

A07: 認証・セッション管理の不備

// JWT(JSON Web Token)の安全な実装
import jwt from 'jsonwebtoken';

// トークンの生成
const token = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '1h', algorithm: 'HS256' }
);

// トークンの検証
try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  req.user = decoded;
} catch (err) {
  if (err.name === 'TokenExpiredError') {
    return res.status(401).json({ error: 'Token expired' });
  }
  return res.status(401).json({ error: 'Invalid token' });
}

// レート制限の実装
import rateLimit from 'express-rate-limit';
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分
  max: 5, // 最大5回
  message: 'ログイン試行回数が多すぎます。しばらくしてから再試行してください。'
});
app.post('/login', loginLimiter, loginHandler);

セキュリティヘッダーの設定(Helmet.js)

import helmet from 'helmet';

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'nonce-${nonce}'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
    },
  },
  hsts: {
    maxAge: 31536000, // 1年
    includeSubDomains: true,
    preload: true,
  },
  noSniff: true,
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
}));

依存関係の脆弱性チェック

# npm auditで依存関係の脆弱性をチェック
npm audit
npm audit fix
npm audit fix --force  # 注意:破壊的変更の可能性あり

# Snykによる継続的セキュリティ監視
npm install -g snyk
snyk auth
snyk test
snyk monitor

# GitHub Dependabotの設定(.github/dependabot.yml)
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 10

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

カテゴリ チェック項目 優先度
認証 パスワードのハッシュ化(bcrypt) ★★★
認証 多要素認証(MFA)の実装 ★★★
通信 HTTPS通信の強制 ★★★
入力 全ての入力値のバリデーション ★★★
ヘッダー セキュリティヘッダーの設定 ★★☆
依存関係 定期的なnpm audit実行 ★★☆
ログ アクセスログ・エラーログの保存 ★★☆

まとめ

Webセキュリティは一度対策すれば終わりではなく、継続的な改善が必要です。OWASP Top 10を参考に、まずは自分のアプリケーションの脆弱性を把握し、優先度の高いものから対策を始めましょう。

  • ✅ SQLインジェクション・XSS対策は必須
  • ✅ パスワードは必ずbcryptでハッシュ化
  • ✅ セキュリティヘッダーを適切に設定
  • ✅ 依存関係の脆弱性を定期的にチェック

投稿者 kasata

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

コメントを残す

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