Webセキュリティは現代のエンジニアに必須のスキルです。2026年現在、サイバー攻撃の被害額は世界で年間10兆ドル以上に達し、中小企業を含むあらゆる組織が標的になっています。本記事では、最も重要なWebセキュリティの脅威と対策を、実際のコード例とともに徹底解説します。
OWASP Top 10(2026年版)
- A01: アクセス制御の不備(最多発生)
- A02: 暗号化の失敗(機密データの平文送受信など)
- A03: インジェクション(SQLi、XSS、コマンドインジェクション)
- A04: 安全でない設計(脅威モデリングの不備)
- A05: セキュリティ設定のミス(デフォルト設定使用など)
- A06: 脆弱なコンポーネント(既知の脆弱性を持つライブラリ使用)
- A07: 認証・セッション管理の不備
- A08: ソフトウェア・データの整合性の失敗
- A09: セキュリティログ・監視の失敗
- A10: サーバーサイドリクエストフォージェリ(SSRF)
SQLインジェクション対策
脆弱なコード(絶対NG)
# 危険:文字列連結でSQLを構築
def get_user_vulnerable(username: str):
query = f"SELECT * FROM users WHERE username = '{username}'"
# username = "' OR '1'='1" のような攻撃が成立してしまう!
return db.execute(query)
安全なコード(パラメータ化クエリ)
# 正しい:パラメータ化クエリを使用
def get_user_safe(username: str):
query = "SELECT * FROM users WHERE username = %s"
return db.execute(query, (username,)) # プレースホルダーを使用
# SQLAlchemyでの例(ORM)
from sqlalchemy.orm import Session
def get_user_with_sqlalchemy(db: Session, username: str):
return db.query(User).filter(User.username == username).first()
# 入力値バリデーション
import re
from pydantic import BaseModel, validator
class LoginRequest(BaseModel):
username: str
password: str
@validator('username')
def validate_username(cls, v):
if not re.match(r'^[a-zA-Z0-9_-]{3,20}$', v):
raise ValueError('ユーザー名は英数字・アンダースコア・ハイフンのみ(3〜20文字)')
return v
XSS(クロスサイトスクリプティング)対策
// React(JSX)は自動エスケープなので基本安全
// ただしdangerouslySetInnerHTMLは危険
const SafeComponent = ({ userInput }) => (
// NG: <div dangerouslySetInnerHTML={{ __html: userInput }} />
<div>{userInput}</div> // OK: 自動エスケープされる
);
// HTMLを動的に生成する場合はDOMPurifyを使用
import DOMPurify from 'dompurify';
const SafeHTML = ({ htmlContent }) => {
const sanitized = DOMPurify.sanitize(htmlContent, {
ALLOWED_TAGS: ['p', 'br', 'b', 'i', 'a'],
ALLOWED_ATTR: ['href', 'target'],
});
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
};
// Content Security Policy(CSP)ヘッダー設定(Next.js例)
// next.config.js
const securityHeaders = [
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://www.googletagmanager.com",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"font-src 'self'",
"connect-src 'self' https://api.example.com",
].join('; ')
},
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
];
認証・セッション管理のベストプラクティス
import jwt
import bcrypt
from datetime import datetime, timedelta
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer
SECRET_KEY = "your-super-secret-key-change-this!"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# パスワードハッシュ化(bcrypt)
def hash_password(password: str) -> str:
salt = bcrypt.gensalt(rounds=12) # コスト係数12
return bcrypt.hashpw(password.encode(), salt).decode()
def verify_password(plain_password: str, hashed: str) -> bool:
return bcrypt.checkpw(plain_password.encode(), hashed.encode())
# JWTトークン生成
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire, "iat": datetime.utcnow()})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
# レート制限(ブルートフォース対策)
from functools import wraps
import time
from collections import defaultdict
login_attempts = defaultdict(list)
def rate_limit(max_attempts: int = 5, window: int = 300):
def decorator(func):
@wraps(func)
async def wrapper(request, *args, **kwargs):
ip = request.client.host
now = time.time()
attempts = [t for t in login_attempts[ip] if now - t < window]
if len(attempts) >= max_attempts:
raise HTTPException(
status_code=429,
detail=f"{window//60}分後に再試行してください"
)
login_attempts[ip].append(now)
return await func(request, *args, **kwargs)
return wrapper
return decorator
セキュリティ診断ツール
| ツール | 用途 | 価格 |
|---|---|---|
| OWASP ZAP | Webアプリの脆弱性スキャン | 無料 |
| Burp Suite Community | プロキシ・脆弱性テスト | 無料/有料 |
| Nmap | ポートスキャン・ネットワーク調査 | 無料 |
| Trivy | コンテナ・IaCの脆弱性スキャン | 無料 |
| Snyk | 依存関係の脆弱性チェック | 無料/有料 |
まとめ
Webセキュリティは後付けでは対処が難しく、設計段階から組み込む「Security by Design」が重要です。OWASPのガイドラインを参考に、パラメータ化クエリの使用、XSS対策、適切な認証・セッション管理を実装し、定期的なセキュリティ診断を行いましょう。セキュリティスキルを持つエンジニアは市場価値が高く、年収1,000万円以上の求人も多数あります。