OWASP Top 10
OWASP Top 10は、Webアプリケーションにおける最も重大なセキュリティリスクをまとめたドキュメントです。Open Web Application Security Project (OWASP)が定期的に更新しており、開発者やセキュリティ専門家が優先的に対処すべき脅威を理解するための指針となっています。
OWASP Top 10 (2021年版)
1. A01:2021 - Broken Access Control (アクセス制御の不備)
概要 ユーザーが許可された権限を超えて行動できてしまう脆弱性です。
リスク例
- URLの直接操作による他ユーザーのデータへのアクセス
- 権限昇格攻撃
- APIの不適切なアクセス制御
対策
- すべてのリソースに対してアクセス制御を実装
- デフォルトで拒否の原則を採用
- セッション管理の適切な実装
- サーバーサイドでの権限チェック
// 良い例: サーバーサイドでの権限チェック
app.get('/api/users/:id/profile', async (req, res) => {
const requestedUserId = req.params.id;
const currentUserId = req.user.id;
// 自分のプロファイルまたは管理者のみアクセス可能
if (currentUserId !== requestedUserId && !req.user.isAdmin) {
return res.status(403).json({ error: 'Access denied' });
}
const profile = await getUserProfile(requestedUserId);
res.json(profile);
});
2. A02:2021 - Cryptographic Failures (暗号化の失敗)
概要 機密データの暗号化が不十分、または暗号化が適切に実装されていない状態です。
リスク例
- 平文でのパスワード保存
- 弱い暗号化アルゴリズムの使用
- HTTPでの機密データ送信
- 不適切な鍵管理
対策
- すべての機密データを暗号化
- 強力な暗号化アルゴリズムの使用(AES-256など)
- HTTPS/TLSの強制
- 安全なハッシュ関数の使用(bcrypt、Argon2など)
// 良い例: パスワードのハッシュ化
using BCrypt.Net;
public class UserService
{
public void CreateUser(string username, string password)
{
// パスワードをハッシュ化して保存
string hashedPassword = BCrypt.HashPassword(password, BCrypt.GenerateSalt(12));
// データベースに保存
SaveToDatabase(username, hashedPassword);
}
public bool VerifyPassword(string username, string password)
{
var user = GetUserFromDatabase(username);
return BCrypt.Verify(password, user.HashedPassword);
}
}
3. A03:2021 - Injection (インジェクション)
概要 信頼できないデータがコマンドやクエリの一部として送信され、意図しない動作を引き起こす脆弱性です。
リスク例
- SQLインジェクション
- NoSQLインジェクション
- OSコマンドインジェクション
- LDAPインジェクション
対策
- パラメータ化クエリ(プリペアドステートメント)の使用
- ORMの適切な使用
- 入力検証とサニタイゼーション
- 最小権限の原則
// 悪い例: SQLインジェクションの脆弱性
string query = "SELECT * FROM Users WHERE Username = '" + username + "'";
// 良い例: パラメータ化クエリ
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE Username = @Username", connection))
{
cmd.Parameters.AddWithValue("@Username", username);
SqlDataReader reader = cmd.ExecuteReader();
}
// Entity Framework Core を使用した例
var user = await dbContext.Users
.Where(u => u.Username == username)
.FirstOrDefaultAsync();
4. A04:2021 - Insecure Design (安全でない設計)
概要 設計段階でのセキュリティ要件の欠如や不適切なリスク分析による脆弱性です。
リスク例
- 脅威モデリングの欠如
- セキュリティパターンの不使用
- ビジネスロジックの欠陥
対策
- セキュア開発ライフサイクル(SDLC)の採用
- 脅威モデリングの実施
- セキュリティ要件の明確化
- セキュリティレビューの実施
5. A05:2021 - Security Misconfiguration (セキュリティ設定ミス)
概要 アプリケーション、フレームワーク、データベース、サーバーなどの設定が不適切な状態です。
リスク例
- デフォルト認証情報の使用
- 不要なサービスの有効化
- 詳細なエラーメッセージの表示
- 最新のセキュリティパッチ未適用
対策
- 最小限の構成で展開
- デフォルト設定の変更
- 定期的なセキュリティアップデート
- 自動化された設定管理
// 良い例: production環境での適切な設定
{
"production": {
"debug": false,
"detailedErrors": false,
"cors": {
"origins": ["https://yourdomain.com"],
"credentials": true
},
"headers": {
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
}
}
}
6. A06:2021 - Vulnerable and Outdated Components (脆弱で古いコンポーネント)
概要 既知の脆弱性を持つライブラリやフレームワークを使用している状態です。
リスク例
- サポート終了したライブラリの使用
- 既知の脆弱性を持つバージョンの使用
- 依存関係の管理不足
対策
- 定期的な依存関係の更新
- 脆弱性スキャンツールの使用(npm audit、Dependabot、Snykなど)
- サポートされているバージョンのみ使用
- 不要な依存関係の削除
# npm の脆弱性チェック
npm audit
# 自動修正
npm audit fix
# package.json での固定バージョン指定
{
"dependencies": {
"express": "4.18.2" # ~ や ^ を避ける
}
}
7. A07:2021 - Identification and Authentication Failures (識別と認証の失敗)
概要 ユーザーの識別や認証が適切に実装されていない脆弱性です。
リスク例
- 弱いパスワードポリシー
- クレデンシャルスタッフィング攻撃
- セッション管理の不備
- 多要素認証の欠如
対策
- 強力なパスワードポリシーの実施
- 多要素認証(MFA)の実装
- アカウントロックアウト機能
- セキュアなセッション管理
// 良い例: レート制限とアカウントロックアウト
import rateLimit from 'express-rate-limit';
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 5, // 最大5回の試行
message: 'Too many login attempts, please try again later.',
standardHeaders: true,
legacyHeaders: false,
});
app.post('/api/login', loginLimiter, async (req, res) => {
const { username, password } = req.body;
// 認証処理
const user = await authenticateUser(username, password);
if (!user) {
// 失敗回数をカウント
await incrementFailedLoginAttempts(username);
return res.status(401).json({ error: 'Invalid credentials' });
}
// MFAトークンの要求
if (user.mfaEnabled) {
return res.json({ requiresMFA: true, tempToken: generateTempToken() });
}
res.json({ token: generateToken(user) });
});
8. A08:2021 - Software and Data Integrity Failures (ソフトウェアとデータの整合性の失敗)
概要 整合性検証なしにソフトウェアの更新やデータの処理を行う脆弱性です。
リスク例
- 署名検証なしのアップデート
- 信頼できないソースからのデシリアライゼーション
- CI/CDパイプラインの不正アクセス
対策
- デジタル署名の検証
- 信頼できるリポジトリの使用
- CI/CDパイプラインのセキュリティ強化
- 整合性チェックの実装
9. A09:2021 - Security Logging and Monitoring Failures (セキュリティログとモニタリングの失敗)
概要 適切なログ記録とモニタリングが実装されていない状態です。
リスク例
- ログの欠如または不十分
- 異常検知の欠如
- インシデント対応の遅延
対策
- すべてのセキュリティイベントのログ記録
- リアルタイム監視とアラート
- ログの集中管理
- 定期的なログレビュー
// 良い例: 構造化ログとセキュリティイベントの記録
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'security.log' })
]
});
// セキュリティイベントのログ記録
app.post('/api/login', async (req, res) => {
const { username, password } = req.body;
const ipAddress = req.ip;
try {
const user = await authenticateUser(username, password);
if (!user) {
logger.warn({
event: 'LOGIN_FAILED',
username,
ipAddress,
timestamp: new Date().toISOString()
});
return res.status(401).json({ error: 'Invalid credentials' });
}
logger.info({
event: 'LOGIN_SUCCESS',
userId: user.id,
username,
ipAddress,
timestamp: new Date().toISOString()
});
res.json({ token: generateToken(user) });
} catch (error) {
logger.error({
event: 'LOGIN_ERROR',
username,
ipAddress,
error: error.message,
timestamp: new Date().toISOString()
});
res.status(500).json({ error: 'Internal server error' });
}
});
10. A10:2021 - Server-Side Request Forgery (SSRF) (サーバーサイドリクエストフォージェリ)
概要 Webアプリケーションが、ユーザー指定のURLを検証せずにリモートリソースを取得する脆弱性です。
リスク例
- 内部サービスへの不正アクセス
- クラウドメタデータの漏洩
- ポートスキャン
- ファイアウォールのバイパス
対策
- URLのホワイトリスト化
- ネットワークレイヤーでのセグメンテーション
- URLスキーマの制限
- 内部IPアドレスのブロック
// 良い例: SSRF対策
import { URL } from 'url';
const ALLOWED_DOMAINS = ['api.example.com', 'cdn.example.com'];
const BLOCKED_IPS = ['127.0.0.1', '0.0.0.0', '::1'];
async function fetchExternalResource(urlString: string) {
try {
const url = new URL(urlString);
// プロトコルチェック
if (url.protocol !== 'https:') {
throw new Error('Only HTTPS is allowed');
}
// ドメインホワイトリストチェック
if (!ALLOWED_DOMAINS.includes(url.hostname)) {
throw new Error('Domain not allowed');
}
// 内部IPアドレスのブロック
if (BLOCKED_IPS.includes(url.hostname) ||
url.hostname.startsWith('192.168.') ||
url.hostname.startsWith('10.') ||
url.hostname.startsWith('172.')) {
throw new Error('Internal IP addresses are not allowed');
}
const response = await fetch(url.toString());
return response;
} catch (error) {
console.error('SSRF attempt blocked:', error);
throw error;
}
}
まとめ
OWASP Top 10は、Webアプリケーション開発において最も注意すべきセキュリティリスクを提示しています。開発の初期段階からこれらの脅威を意識し、適切な対策を実装することが重要です。
推奨事項
- セキュア開発ライフサイクルの採用: 設計段階からセキュリティを考慮
- 定期的なセキュリティレビュー: コードレビューと脆弱性診断の実施
- 教育とトレーニング: 開発チーム全体のセキュリティ意識向上
- 自動化ツールの活用: SAST、DAST、依存関係スキャンの導入
- インシデント対応計画: 万が一に備えた対応手順の準備