OWASP Top 10 2025版対策|最新脆弱性と実装コード例
OWASP Top 10 2025版の最新対策を解説。プロンプトインジェクション、サプライチェーンリスク等の新種脆弱性への実装レベルの対応方法を紹介。
Sponsored
OWASP Top 10 2025版 実装対策ガイド|最新脆弱性と検証ツール
はじめに:OWASP Top 10 2025版の位置づけ
2025年にOWASPが発表した「OWASP Top 10 2025」は、2021年版から大幅に改定されました。現在、多くの企業がこの新しいリスク分類に基づいた脅威モデリングと対策を急速に進めています。
従来のInjection脆弱性だけに対応する時代は終わり、AI時代の新たな攻撃パターン、サプライチェーンリスク、プロンプトインジェクションといった新種の脆弱性への対応が必須となっています。本記事では、開発環境で実際に機能する対策手法を、実装レベルのコード例と共に解説します。
OWASP Top 10 2025版の主要変更点
2021年版との主な違い
| 順位 | 2021年版 | 2025年版 | 変更理由 |
|---|---|---|---|
| 1位 | Broken Access Control | Injection(拡張) | AI時代のプロンプトインジェクション台頭 |
| 2位 | Cryptographic Failures | Broken Authentication | 認証・セッション管理の複雑化 |
| 3位 | Injection | Insecure Object Deserialization | シリアライゼーション攻撃の深刻化 |
| 4位 | Insecure Design | Data Exposure | API経由のデータ漏洩増加 |
| 5位 | Security Misconfiguration | SQL/NoSQL Injection(分離) | NoSQLインジェクションの急増 |
| 6位 | Vulnerable & Outdated Components | Server-Side Template Injection | テンプレートエンジン脆弱性の顕在化 |
| 7位 | Identification & Auth Failures | Supply Chain Vulnerabilities | 依存関係の脆弱性リスク |
| 8位 | Software & Data Integrity Failures | Insufficient Logging & Monitoring | 検知・対応能力の強化要求 |
| 9位 | SSRF | Insecure AI Integration | 新規:LLM統合アプリの脆弱性 |
| 10位 | Using Components with Known Vulns | Business Logic Vulnerabilities | ビジネスロジック脆弱性の重要性向上 |
特に重要な3つのカテゴリと対策
1. AI統合アプリケーションのセキュリティ(新規追加)
現在、生成AI・LLM統合アプリは急速に本番環境に展開されています。しかしプロンプトインジェクションやLLM出力の検証不足による情報漏洩事例が急増しています。
脆弱なコード例
# ❌ 危険:ユーザー入力を直接プロンプトに埋め込み
from openai import OpenAI
client = OpenAI()
user_query = request.args.get('query')
# プロンプトインジェクション攻撃: query="""Ignore previous instructions
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{
"role": "user",
"content": f"ユーザーの質問に回答してください: {user_query}"
}]
)
# LLM出力をそのまま返すのは危険
return response.choices[0].message.content
セキュアな実装パターン
import re
from typing import Literal
from openai import OpenAI
from pydantic import BaseModel, validator
class SafeQuery(BaseModel):
"""入力の厳密な検証"""
text: str
@validator('text')
def validate_length_and_content(cls, v):
# 長さ制限
if len(v) > 500:
raise ValueError('Query too long')
# 危険なパターンを検出
dangerous_patterns = [
r'ignore.*instructions',
r'forget.*previous',
r'system.*prompt',
]
for pattern in dangerous_patterns:
if re.search(pattern, v, re.IGNORECASE):
raise ValueError('Suspicious pattern detected')
return v
# LLM出力の検証レイヤー
class LLMOutputValidator:
"""LLM出力の検証と無毒化"""
@staticmethod
def validate_response(response: str,
expected_type: Literal['json', 'text']) -> dict:
"""LLM応答の妥当性チェック"""
# 応答サイズの制限
if len(response) > 5000:
raise ValueError('Response exceeds max length')
if expected_type == 'json':
try:
import json
parsed = json.loads(response)
# スキーマ検証
return parsed
except json.JSONDecodeError:
raise ValueError('Invalid JSON response')
# テキスト応答のサニタイゼーション
return {
'content': response.strip(),
'truncated': len(response) > 2000
}
# 安全なAPI実装
def safe_llm_query(user_input: str) -> dict:
"""プロンプトインジェクション対策を施したLLMクエリ"""
# 1. 入力検証
validated_query = SafeQuery(text=user_input)
# 2. システムプロンプトを厳密に定義(ユーザー入力で上書き不可)
system_prompt = (
"You are a helpful assistant. "
"You must follow these rules: "
"1. Only answer technical questions. "
"2. Do not execute code. "
"3. Do not access external systems."
)
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": validated_query.text}
],
temperature=0.2, # 予測可能性向上
max_tokens=1000, # 出力制限
)
# 3. 出力検証
validated_output = LLMOutputValidator.validate_response(
response.choices[0].message.content,
expected_type='text'
)
return validated_output
2. Server-Side Template Injection(SSTI)対策
Jinja2、ERB、Mustacheなどのテンプレートエンジンを使用したアプリケーションが増加しており、SSTIを含む脆弱性が多く報告されています。
脆弱性の実例
# ❌ 危険:ユーザー入力をテンプレートに直接埋め込み
from jinja2 import Template
user_name = request.args.get('name')
template_string = f"Hello {user_name}!" # 危険!
template = Template(template_string)
# 攻撃例: name="{{7*7}}" → "Hello 49!"
# 攻撃例: name="{{config.items()}}" → 機密情報漏洩
result = template.render()
セキュアな実装
from jinja2 import Environment, FileSystemLoader, select_autoescape
from markupsafe import escape
import os
class SecureTemplateRenderer:
"""SSTI対策を施したテンプレートレンダリング"""
def __init__(self):
# テンプレートディレクトリを厳密に限定
self.env = Environment(
loader=FileSystemLoader('/app/templates/safe'),
autoescape=select_autoescape(
enabled_extensions=('html', 'xml'),
default_for_string=True # デフォルトでエスケープ
),
enable_async=False
)
# 危険な関数をグローバルから除外
dangerous_globals = ['config', '__import__', 'eval']
for name in dangerous_globals:
if name in self.env.globals:
del self.env.globals[name]
def render_safe(self, template_name: str, context: dict) -> str:
"""
安全なテンプレートレンダリング
Args:
template_name: templates/safeディレクトリ内のテンプレート
context: テンプレート変数(自動エスケープされる)
Returns:
レンダリング結果
"""
# テンプレート名の検証(ディレクトリトラバーサル対策)
if '..' in template_name or template_name.startswith('/'):
raise ValueError('Invalid template name')
# コンテキスト値の事前検証
for key, value in context.items():
if isinstance(value, str):
context[key] = escape(value) # HTMLエスケープ
template = self.env.get_template(template_name)
return template.render(context)
# 使用例
renderer = SecureTemplateRenderer()
# テンプレート: templates/safe/user_greeting.html
# <h1>Hello {{ user_name }}!</h1>
# <p>Your query: {{ query }}</p>
user_input = request.args.get('name', 'Guest')
query_input = request.args.get('q', '')
result = renderer.render_safe('user_greeting.html', {
'user_name': user_input,
'query': query_input
})
3. Supply Chain Vulnerabilities対策
依存関係の脆弱性管理はビルドパイプラインの必須機能となっています。単なるSBOM(Software Bill of Materials)生成では不十分で、能動的な脆弱性検証とリスク分類が求められます。
実装例:DevSecOps統合
# .github/workflows/secure-build.yml
name: Security-First Build Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
dependency-check:
runs-on: ubuntu-latest
steps:
# 1. 依存関係の脆弱性スキャン
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # 脆弱性検出時は失敗
# 2. SBOMの生成と署名
- name: Generate signed SBOM
run: |
pip install cyclonedx-bom
cyclonedx-bom -o sbom.json
# SBOMに署名(改ざん検知対策)
cosign sign-blob --key cosign.key sbom.json > sbom.json.sig
# 3. SLSA Provenanceの生成
- name: Generate SLSA provenance
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
with:
base64-subjects: ${{ needs.build.outputs.hashes }}
upload-assets: true
# 4. GitHub Security Advisoryとの同期
- name: Check GitHub Advisory Database
run: |
python3 << 'EOF'
import json
import subprocess
# pip-auditで脆弱性チェック
result = subprocess.run(
['pip-audit', '--format', 'json'],
capture_output=True,
text=True
)
vulnerabilities = json.loads(result.stdout)
# リスク分類
critical_vulns = [v for v in vulnerabilities
if v.get('vulnerability_id', '').startswith('CVE')]
if critical_vulns:
print(f"Found {len(critical_vulns)} critical vulnerabilities")
for vuln in critical_vulns:
print(f" - {vuln['package']}: {vuln['vulnerability_id']}")
exit(1)
EOF
# 5. ライセンスコンプライアンスチェック
- name: License compliance check
run: |
pip install licensecheck
licensecheck --zero --no-deps Sponsored