Webアプリケーションのセキュリティ対策は、エンジニアにとって必須の知識です。本記事ではOWASP Top 10の主要な脆弱性(SQLインジェクション・XSS・CSRF等)の仕組みと対策を、実際のコードサンプルを交えて解説します。
OWASP Top 10(2026年版)
| 順位 | 脆弱性 | 概要 |
|---|---|---|
| A01 | アクセス制御の不備 | 認可の不正回避 |
| A02 | 暗号化の失敗 | 機密データの平文送信 |
| A03 | インジェクション | SQLi・XSS・コマンドインジェクション |
| A04 | 安全でない設計 | セキュリティを考慮しない設計 |
| A07 | 認証の失敗 | 弱いパスワード・不適切なセッション管理 |
| A10 | SSRF | サーバーサイドリクエストフォージェリ |
SQLインジェクション攻撃と対策
脆弱なコード例(NG)
# 危険:文字列結合でSQL生成
user_input = "admin' OR '1'='1"
query = f"SELECT * FROM users WHERE username = '{user_input}'"
# 実際に実行されるSQL:
# SELECT * FROM users WHERE username = 'admin' OR '1'='1'
# → 全ユーザー情報が漏洩!
安全なコード例(プリペアドステートメント)
import sqlite3
# 安全:プリペアドステートメントを使用
def get_user_safe(username: str):
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
# パラメータ化クエリで安全にエスケープ
cursor.execute(
"SELECT * FROM users WHERE username = ?",
(username,) # タプルで渡す
)
return cursor.fetchone()
# SQLAlchemy(ORMを使うのが最善)
from sqlalchemy.orm import Session
def get_user_sqlalchemy(db: Session, username: str):
return db.query(User).filter(User.username == username).first()
XSS(クロスサイトスクリプティング)対策
脆弱なコード例(React)
// 危険:dangerouslySetInnerHTMLを安易に使用
const UserComment = ({ comment }) => (
// コメントにが含まれると実行される!
);
// 安全:テキストとして表示(Reactはデフォルトでエスケープ)
const SafeComment = ({ comment }) => (
{comment} // Reactが自動エスケープ
);
// HTMLが必要な場合はDOMPurifyでサニタイズ
import DOMPurify from "dompurify";
const SanitizedContent = ({ html }) => (
);
CSRF対策
# FastAPIでのCSRF対策
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer
import secrets
app = FastAPI()
# CSRFトークン生成
def generate_csrf_token():
return secrets.token_urlsafe(32)
# セッションにCSRFトークンを保存して検証
@app.post("/transfer")
async def transfer_money(
amount: float,
csrf_token: str,
session_token: str
):
stored_token = get_session_csrf_token(session_token)
if not secrets.compare_digest(csrf_token, stored_token):
raise HTTPException(status_code=403, detail="Invalid CSRF token")
# 処理続行...
JWT認証の安全な実装
from datetime import datetime, timedelta
import jwt
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
SECRET_KEY = "your-very-long-secret-key-here" # 環境変数で管理
ALGORITHM = "HS256"
def create_access_token(user_id: int) -> str:
expire = datetime.utcnow() + timedelta(minutes=30)
payload = {"sub": str(user_id), "exp": expire}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str) -> dict:
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expired")
except jwt.JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
# パスワードハッシュ化
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
まとめ
Webアプリのセキュリティ対策は開発初期から組み込む必要があります。本記事で紹介したSQLインジェクション・XSS・CSRF・JWT認証の対策を理解し、セキュアなアプリケーションを開発しましょう。定期的なセキュリティレビューとOWASP Top 10の最新情報のチェックも重要です。