【道·术·器·造器】 认证 · 会话 · RBAC · 网络基线
黄玮
2026-秋
每年泄露报告里排第一的,几乎不是零日漏洞(0day),而是弱口令、明文会话、越权——都不高级,但年年致命。
secret_key="REPLACE_ME"(:21)、USERS={admin:admin123}
明文(:28)、USERS.get(u)==p 比对(:46)深度理论见
https://github.com/c4pr1c3/cuc-ns-ppt/blob/master/chap0x03.md。本课件只讲「做 M1 所需」。
本单元实验 = M1,证据就是你的「加固代码 + 种子工程弱实现 vs 新实现 加固对照表」。实验见
labs/lab01-baseline.md。
| 认证(Authentication) | 授权(Authorization) | |
|---|---|---|
| 回答 | 你是谁 | 你能做什么 |
| 失败后果 | 冒充(Spoofing,破坏认证属性) | 越权(Elevation,破坏授权属性) |
| 本单元对应 | 口令哈希 + 失败锁定(任务 A) | RBAC 行级授权(任务 C) |
混淆二者是常见根因:很多人把「登录成功」当成「可以做任何事」——种子工程的
/orders正是只login_required、无授权校验 → 越权可读他人订单。
REPLACE_ME)regenerate)→
会话固定攻击/orders
不能只问「你登录了吗」,要问「这个 user
参数你是否有权读」admin 能管账户、alice
只能读自己的单——行级而非端点级USERS={admin:admin123} 是反面教材)原理(慢哈希、cost、pepper)见
https://github.com/c4pr1c3/cuc-ns-ppt/blob/master/chap0x03.md「口令安全」。
werkzeug.security.generate_password_hash(pw) /
check_password_hash(hash, pw) —— Flask 自带、最省事bcrypt —— 工业标准,可调 costpbkdf2 —— 标准库 / 通用框架常见/login:失败累计、阈值后拒、成功/超时清零;审计每条
login.fail(种子工程 :50 留了钩子,M6 可挂 AI
打分)| 属性 | 防什么 | 配置 |
|---|---|---|
| Secure | 明文 HTTP 下被窃听 | 仅 HTTPS 发送 |
| HttpOnly | JS 读取(XSS 偷 cookie) | document.cookie 取不到 |
| SameSite | CSRF(跨站借 cookie 发请求) | Lax/Strict |
app.config.update(
SESSION_COOKIE_SECURE=True, # 生产须 HTTPS
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE="Lax",
)
session.permanent=True +
PERMANENT_SESSION_LIFETIME 设上限——会话不能永久有效session.regenerate()(清旧 sid、发新的),防止攻击者预植的
sid 被受害者登录后复用REPLACE_ME 让签名可预测 → 改用
secrets.token_hex(32) 启动时随机化(闭环 M0
R4)import secrets
app.secret_key = secrets.token_hex(32) # 不再硬编码,落实 M0 R4
这是 M0 登记表 R4 的「落到代码」证据——评审会专门看
secret_key是否仍硬编码。
admin / alice
各自能做什么——一张角色-权限矩阵@rbac_required("admin")/orders
等「带参数查资源」端点,必须服务端强校验 user
参数种子工程
/orders直接信任前端传的user→ 越权读他人订单(M3 SQLi 之外的另一个必修点)。
@rbac_required 装饰器(端点级实现)def rbac_required(role):
def deco(fn):
@wraps(fn)
def w(*a, **k):
u = session.get("user")
if not u or USERS_ROLE.get(u) != role:
return jsonify({"err": "forbidden"}), 403
return fn(*a, **k)
return w
return deco
/orders 行级授权:服务端不信任何客户端入参user = request.args.get("user", session["user"]) →
前端传谁的 user 就查谁user 只能取自
session["user"](或显式比对
user == session["user"]),否则 403admin 的哈希丢进 hashcat + 字典,秒级还原
admin123 → 这就是为什么不能有弱口令⚠️ 这是「用器」——会调库、会跑工具只是开始。课程目标是「造器」:理解口令为何要加盐、会话为何要轮换、授权为何要行级,进而能设计带 AI 能力的认证与护栏(M6)。
# 生成一个测试哈希(自造、可逆、仅自检)
echo -n "admin123" | sha256sum
# 用字典模式爆破(仅对你自己的哈希、在授权环境内)
hashcat -m 1400 -a 0 myhash.txt rockyou.txt
这是「侦察可逆」的同一思想:攻击者能爆的,你理应先自爆出来。
| 维度 | 种子工程弱实现 | M1 新实现 | 闭环 |
|---|---|---|---|
| 口令 | USERS={admin:admin123}
明文(:28) |
generate_password_hash +
盐 |
R1 |
| 登录 | USERS.get(u)==p
明文比对(:46) |
check_password_hash +
失败锁定 |
R1 |
| secret_key | REPLACE_ME 硬编码(:21) |
secrets.token_hex(32) |
R4 |
| 维度 | 种子工程弱实现 | M1 新实现 | 闭环 |
|---|---|---|---|
| cookie | 无三件套 | Secure/HttpOnly/SameSite + 过期 | — |
| 授权 | 仅 login_required |
@rbac_required +
行级校验 |
— |
这张表是
docs/m1/report.md的核心——逐条对照、附测试佐证,体现 L3「工程化」而非「贴配置」。
任务 A 口令哈希 + 失败计数 / 锁定 ── 闭环 R1
任务 B 会话加固(cookie 三件套 + 过期 + 防固定 + 随机 secret)── 闭环 R4
任务 C RBAC(角色 + @rbac_required + /orders 行级授权)
任务 D 网络 / 传输基线(暴露面收敛 + HTTPS 思路 + iptables)
任务 E(可选)AI 辅助审查加固配置、生成对照表草稿
milestone/m1(从 milestone/m0
切,不是 main),开 MR 目标 =
milestone/m0git grep -nE 'generate_password_hash|bcrypt|pbkdf2'
/ 'secrets.token' / 'fail.*count|lock'iptables /
nftables 写收敛规则——默认 DROP、显式
ACCEPT# 仅放行 22 / 5000,其余入站默认拒绝(仅本机授权环境)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 5000 -j ACCEPT
sudo iptables -P INPUT DROP # 默认 deny
| 级 | 能力描述 | 自评勾选 |
|---|---|---|
| L1 | 复述 CIA/STRIDE/CVSS,识别资产与威胁 | ☐ U0 已点亮 |
| L2 | 对系统做威胁建模 + 风险登记表 | ☐ M0 已点亮 |
| L3 | 设计并实现 认证/会话/RBAC + 网络基线,并随项目演进 | ☐ M1 交付 |
docs/m1/report.md 逐项附证据路径127.0.0.1
或明确授权的环境内下一单元 U2 自侦察(M2):对你这版「已加固的应用」做暴露面测绘——你能看见自己暴露了什么,攻击者就能看见什么。