| name | web-security-audit |
| description | 基于 OWASP Top 10 (2021) 标准提供代码安全审查,逐项检查 SQL 注入、XSS、SSRF、访问控制、加密失败等常见漏洞,并给出具体的漏洞代码示例与修复方案。当用户需要代码安全审查、安全加固、渗透测试辅助,或提及 OWASP、安全检查、SQL 注入、XSS、代码审计、安全清单等关键词时触发此技能。 |
| license | MIT |
OWASP Top 10 代码安全检查清单
基于 OWASP Top 10 (2021) 标准,对代码进行逐项安全审查。每一项包含:漏洞说明、典型漏洞代码、检查要点、修复示例。适用于 Web 应用的安全 Code Review 场景。
使用方式
将待审查的代码文件或代码片段提供给 Claude,指定需要检查的 OWASP 项目(或全部检查),即可获得逐项审查报告。
示例提问:
- "帮我检查这段代码有没有 SQL 注入风险"
- "对这个项目做一次 OWASP Top 10 安全审查"
- "这个 API 接口有没有 SSRF 漏洞?"
快速参考
| 编号 | 类别 | 一句话检查重点 |
|---|
| A01 | 失效的访问控制 | 每个端点是否校验当前用户身份?能否通过改 ID 越权? |
| A02 | 加密失败 | 密码是否用 bcrypt/argon2?密钥是否硬编码? |
| A03 | 注入 | SQL 拼接?shell=True?模板未转义? |
| A04 | 不安全的设计 | 有无频率限制?关键操作能否被跳步? |
| A05 | 安全配置错误 | DEBUG 开着?错误页泄露堆栈?默认密码? |
| A06 | 过时的组件 | pip audit / npm audit 有 CVE 吗? |
| A07 | 认证失败 | JWT 验签名了吗?Token 能失效吗?有 MFA 吗? |
| A08 | 完整性失败 | 有 pickle.loads 反序列化不可信数据吗? |
| A09 | 日志监控失败 | 日志里有明文密码吗?登录失败有记录吗? |
| A10 | SSRF | 用户可控 URL 的请求过滤了内网 IP 吗? |
审查流程 SOP
关键原则:宁可多报 false positive,不可漏报 true positive。
- 确认审查范围 — 明确要检查的文件、模块或代码片段
- 逐项全覆盖检查 — 按 A01–A10 逐项扫描,每一项都必须在报告中体现(即使未发现问题也标注 ✅)。Claude 的默认行为是只报告发现的问题——这里要求完整覆盖,确保无遗漏
- 风险分级 — 按以下标准标注:
- 🔴 高危:可被直接利用(RCE、SQL 注入、SSRF 可达内网、明文密码存储)
- 🟡 中危:需特定条件才可利用(缺失频率限制、弱密码策略、静态 Token)
- 🟢 低危:防御纵深不足但无直接利用路径(缺安全头、日志不够详细)
- 每个发现必须附带可直接使用的修复代码(不是描述,是代码)。引用具体
文件:行号
- 输出审查报告 — 按下方模板输出,发现按风险等级降序排列,末尾给出修复优先级排序
A01:2021 — 失效的访问控制 (Broken Access Control)
风险说明: 用户能够越权访问其他用户的数据或执行未授权的操作。
检查要点:
漏洞代码示例
@app.route("/api/orders/<user_id>")
def get_orders(user_id):
orders = db.query(f"SELECT * FROM orders WHERE user_id = {user_id}")
return jsonify(orders)
修复示例
@app.route("/api/orders")
@login_required
def get_orders():
current_user_id = get_current_user().id
orders = db.query("SELECT * FROM orders WHERE user_id = %s", (current_user_id,))
return jsonify(orders)
A02:2021 — 加密失败 (Cryptographic Failures)
风险说明: 敏感数据(密码、信用卡号、个人信息)未加密或使用弱加密算法。
检查要点:
漏洞代码示例
import hashlib
SECRET_KEY = "my-secret-key-123"
def save_password(password):
hashed = hashlib.md5(password.encode()).hexdigest()
db.save(hashed)
修复示例
import bcrypt
import os
SECRET_KEY = os.environ["SECRET_KEY"]
def save_password(password):
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode(), salt)
db.save(hashed)
A03:2021 — 注入 (Injection)
风险说明: 用户输入未经过滤直接拼接到 SQL、命令、LDAP 等查询中,导致攻击者可执行任意查询或命令。
检查要点:
SQL 注入 — 漏洞代码
@app.route("/api/user")
def get_user():
username = request.args.get("username")
query = f"SELECT * FROM users WHERE username = '{username}'"
result = db.execute(query)
return jsonify(result)
SQL 注入 — 修复示例
@app.route("/api/user")
def get_user():
username = request.args.get("username")
result = db.execute(
"SELECT * FROM users WHERE username = %s",
(username,)
)
return jsonify(result)
命令注入 — 漏洞代码
import os
def ping_host(host):
os.system(f"ping -c 4 {host}")
命令注入 — 修复示例
import subprocess
import re
def ping_host(host):
if not re.match(r'^[a-zA-Z0-9.\-]+$', host):
raise ValueError("Invalid hostname")
subprocess.run(["ping", "-c", "4", host], check=True)
A04:2021 — 不安全的设计 (Insecure Design)
风险说明: 业务逻辑层面的设计缺陷,无法通过完美的实现来修复。
检查要点:
漏洞代码示例
@app.route("/api/verify-code", methods=["POST"])
def verify_code():
code = request.json["code"]
stored_code = session.get("verification_code")
if code == stored_code:
return jsonify({"status": "verified"})
return jsonify({"status": "invalid"}), 400
修复示例
@app.route("/api/verify-code", methods=["POST"])
def verify_code():
attempts = session.get("verify_attempts", 0)
if attempts >= 5:
return jsonify({"error": "尝试次数过多,请重新获取验证码"}), 429
code = request.json["code"]
stored = session.get("verification_code")
expire_at = session.get("code_expire_at", 0)
if time.time() > expire_at:
return jsonify({"error": "验证码已过期"}), 400
session["verify_attempts"] = attempts + 1
if code == stored:
session.pop("verify_attempts", None)
return jsonify({"status": "verified"})
return jsonify({"status": "invalid"}), 400
A05:2021 — 安全配置错误 (Security Misconfiguration)
风险说明: 应用或服务器使用默认配置、开启了不必要的功能、错误消息暴露敏感信息。
检查要点:
漏洞代码示例
app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SECRET_KEY"] = "default-secret"
@app.errorhandler(500)
def error_handler(e):
return jsonify({"error": str(e), "traceback": traceback.format_exc()}), 500
修复示例
import os
app = Flask(__name__)
app.config["DEBUG"] = os.environ.get("FLASK_DEBUG", "false").lower() == "true"
app.config["SECRET_KEY"] = os.environ["FLASK_SECRET_KEY"]
@app.errorhandler(500)
def error_handler(e):
app.logger.error(f"Internal error: {e}")
return jsonify({"error": "服务器内部错误,请稍后重试"}), 500
A06:2021 — 易受攻击和过时的组件 (Vulnerable and Outdated Components)
风险说明: 使用了存在已知漏洞的第三方库或框架版本。
检查要点:
检查命令
pip audit
npm audit
修复建议
pip install --upgrade package_name
npm audit fix
pip freeze > requirements.txt
A07:2021 — 身份识别和认证失败 (Identification and Authentication Failures)
风险说明: 认证机制存在缺陷,允许暴力破解、凭据填充、会话劫持等攻击。
检查要点:
漏洞代码示例
import jwt
def verify_token(token):
payload = jwt.decode(token, options={"verify_signature": False})
return payload
修复示例
import jwt
import os
JWT_SECRET = os.environ["JWT_SECRET"]
def verify_token(token):
try:
payload = jwt.decode(
token,
JWT_SECRET,
algorithms=["HS256"],
options={"require": ["exp", "iat", "sub"]}
)
return payload
except jwt.ExpiredSignatureError:
raise AuthError("Token 已过期")
except jwt.InvalidTokenError:
raise AuthError("无效的 Token")
A08:2021 — 软件和数据完整性失败 (Software and Data Integrity Failures)
风险说明: 未验证软件更新、关键数据、CI/CD 流水线的完整性,导致供应链攻击或数据篡改。
检查要点:
漏洞代码示例
import pickle
@app.route("/api/import", methods=["POST"])
def import_data():
data = pickle.loads(request.data)
process(data)
return "OK"
修复示例
import json
@app.route("/api/import", methods=["POST"])
def import_data():
try:
data = json.loads(request.data)
except json.JSONDecodeError:
return jsonify({"error": "无效的 JSON 格式"}), 400
process(data)
return "OK"
A09:2021 — 安全日志和监控失败 (Security Logging and Monitoring Failures)
风险说明: 缺乏安全事件的日志记录和监控,导致攻击无法被及时发现和响应。
检查要点:
漏洞代码示例
def login(username, password):
user = db.get_user(username)
if not user or not check_password(password, user.password_hash):
print(f"Login failed for {username} with password {password}")
return None
return create_session(user)
修复示例
import logging
security_logger = logging.getLogger("security")
def login(username, password):
user = db.get_user(username)
if not user or not check_password(password, user.password_hash):
security_logger.warning(
"登录失败",
extra={"username": username, "ip": request.remote_addr}
)
return None
security_logger.info(
"登录成功",
extra={"username": username, "ip": request.remote_addr}
)
return create_session(user)
A10:2021 — 服务端请求伪造 SSRF (Server-Side Request Forgery)
风险说明: 应用接受用户提供的 URL 并在服务端发起请求,攻击者可利用此访问内网资源或云元数据。
检查要点:
漏洞代码示例
import requests
@app.route("/api/fetch-url")
def fetch_url():
url = request.args.get("url")
response = requests.get(url)
return response.text
修复示例
import requests
import ipaddress
from urllib.parse import urlparse
import socket
BLOCKED_NETWORKS = [
ipaddress.ip_network("127.0.0.0/8"),
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
ipaddress.ip_network("169.254.0.0/16"),
]
def is_safe_url(url):
parsed = urlparse(url)
if parsed.scheme not in ("http", "https"):
return False
try:
ip = ipaddress.ip_address(socket.gethostbyname(parsed.hostname))
for network in BLOCKED_NETWORKS:
if ip in network:
return False
except (socket.gaierror, ValueError):
return False
return True
@app.route("/api/fetch-url")
def fetch_url():
url = request.args.get("url")
if not is_safe_url(url):
return jsonify({"error": "不允许访问该地址"}), 403
response = requests.get(url, timeout=10, allow_redirects=False)
response.text
审查报告模板
完成检查后,输出如下格式的报告。所有 10 项都必须出现,无发现的标 ✅:
# OWASP Top 10 安全审查报告
## 审查概览
- 审查范围:[文件/模块列表]
- 审查时间:[日期]
- 风险统计:🔴 高危 X 个 | 🟡 中危 X 个 | 🟢 低危 X 个 | ✅ 无发现 X 项
## 发现详情(按风险等级降序)
### [风险等级] [OWASP 编号] — [问题标题]
- **位置:** [文件:行号]
- **描述:** [问题描述]
- **影响:** [可能造成的危害]
- **修复代码:**(直接可用的代码,非描述)
### ✅ A0X — [类别名] — 未发现问题
## 修复优先级
1. [最紧急修复项 — 理由]
2. [次优先项 — 理由]
3. ...
常用自动化检查工具(开源免费)
| 工具 | 语言 | 用途 |
|---|
bandit | Python | Python 代码安全扫描 |
semgrep | 多语言 | 基于规则的代码扫描 |
eslint-plugin-security | JavaScript | JS 安全规则 |
npm audit / pip audit | JS / Python | 依赖漏洞扫描 |
trivy | 多语言 | 容器和依赖扫描 |
sqlmap | — | SQL 注入检测 |
OWASP ZAP | — | Web 应用动态扫描 |
注意: 本清单为辅助审查工具,不能替代专业渗透测试。对于高安全要求的系统,建议结合自动化扫描 + 人工审计 + 渗透测试。