owasp-top-10 について
owasp-top-10は、Web開発者向けのセキュリティスキルです。OWASP Top 10のリスクに沿って、アクセス制御、インジェクション、JWTなどの対策とコード例を示します。
主な機能
- 01OWASP Top 10のリスク解説
- 02アクセス制御とIDORの修正案
- 03パラメーター化クエリによるインジェクション対策
- 04パスワードとJWTのセキュリティ確認
- 05依存関係スキャンとセキュリティログの案内
活用シーン
- 01Webアプリの一般的なリスク確認
- 02SQLインジェクションやIDORの修正作成
- 03パスワード処理とJWT設定のレビュー
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ yonatangross/ orchestkit --skill owasp-top-10インストール後、Claude Code で/owasp-top-10を入力して読み込まれたか確認します。
同梱ファイルexamples/owasp-top10-fixes.mdreferences/vulnerability-demos.md
詳細
OWASP Top 10
最も重大なウェブセキュリティリスクから保護します。
1. アクセス制御の不備
# ❌ Bad: No authorization check
@app.route('/api/users/<user_id>')
def get_user(user_id):
return db.query(f"SELECT * FROM users WHERE id = {user_id}")
# ✅ Good: Verify user can access resource
@app.route('/api/users/<user_id>')
@login_required
def get_user(user_id):
if current_user.id != user_id and not current_user.is_admin:
abort(403)
return db.query("SELECT * FROM users WHERE id = ?", [user_id])
2. 暗号化の失敗
# ❌ Bad: Weak hashing
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
# ✅ Good: Strong hashing
from argon2 import PasswordHasher
ph = PasswordHasher()
password_hash = ph.hash(password)
3. インジェクション
# ❌ Bad: SQL injection vulnerable
query = f"SELECT * FROM users WHERE email = '{email}'"
# ✅ Good: Parameterized query
query = "SELECT * FROM users WHERE email = ?"
db.execute(query, [email])
4. 安全でない設計
- ログイン時のレート制限がない
- 連番または推測可能な ID
- 機密性の高い操作に CAPTCHA がない
修正方法: UUID を使用し、レート制限を実装し、早い段階で脅威モデリングを行います。
5. セキュリティ設定の不備
# ❌ Bad: Debug mode in production
app.debug = True
# ✅ Good: Environment-based config
app.debug = os.getenv('FLASK_ENV') == 'development'
6. 脆弱なコンポーネント
# Scan for vulnerabilities
npm audit
pip-audit
# Fix vulnerabilities
npm audit fix
7. 認証の失敗
# ✅ Strong password requirements
def validate_password(password):
if len(password) < 12:
return "Password must be 12+ characters"
if not re.search(r"[A-Z]", password):
return "Must contain uppercase"
if not re.search(r"[0-9]", password):
return "Must contain number"
return None
JWT セキュリティ(OWASP のベストプラクティス)
import jwt
import hashlib
import secrets
from datetime import datetime, timezone, timedelta
# ❌ Bad: Trust algorithm from header
payload = jwt.decode(token, SECRET, algorithms=jwt.get_unverified_header(token)['alg'])
# ✅ Good: Hardcode expected algorithm (prevents algorithm confusion attacks)
def verify_jwt(token: str) -> dict:
try:
payload = jwt.decode(
token,
SECRET_KEY,
algorithms=['HS256'], # NEVER read from header
options={
'require': ['exp', 'iat', 'iss', 'aud'], # Required claims
}
)
# Validate issuer and audience
if payload['iss'] != EXPECTED_ISSUER:
raise jwt.InvalidIssuerError()
if payload['aud'] != EXPECTED_AUDIENCE:
raise jwt.InvalidAudienceError()
return payload
except jwt.ExpiredSignatureError:
raise AuthError("Token expired")
except jwt.InvalidTokenError as e:
raise AuthError(f"Invalid token: {e}")
# Token sidejacking protection (OWASP recommended)
def create_protected_token(user_id: str, response) -> str:
"""Create token with user context to prevent sidejacking."""
# Generate random fingerprint
fingerprint = secrets.token_urlsafe(32)
# Store fingerprint hash in token (not raw value)
payload = {
'user_id': user_id,
'fingerprint': hashlib.sha256(fingerprint.encode()).hexdigest(),
'exp': datetime.now(timezone.utc) + timedelta(minutes=15),
'iat': datetime.now(timezone.utc),
'iss': ISSUER,
'aud': AUDIENCE,
}
# Send raw fingerprint as hardened cookie
response.set_cookie(
'__Secure-Fgp', # Cookie prefix for extra security
fingerprint,
httponly=True,
secure=True,
samesite='Strict',
max_age=900 # 15 min
)
return jwt.encode(payload, SECRET_KEY, algorithm='HS256')
JWT セキュリティチェックリスト:
- アルゴリズムをハードコードする(ヘッダーから読み取らない)
- exp、iat、iss、aud クレームを検証する
- 有効期限を短くする(15 分~1 時間)
- セッションを長くする場合はリフレッシュトークンのローテーションを使用する
- ログアウト/失効のためにトークンの拒否リストを実装する
8. データ整合性の失敗
<script src="https://cdn.example.com/lib.js"
integrity="sha384-..."
crossorigin="anonymous"></script>
9. ログ記録の失敗
# ✅ Log security events
@app.route('/login', methods=['POST'])
def login():
user = authenticate(email, password)
if user:
logger.info(f"Successful login: {email}")
else:
logger.warning(f"Failed login: {email}")
10. SSRF(サーバーサイドリクエストフォージェリ)
# ❌ Bad: Fetch any URL
response = requests.get(user_provided_url)
# ✅ Good: Allowlist domains
ALLOWED = ['api.example.com']
if urlparse(url).hostname not in ALLOWED:
abort(400)
クイックチェックリスト
- すべてのエンドポイントで認可を行う
- パスワードを bcrypt/argon2 でハッシュ化する
- パラメーター化クエリのみを使用する
- レート制限を有効にする
- 本番環境ではデバッグモードをオフにする
- 依存関係を定期的にスキャンする
- セキュリティイベントをログに記録する
関連スキル
auth-patterns- 認証の実装input-validation- サニタイズのパターンsecurity-scanning- 自動スキャン
機能の詳細
injection
キーワード: sql injection, command injection, injection, parameterized 解決する内容:
- SQL インジェクションを防ぐ
- コマンドインジェクションを修正する
- パラメーター化クエリを使用する
access-control
キーワード: access control, authorization, idor, privilege 解決する内容:
- アクセス制御の不備を修正する
- IDOR の脆弱性を防ぐ
- 認可チェックを実装する
owasp-fixes
キーワード: fix, mitigation, example, vulnerability 解決する内容:
- OWASP の脆弱性を修正する
- 緩和策の例
- コード修正のパターン
コメント
Markdown 対応