mcpField
C
cryptographic-failures

cryptographic-failures

github.com/scholarly360安全2246 次安装29 周前更新
代码仓库

关于 cryptographic-failures

用于审查 Python 应用加密失效问题的安全技能,结合 Bandit 静态扫描、代码模式检查和修复建议,覆盖常见加密风险。

主要功能

  1. 01使用 Bandit 扫描加密问题
  2. 02检查密码哈希与随机数
  3. 03排查硬编码密钥和 TLS 验证
  4. 04审查 JWT 与对称加密
  5. 05提供 Python 框架专项指导

适用场景

  1. 01审计 Python 代码中的弱加密
  2. 02检查令牌和密码处理
  3. 03核查 TLS 与证书验证
  4. 04指导修复加密问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scholarly360/owasp-top10-web-skills --skill cryptographic-failures

安装后在 Claude Code 中输入/cryptographic-failures确认已加载。

附带文件references/owasp-a04-full.md

详细介绍

A04:2025 — 加密失效

OWASP 排名: 第 4 位(因 TLS 采用率提升,从第 2 位下降) 发生率: 3.80% 的应用,超过 160 万次,涉及 32 个 CWE

加密失效指用于保护静态和传输中数据的加密技术缺失、使用不当或强度不足。Python 中有一系列独特的陷阱,与 Java/.NET 中的情况有所不同。


本技能涵盖的内容

领域主要风险Python 特有陷阱
密码哈希算法强度不足或缺失使用 hashlib.md5/sha1,而非 bcrypt/Argon2
随机性值可预测使用 import random,而非 import secrets
硬编码密钥密钥泄露在源代码中使用 SECRET_KEY = "..." 字面值
TLS/SSL绕过证书验证在 requests/httpx 中使用 verify=False
JWT 密钥密钥强度/算法密钥强度不足,未固定算法
对称加密已弃用的模式ECB 模式,未使用经过身份验证的加密

逐步审计工作流

1. 使用 Bandit 进行静态扫描

运行 Bandit——这是用于自动检测加密问题的主要 Python SAST 工具:

pip install bandit
bandit -r . -t B303,B304,B305,B306,B311,B324,B501,B502,B503,B504,B505,B506 -f json -o bandit_crypto.json

与加密失效相关的 Bandit 测试 ID:

Bandit ID检测内容严重性
B303使用 MD5/SHA1中
B304/B305弱加密模式(ECB、DES)高
B311在安全相关场景中使用 random 模块低
B324使用 hashlib 的弱哈希中
B501在 SSL 上下文中使用 verify=False高
B502/B503/B504不安全的 SSL/TLS 版本中–高
B105/B106硬编码密码/密钥中
2. 手动检查代码模式

按优先级依次检查以下模式:

🔴 严重 — 密码哈希
# BAD — MD5/SHA1 for passwords: CWE-328, CWE-759, CWE-916
hashlib.md5(password.encode()).hexdigest()
hashlib.sha1(password.encode()).hexdigest()
hashlib.sha256(password.encode()).hexdigest()  # also bad — no salt, no stretching

# GOOD — use passlib with bcrypt or argon2
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
# OR
pwd_context = CryptContext(schemes=["bcrypt"], bcrypt__rounds=12, deprecated="auto")
hashed = pwd_context.hash(plain_password)

检查以下情况:

  • 使用任何 hashlib.* 调用对密码或令牌进行哈希
  • 缺少盐值(未使用 hashlib.pbkdf2_hmac,直接对原始密码进行哈希)
  • bcrypt 的 rounds < 12——应为 ≥12,以抵御暴力破解
🔴 严重 — 随机性不足(CWE-330)
# BAD — random is NOT cryptographically secure
import random
token = random.randint(100000, 999999)       # predictable OTP
reset_key = random.choice(string.ascii_letters + string.digits)  # guessable

# GOOD
import secrets
token = secrets.randbelow(900000) + 100000   # secure OTP
reset_key = secrets.token_urlsafe(32)        # secure reset token
session_id = secrets.token_hex(16)           # secure session ID

检查以下情况: 在涉及令牌、OTP、会话 ID、密钥或随机数的代码路径中,使用了任何 random.random()、random.randint()、random.choice()、random.shuffle()。

🔴 高 — 硬编码的加密密钥(CWE-321)
# BAD — key in source code
SECRET_KEY = "my-super-secret-key"
JWT_SECRET = "hardcoded_jwt_secret_123"
app.config['SECRET_KEY'] = "flask_secret"

# GOOD — load from environment
import os
SECRET_KEY = os.environ["SECRET_KEY"]        # raises KeyError if missing (intentional)
SECRET_KEY = os.getenv("SECRET_KEY")         # returns None silently (verify it's not None)

最低密钥长度:

  • Flask SECRET_KEY:≥32 个随机字节(使用 secrets.token_hex(32))
  • JWT HMAC 密钥:≥32 个字符
  • AES 密钥:128、192 或 256 位(16、24 或 32 字节)
