L09 代码 — STRIDE + OWASP 安全审计
目标:用 STRIDE 矩阵对任意系统做威胁分类,再用 OWASP 检查清单找到代码中的具体危险模式。
运行方式:
sh
python stride_matrix.py "订单管理 API"
python owasp_checklist.py工具一:STRIDE 威胁矩阵生成器
第一步:定义六类威胁
python
import textwrap, sys
STRIDE = [
{
"letter": "S",
"threat": "欺骗(Spoofing)",
"description": "攻击者冒充其他实体",
"examples": ["未验证签名的 JWT", "缺少发送方身份验证"],
"audit_question": "所有身份声明是否经过密码学验证?",
},
{
"letter": "T",
"threat": "篡改(Tampering)",
"description": "攻击者在传输或存储中修改数据或代码",
"examples": ["未签名的 API 响应", "状态变更端点上的 CSRF"],
"audit_question": "所有写操作是否防止了未授权修改?",
},
{
"letter": "R",
"threat": "抵赖(Repudiation)",
"description": "用户否认执行了敏感操作",
"examples": ["管理员操作缺少审计日志", "写操作没有时间戳"],
"audit_question": "敏感操作是否记录了用户身份和时间戳?",
},
{
"letter": "I",
"threat": "信息泄露(Information Disclosure)",
"description": "敏感数据暴露给未授权方",
"examples": ["500 响应中返回堆栈追踪", "API 响应过度获取"],
"audit_question": "响应中是否包含了调用方不应看到的数据?",
},
{
"letter": "D",
"threat": "拒绝服务(Denial of Service)",
"description": "攻击者使服务不可用",
"examples": ["用户输入触发无限循环", "缺少速率限制"],
"audit_question": "单个客户端能否压垮任何端点?",
},
{
"letter": "E",
"threat": "权限提升(Elevation of Privilege)",
"description": "攻击者获得超出预期的权限",
"examples": ["资源端点上的 IDOR", "缺少授权检查"],
"audit_question": "每个敏感操作是否验证了调用者的角色?",
},
]关键行:每个威胁都有 audit_question — 这是审计时真正要在代码库里验证的问题,不是理论描述。
第二步:渲染威胁矩阵
python
def render_matrix(system_name: str = "目标系统") -> None:
print(f"STRIDE 威胁矩阵 — {system_name}")
print("=" * 72)
for item in STRIDE:
print(f"\n[{item['letter']}] {item['threat']}")
print(f" 威胁描述 : {item['description']}")
print(f" 典型例子 : {', '.join(item['examples'])}")
wrapped_q = textwrap.fill(
item["audit_question"], width=60,
subsequent_indent=" "
)
print(f" 审计问题 : {wrapped_q}")
print()
print("下一步:针对以上每类威胁,在代码库中搜索相关模式,")
print("将发现映射到 OWASP Top 10 类别。")
def main():
name = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "目标系统"
render_matrix(name)
if __name__ == "__main__":
main()工具二:OWASP Top 10 检查清单
第一步:定义十类漏洞和对应代码模式
python
OWASP_TOP_10 = [
{
"rank": 1,
"name": "访问控制失效",
"patterns": ["缺少 @login_required", "/api/ 上的 IDOR", "路径穿越 ../"],
"severity": "Critical",
},
{
"rank": 2,
"name": "加密失败",
"patterns": ["MD5(", "SHA1(", "配置中的 http://", "明文密码"],
"severity": "High",
},
{
"rank": 3,
"name": "注入",
"patterns": ['f"SELECT', "execute(query +", "shell=True", "eval("],
"severity": "Critical",
},
{
"rank": 4,
"name": "不安全设计",
"patterns": ["无速率限制", "直接对象引用", "缺少 CSRF token"],
"severity": "High",
},
{
"rank": 5,
"name": "安全配置错误",
"patterns": ["DEBUG=True", "默认密码", "详细错误信息", "CORS *"],
"severity": "High",
},
{
"rank": 6,
"name": "易受攻击的组件",
"patterns": ["requirements.txt", "package.json", "过期的固定版本"],
"severity": "High",
},
{
"rank": 7,
"name": "身份验证失败",
"patterns": ["无 MFA", "弱密码策略", "会话固定", "无注销"],
"severity": "High",
},
{
"rank": 8,
"name": "软件完整性失败",
"patterns": ["pickle.loads(", "yaml.load(", "deserialize(", "无校验和"],
"severity": "High",
},
{
"rank": 9,
"name": "日志记录失败",
"patterns": ["无审计日志", "日志中的敏感数据", "日志注入"],
"severity": "Medium",
},
{
"rank": 10,
"name": "SSRF",
"patterns": ["requests.get(url", "urllib.request", "未验证的重定向"],
"severity": "High",
},
]关键行:"patterns" 字段 — 这些是可以直接在代码库里 grep 的字符串,把安全审计变成可执行的搜索任务。
第二步:打印检查清单
python
def print_checklist() -> None:
print("OWASP Top 10 — 审计检查清单")
print("=" * 70)
print(f"{'#':<4} {'类别':<22} {'严重级别':<10} 需搜索的代码模式")
print("-" * 70)
for item in OWASP_TOP_10:
# 只显示前两个模式,避免一行太长
patterns_str = " | ".join(item["patterns"][:2])
print(f"{item['rank']:<4} {item['name']:<22} {item['severity']:<10} {patterns_str}")
print()
print("对每一行:在代码库中搜索模式,发现时记录:")
print(" 文件:行号 + 具体攻击场景 + 严重级别评估")
if __name__ == "__main__":
print_checklist()动手改一改
- 运行
stride_matrix.py "用户登录服务",哪个威胁类别和登录功能最相关? - 在
OWASP_TOP_10里,找到"注入"条目。在你自己的代码里搜索f"SELECT— 找到了吗? - 给 STRIDE 的
"I"(信息泄露)条目添加一个新的examples:你的项目里最可能出现的信息泄露场景是什么? - 为什么"可能有 SQL 注入"不是有效发现,而"
users.py:147行的 f-string 查询"是?用一句话解释。