如何建立安全判断能力
Published: Sat Feb 01 2025 | Modified: Sat Feb 07 2026 , 8 minutes reading.
1. 为什么要关注这个?
你已经学会了算法,了解了陷阱。但安全不是一份清单——而是一种判断。
每个安全决策都是成本、可用性和保护级别之间的权衡。没有”完美安全”——只有”对这个威胁模型足够安全”。
这篇文章教你如何思考安全,而不仅仅是实现它。
2. 安全思维
开发者 vs. 安全工程师
开发者思维:
"我如何让这个功能工作?"
- 关注功能
- 正向路径思考
- 信任输入
- 假设用户善意
安全思维:
"这个怎么能被破解?"
- 关注失败模式
- 对抗性思考
- 不信任一切
- 假设恶意意图像攻击者一样思考
对于每个功能,问:
1. 这做了什么假设?
2. 如果这些假设是错的呢?
3. 谁能访问什么?
4. 最坏情况会怎样?
5. 如果我是恶意的,我会怎么利用这个?
例子:密码重置
开发者:"用户点击链接,输入新密码,完成。"
攻击者:
- 如果我拦截了邮件呢?
- 如果我猜到重置令牌呢?
- 如果我请求重置别人的密码呢?
- 如果我使用令牌两次呢?
- 如果我在请求重置后更改邮箱呢?偏执的问题
部署任何功能之前:
认证:
- 有人能以另一个用户身份认证吗?
- 如果凭据被盗会发生什么?
- 尝试有速率限制吗?
授权:
- 用户能访问其他人的数据吗?
- ID 是否可猜测?
- 每一层都检查了权限吗?
数据处理:
- 数据在哪里以明文形式存在?
- 谁能访问加密密钥?
- 日志里有什么?
失败模式:
- 出问题时会发生什么?
- 错误消息会泄露信息吗?
- 有安全的降级方案吗?3. 威胁建模
什么是威胁模型?
威胁模型回答:
1. 我们在保护什么?(资产)
2. 谁可能攻击它?(威胁行为者)
3. 他们可能如何攻击?(攻击向量)
4. 可能出什么问题?(影响)
5. 我们如何预防?(缓解措施)
没有威胁模型,你要么:
- 防御不存在的威胁
- 遗漏存在的威胁
- 低效地分配资源STRIDE 框架
微软的 STRIDE 分类:
S - Spoofing(欺骗)
假冒他人身份
缓解:认证
T - Tampering(篡改)
修改数据或代码
缓解:完整性检查、签名
R - Repudiation(抵赖)
否认所做的操作
缓解:日志、审计追踪
I - Information Disclosure(信息泄露)
暴露机密数据
缓解:加密、访问控制
D - Denial of Service(拒绝服务)
使系统不可用
缓解:速率限制、冗余
E - Elevation of Privilege(权限提升)
获取未授权访问
缓解:最小权限、沙箱实用威胁建模
步骤 1:画出系统
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 客户端 │────▶│ API │────▶│ 数据库 │
└──────────┘ └──────────┘ └──────────┘
│
▼
┌──────────┐
│ 缓存 │
└──────────┘
步骤 2:标记信任边界
┌─────────────────────────────────────────────┐
│ 不受信任 │
│ ┌──────────┐ │
│ │ 客户端 │ │
│ └──────────┘ │
└─────────────────────────────────────────────┘
│ 信任边界
▼
┌─────────────────────────────────────────────┐
│ 受信任(但要验证) │
│ ┌──────────┐ ┌──────────┐ │
│ │ API │────▶│ 数据库 │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────┘
步骤 3:列出每个边界的威胁
客户端 → API:
- 注入攻击
- 认证绕过
- 速率限制滥用
- 数据篡改
API → 数据库:
- SQL 注入
- 权限提升
- 数据泄露威胁行为者画像
不同攻击者有不同的能力:
脚本小子:
- 使用现成工具
- 低复杂度
- 大量攻击
- 防御:基本安全卫生
网络犯罪分子:
- 财务动机
- 中等复杂度
- 针对性攻击
- 防御:强认证、监控
国家级行为者:
- 无限资源
- 高级能力
- 战略目标
- 防御:纵深防御,假设已被入侵
内部人员:
- 已有访问权限
- 了解系统
- 利用信任
- 防御:最小权限、审计日志
你的威胁模型是什么?
个人博客不需要防国家级攻击。
处理数十亿的银行需要。4. 评估风险
风险 = 概率 × 影响
│ 低概率 │ 高概率 │
────────────────────┼──────────────────┼─────────────────┤
高影响 │ 监控 │ 立即修复 │
────────────────────┼──────────────────┼─────────────────┤
低影响 │ 接受 │ 最终修复 │
────────────────────┴──────────────────┴─────────────────┘
评估示例:
登录中的 SQL 注入:
- 概率:高(常见攻击)
- 影响:高(完全数据库访问)
- 优先级:立即修复
比较中的时序攻击:
- 概率:低(需要精确度)
- 影响:中(凭据泄露)
- 优先级:最终修复
管理面板中的 XSS:
- 概率:低(有限用户)
- 影响:高(账户接管)
- 优先级:监控/修复安全的经济学
攻击者也做成本效益分析:
攻击成本 vs. 目标价值
低价值目标 + 高攻击成本 = 安全
高价值目标 + 低攻击成本 = 被攻破
你的目标:
1. 降低目标价值(最小化存储的数据)
2. 增加攻击成本(更好的安全)
3. 减少攻击者回报(限制爆炸半径)
真实例子:
- 目标:密码数据库
- 无哈希:一次泄露 = 所有凭据
- 使用 bcrypt:一次泄露 = 每个密码需要数月破解
- 攻击成本增加 1000 倍,保护价值相同什么是”足够好”?
安全总是相对于:
1. 你在保护什么
- 个人博客:基本安全
- 电商:强安全
- 医疗:合规 + 强安全
- 国防:最大安全
2. 你在防御谁
- 随机互联网:标准实践
- 针对性攻击者:高级措施
- 国家级:专门防御
3. 失败的后果
- 尴尬:基本保护
- 财务损失:强保护
- 安全/生命:最大保护
4. 可用资源
- 创业公司:优先处理最高风险
- 企业:全面覆盖
- 政府:纵深防御
"足够好" = 风险在可用资源内降低到可接受水平5. 常见安全决策
什么时候用什么
密码存储:
- 总是:Argon2id 或 bcrypt
- 绝不:MD5、SHA-1、纯 SHA-256
对称加密:
- 默认:AES-256-GCM
- 替代:ChaCha20-Poly1305
- 绝不:DES、3DES、ECB 模式
非对称加密:
- 密钥交换:X25519 或 ECDH P-256
- 签名:Ed25519 或 ECDSA P-256
- 遗留:RSA-2048+ 使用 OAEP
随机数:
- 总是:secrets 模块或 OS CSPRNG
- 绝不:random 模块用于安全
TLS:
- 最低:TLS 1.2
- 首选:TLS 1.3
- 绝不:SSL、TLS 1.0/1.1决策框架
选择安全控制时:
1. 行业标准是什么?
- 从已建立的最佳实践开始
- 只有充分理由才偏离
2. 威胁模型需要什么?
- 保护与威胁匹配
- 不要过度工程
3. 权衡是什么?
- 性能影响
- 可用性影响
- 维护负担
4. 失败模式是什么?
- 安全失败 vs. 开放失败
- 优雅降级
5. 我们能检测到失败吗?
- 日志和监控
- 异常告警安全讨论中的危险信号
某人不理解安全的警告信号:
"我们不需要担心那个"
- 泄露前的名言
"通过隐藏来安全"
- 攻击者会弄清楚的
"我们以后再加安全"
- 技术债务会累积
"它在防火墙后面"
- 防火墙是一层,不是唯一层
"我们用了[时髦词]所以我们安全了"
- 没有单一技术能解决安全
"没人会想攻击我们"
- 每个人都是目标
"我们的用户不会那样做"
- 永远不要信任用户行为
"那太不可能发生了"
- 在规模上不可能的事情经常发生6. 培养你的技能
从泄露事件中学习
每份泄露报告都是一课:
1. 漏洞是什么?
- 技术缺陷
- 流程失败
- 人为错误
2. 如何被利用?
- 攻击技术
- 使用的工具
- 利用时间
3. 如何被发现?
- 监控发现
- 攻击者报告
- 第三方发现
4. 什么能阻止它?
- 技术控制
- 流程改进
- 培训
资源:
- Krebs on Security
- Troy Hunt 的博客
- 公司泄露报告
- CVE 数据库练习进攻性安全
理解攻击有助于建立防御:
初学者:
- OWASP WebGoat
- HackTheBox 入门点
- TryHackMe 免费房间
中级:
- CTF 比赛
- 漏洞赏金计划(先只读)
- 易受攻击的虚拟机(DVWA、Metasploitable)
高级:
- 代码审查找漏洞
- 渗透测试课程
- 安全认证(OSCP)
你不需要成为专家攻击者。
但理解攻击能让你成为更好的防御者。安全审查清单
# 代码审查时要问的问题
class SecurityReviewChecklist:
"""
在审查代码时用作思维框架。
"""
authentication = [
"凭据是否安全存储(哈希密码)?",
"每个请求都检查了认证吗?",
"会话管理是否安全?",
"有暴力破解保护吗?",
]
authorization = [
"是否在正确的层检查了访问控制?",
"所有敏感操作都受保护吗?",
"遵循了最小权限原则吗?",
"用户能访问其他用户的数据吗?",
]
input_handling = [
"所有输入都验证了吗?",
"查询参数化了吗(没有 SQL 注入)?",
"输出编码了吗(没有 XSS)?",
"文件上传受限制吗?",
]
cryptography = [
"使用了标准算法吗?",
"密钥管理得当吗?",
"随机性来自安全来源吗?",
"敏感数据在静态/传输中加密了吗?",
]
error_handling = [
"错误消息会泄露信息吗?",
"异常处理是否安全?",
"系统是否安全失败?",
"错误是否适当记录?",
]
data_handling = [
"存储了什么敏感数据?",
"日志中有敏感数据吗?",
"数据备份如何处理?",
"需要时数据是否正确删除?",
]7. 与非安全人员合作
沟通风险
对高管:
- 用商业术语说话(风险、成本、影响)
- 使用类比("这就像让保险库敞开")
- 尽可能量化("泄露可能造成 X 百万损失")
- 呈现带权衡的选项
对开发者:
- 具体说明漏洞
- 解释攻击场景
- 提供具体修复方案
- 不要只说"这不安全"
对用户:
- 解释"为什么"不只是"什么"
- 让安全行为变得简单
- 不要责怪错误
- 将安全内建到产品中何时推回
有时你需要说不:
推回当:
- 截止日期压力凌驾于安全之上
- "就这一次"的例外积累
- 安全被当作可选项
- 已知漏洞没有被修复
如何推回:
- 解释具体风险
- 提出替代方案
- 记录决定
- 必要时升级
记录一切:
"在 [日期],我提出了对 [问题] 的担忧。
决定是 [接受/推迟]。
风险所有者:[姓名]。"建立安全文化
安全是每个人的工作:
对开发者:
- 在代码审查中包含安全
- 进行安全培训
- 让安全编码成为默认
- 表彰安全修复
对组织:
- 让报告漏洞变得安全
- 奖励安全贡献
- 在规划中包含安全
- 从事件中学习而不责备
对产品:
- 默认安全设置
- 清晰的安全文档
- 简单的安全配置
- 定期安全更新8. 判断框架
做安全决策
面对安全决策时:
1. 识别资产
我们到底在保护什么?
2. 评估威胁
谁可能攻击,如何攻击?
3. 评估风险
概率 × 影响
4. 考虑选项
有哪些缓解措施可用?
5. 权衡利弊
成本、可用性、维护
6. 决定并记录
做出选择,记录理由
7. 定期审查
威胁在变化,定期重新评估与不确定性共存
安全没有终点:
接受:
- 完美安全不存在
- 新漏洞会被发现
- 攻击者在进化他们的技术
- 你的威胁模型可能是错的
计划:
- 定期安全审查
- 事件响应
- 持续改进
- 从失败中学习
记住:
- 今天足够好明天可能不够
- 纵深防御提供韧性
- 检测和预防同样重要
- 恢复能力是必须的9. 总结
三件事要记住:
像攻击者一样思考。 对每个系统,问:“我怎么能破解这个?“考虑认证绕过、数据访问、信任边界和失败模式。防御者必须处处正确;攻击者只需要对一次。
安全是风险管理。 没有”完美安全”——只有成本、可用性和保护级别之间的权衡。理解你的威胁模型,现实地评估风险,在最重要的地方投入资源。
通过实践建立判断力。 研究泄露事件,练习进攻技术,带着安全思维审查代码,从每个事件中学习。安全判断来自经验,不仅仅是知识。
10. 系列结语
你已经走了很长的路:
第一部分:你学会了为什么密码学重要以及基本原语。
第二部分:你掌握了对称加密——AES、操作模式和密钥派生。
第三部分:你理解了非对称密码学——RSA、Diffie-Hellman 和椭圆曲线。
第四部分:你探索了哈希、MAC 和数字签名。
第五部分:你看到了这些组件如何在真实协议中组合——TLS、密码存储、密钥管理。
第六部分:你学会了为什么好的密码学还不够,以及如何全面思考安全。
最重要的一课:密码学是工具,不是解决方案。 正确使用它,但记住安全是一个系统属性,需要持续关注代码、运营和人的因素。
现在去构建安全的系统吧。当你不确定时,记住:最好的安全决策通常是能够充分应对威胁模型的最简单方案。
祝你好运。