🔴 高 — 绕过 TLS/SSL 证书验证(CWE-295)
# BAD — disables certificate validation entirely
requests.get(url, verify=False)
httpx.get(url, verify=False)
ssl._create_unverified_context()
urllib3.disable_warnings()  # companion to verify=False

# GOOD
requests.get(url)               # verify=True is the default
requests.get(url, verify="/path/to/ca-bundle.crt")  # custom CA
🟡 中 — JWT 配置(CWE-327)
# BAD — algorithm confusion attacks
jwt.decode(token, key, algorithms=["none"])  # NEVER allow "none"
jwt.decode(token, key)                       # no algorithm pin = vulnerable

# BAD — weak secret loaded without validation
JWT_SECRET = os.getenv("JWT_SECRET", "default")  # fallback default is dangerous

# GOOD
JWT_SECRET = os.environ["JWT_SECRET"]        # fail hard if missing
assert len(JWT_SECRET) >= 32, "JWT secret too short"
jwt.decode(token, JWT_SECRET, algorithms=["HS256"])  # explicit allowlist

另请检查:

  • 令牌过期时间(exp 声明)——访问令牌应为 15–30 分钟
  • 解码时会验证 aud 和 iss 声明
🟡 中 — 已弃用的对称加密(CWE-327)
# BAD — ECB mode leaks patterns in data
from Crypto.Cipher import AES
cipher = AES.new(key, AES.MODE_ECB)

# BAD — no authentication = vulnerable to tampering
cipher = AES.new(key, AES.MODE_CBC, iv)

# GOOD — authenticated encryption
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
# ChaCha20-Poly1305 is also acceptable

FastAPI 特定检查

# 1. Verify OAuth2/JWT middleware algorithm pinning
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt

ALGORITHM = "HS256"  # must be explicit, not a variable that could be overridden
# Check: is ALGORITHM loaded from config where it could be tampered with?

# 2. Verify password hashing in user creation/login endpoints
@router.post("/register")
async def register(user: UserCreate, db: Session = Depends(get_db)):
    hashed = pwd_context.hash(user.password)  # must NOT store plain or MD5

# 3. Token generation for password resets / email verification
def generate_reset_token() -> str:
    return secrets.token_urlsafe(32)   # GOOD
    # NOT: str(uuid.uuid4())  — UUID v4 uses os.urandom, acceptable but secrets is preferred
    # NOT: random-based anything

Flask 特定检查

# 1. Session cookie signing uses SECRET_KEY — must be strong
app.secret_key = os.environ["SECRET_KEY"]  # GOOD
app.secret_key = "dev"                     # BAD — common in tutorials, dangerous in prod

# 2. Flask-Login password verification
from flask_bcrypt import Bcrypt
bcrypt = Bcrypt(app)
bcrypt.generate_password_hash(password, rounds=12)  # rounds≥12

# 3. HTTPS enforcement via HSTS
from flask_talisman import Talisman
Talisman(app, force_https=True)  # adds HSTS header

关键 CWE 参考

CWE名称常见表现
CWE-327使用已破解/有风险的加密算法MD5、SHA1、ECB、DES、RC4
CWE-328可逆的单向哈希将 MD5/SHA1 用于密码(可通过彩虹表还原)
CWE-330随机值不足使用 random 模块生成令牌/密钥
CWE-321硬编码的加密密钥密钥写在源代码中
CWE-759单向哈希未使用盐值hashlib.sha256(password)——没有盐值
CWE-916密码哈希所用计算量不足bcrypt rounds<12,PBKDF2 迭代次数<600k
CWE-295证书验证不当在 HTTP 客户端中使用 verify=False

修复检查清单

Python 2025 最低可行加密技术栈
Password hashing:   passlib[argon2] or passlib[bcrypt] (rounds≥12)
Token generation:   secrets module exclusively
Symmetric crypto:   cryptography library, AES-GCM or ChaCha20-Poly1305
JWT:                python-jose or PyJWT, algorithm pinned, secret≥32 chars
TLS:                verify=True always; pin CA bundle where needed
Config/secrets:     os.environ (fail-hard) or a secrets manager (Vault, AWS SSM)
HSTS:               flask-talisman (Flask) or custom middleware (FastAPI)
用于代码搜索的快速正则表达式
# Find weak hashing
grep -rn "hashlib\.md5\|hashlib\.sha1\|hashlib\.sha224" --include="*.py"

# Find insecure random
grep -rn "import random\b" --include="*.py"
grep -rn "random\.randint\|random\.choice\|random\.random()" --include="*.py"

# Find hardcoded secrets
grep -rn "SECRET_KEY\s*=\s*['\"]" --include="*.py"
grep -rn "verify=False" --include="*.py"

# Find ECB mode
grep -rn "MODE_ECB\|AES\.MODE_ECB" --include="*.py"

另请参阅

  • references/owasp-a04-full.md — 完整的 OWASP A04:2025 规范及扩展 CWE 列表
  • 有关供应链加密问题(固定依赖哈希),请参阅 software-supply-chain 技能
  • 有关超出加密范畴的 JWT 身份验证逻辑(过期时间、声明),请参阅 authentication-failures 技能

评论

支持 Markdown