2024年熵密杯 Flag3 精讲:证书伪造 — CA注册 + 持有者验证缺失

发布时间:2026/11/4 17:15:11

2024年熵密杯 Flag3 精讲:证书伪造 — CA注册 + 持有者验证缺失 2024年熵密杯 Flag3 精讲证书伪造 — CA注册 持有者验证缺失阅读指引本文是熵密杯2024年真题精析密码系统系列的第三篇。Flag3 考察的是证书认证中的身份验证缺失漏洞——系统在登录时验证了证书链的合法性Issuer/Subject字段、有效期、证书链却漏掉了最关键的一步验证证书持有者CommonName是否与登录用户名一致。同时系统开放了CA注册接口允许用户使用任意公钥申请合法证书。攻击者只需生成SM2密钥对 → 拿公钥去CA注册获取合法证书 → 用私钥证书管理员账号登录即可绕过认证无需伪造证书。 目录题目场景还原系统双接口分析漏洞分析关键字段验证缺失攻击链路合法证书 任意用户名代码实现攻击步骤详解攻击原理总结与防御1. 题目场景还原题目描述某数据库管理系统实现了基于 SM2 证书的挑战-应答登录认证。系统提供了两个接口(1) 登录接口需要提供用户名、私钥签名、证书三项(2) 注册接口允许用户提交裸公钥CA用根证书签发合法证书返回。请以管理员身份shangmibeiadmin登录系统获取 flag3。┌──────────────────────────────────────────────────────────────┐ │ 系统架构 双接口 │ │ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ 注册接口 /register │ │ 登录接口 /login │ │ │ │ │ │ │ │ │ │ 输入裸公钥(PEM) │ │ 输入username │ │ │ │ │ │ cert(PEM) │ │ │ │ 输出CA签发的证书 │ │ signature(hex) │ │ │ │ (合法证书!) │ │ │ │ │ └─────────┬───────────┘ │ 验证Issuer字段 ✓ │ │ │ │ │ Subject字段 ✓ │ │ │ │ │ 有效期 ✓ │ │ │ │ ┌──────────┤ 证书链签名 ✓ │ │ │ │ │ │ │ │ │ └─────┼──────────┤ CommonName ? │ ← 缺失! │ │ │ └─────────────────────┘ │ │ │ │ │ 攻击者拿着自己公钥 │ │ 通过CA注册拿到合法证书 │ │ 然后用私钥证书 │ │ 以 shangmibeiadmin 身份登录 │ │ → 证书是合法的 → 验证全通过 → flag3 │ └──────────────────────────────────────────────────────────────┘2. 系统双接口分析2.1 注册接口 — CA 证书签发系统提供了一个证书注册接口用户可以提交裸公钥raw public keyCA 会使用根证书为该公钥签发一个合法证书用户 ──提交裸公钥(PEM)──► CA 服务 │ ├─ 检查公钥格式是否正确 ├─ 使用根证书签发新证书 │ Subject.CommonName 用户提交的或默认值 │ Subject.PublicKey 用户提交的公钥 │ 用根证书私钥签名 │ 合法证书(PEM) ◄──┘关键事实任何人可以拿着任意公钥去CA注册获得一个由根证书签名的、完全合法的证书。该证书能通过所有密码学验证。2.2 登录接口 — 证书验证流程funcvalidateCertificate(cert,rootCert*x509.Certificate)error{// 第一层: Issuer 字段字符串比对ifcert.Issuer.CommonName!rootCert.Subject.CommonName{returnfmt.Errorf(证书校验失败)}ifcert.Issuer.Organization[0]!rootCert.Subject.Organization[0]{returnfmt.Errorf(证书校验失败)}// 第二层: 有效期检查iftime.Now().Before(cert.NotBefore)||time.Now().After(cert.NotAfter){returnfmt.Errorf(证书校验失败)}// 第三层: Subject 字段硬编码比对ifcert.Subject.Organization[0]!ShangMiBei{returnfmt.Errorf(证书校验失败)}ifcert.Subject.OrganizationalUnit[0]!ShangMiBei2024{returnfmt.Errorf(证书校验失败)}// 第四层: x509 证书链密码学验证roots:x509.NewCertPool()roots.AddCert(rootCert)opts:x509.VerifyOptions{Roots:roots}if_,err:cert.Verify(opts);err!nil{returnfmt.Errorf(证书链校验失败)}returnnil}2.3 验签流程funcvalidateSignature(message,signaturestring,publicKey*sm2.PublicKey)(bool,error){hexSignature,_:hex.DecodeString(signature)isValid:publicKey.Verify([]byte(message),hexSignature)returnisValid,nil}验签用的publicKey是从用户上传的证书中提取的——证书来自CA注册完全合法私钥在攻击者手中签名必然验真。3. 漏洞分析关键字段验证缺失漏洞致命: CommonName 持有者身份未验证整个验证流程检查了四项内容检查项验证内容结果Issuer 字段Issuer 根证书 Subject✅ 通过有效期NotBefore ≤ now ≤ NotAfter✅ 通过Subject 硬编码Org/OU 字段是否匹配✅ 通过证书链签名cert.Verify() 密码学验证✅ 通过CommonName vs username证书持有者 登录用户名?❌未检查!// 代码中缺失了这一行:// if cert.Subject.CommonName ! username {// return fmt.Errorf(证书持有者与登录用户不匹配)// }后果登录用户名username与证书持有者Subject.CommonName之间没有任何绑定关系。攻击者可以拿着以自己公钥注册的合法证书CommonName可能是自己的名字或默认值在登录时填写usernameshangmibeiadmin系统不会发现任何异常。为什么证书链验证全部通过因为证书本身就是合法的——它不是自签证书不是伪造证书而是通过CA正规注册流程签发的真实证书根证书 ──密码学签名──► 攻击者的证书 (CA签发) │ ├─ Issuer 根证书 Subject ✅ ├─ Subject.O ShangMiBei ✅ ├─ Subject.OU ShangMiBei2024 ✅ ├─ 有效期正常 ✅ └─ cert.Verify() 密码学验证 ✅证书完全合法但持有者不是管理员——而系统恰恰没检查这一条。4. 攻击链路合法证书 任意用户名步骤①: 生成攻击者的 SM2 密钥对 (privKey, pubKey) 步骤②: 将 pubKey 以 PEM 格式提交到注册接口 /register → CA 使用根证书签发合法证书 certPEM → certPEM 中的 PublicKey 攻击者的 pubKey 步骤③: GET /challenge?usernameshangmibeiadmin → 服务端返回 randomStr 步骤④: 用攻击者私钥 privKey 对 randomStr 做 SM2 签名 → signature SM2_Sign(privKey, randomStr) 步骤⑤: POST /login { username: shangmibeiadmin, ← 管理员账号 cert: certPEM, ← CA签发的合法证书 signature: hex(signature) ← 自己的私钥签名 } 步骤⑥: 服务端验证: ├─ validateCertificate(cert, rootCert) → ✅ 通过 (合法CA签发) ├─ 提取 cert.PublicKey → 攻击者的公钥 ├─ validateSignature(msg, sig, pubKey) → ✅ 通过 (自己私钥签名) └─ isAdmin (username shangmibeiadmin) → true! 步骤⑦: 签发 JWT → 管理员身份 → 访问 /admin/flag → flag3┌─────────────────────────────────────────────────────────────┐ │ 攻击链路全景 │ │ │ │ gmssl 生成密钥对 │ │ ┌──────────────────┐ │ │ │ privKey pubKey │ │ │ └───────┬──────────┘ │ │ │ │ │ ├──► pubKey ──► CA注册接口 ──► 合法证书 certPEM │ │ │ │ │ ├──► privKey ──► SM2签名(challenge) ──► signature │ │ │ │ │ └──► certPEM signature shangmibeiadmin │ │ │ │ │ ▼ │ │ POST /login │ │ │ │ │ ▼ │ │ ┌─────────────────────────────┐ │ │ │ 证书合法? ✅ (CA签发) │ │ │ │ 证书持有者 登录用户? ← 没查! │ ← 致命缺陷 │ │ │ 签名有效? ✅ (自己私钥签的) │ │ │ │ username shangmibeiadmin │ │ │ │ → isAdmin true │ │ │ └─────────────────────────────┘ │ │ │ │ │ ▼ │ │ JWT Token → GET /admin/flag → flag3{...} │ └─────────────────────────────────────────────────────────────┘5. 代码实现攻击步骤详解步骤①: 生成 SM2 密钥对fromgmsslimportsm2,func# 使用 gmssl 生成 SM2 密钥对# 方式一gmssl 命令行# $ gmssl genpkey -algorithm SM2 -out priv.pem# $ gmssl pkey -in priv.pem -pubout -out pub.pem# 方式二Python gmssl库sm2_cryptsm2.CryptSM2()priv_key_hexfunc.random_hex(64)# 32字节私钥pub_key_hexsm2_crypt.public_key_from_private(priv_key_hex)或使用合适的工具生成步骤②: 注册证书importrequests# 读取公钥 PEMwithopen(pub.pem,r)asf:pub_pemf.read()# 提交到注册接口resprequests.post(http://server/register,json{public_key:pub_pem})cert_pemresp.json()[certificate]# cert_pem 是 CA 用根证书签发的合法证书# 保存供后续使用withopen(cert.pem,w)asf:f.write(cert_pem)注意注册接口只是验证公钥格式PEM格式、SM2 OID不限制谁可以注册。任何人都能拿到由根证书签名的合法证书。步骤③④⑤: 请求challenge → 签名 → 登录fromgmsslimportsm2,func# 1. 获取 challenge以管理员身份请求resprequests.get(http://server/challenge?usernameshangmibeiadmin)random_strresp.json()[random_str]# 2. 用攻击者私钥对 challenge 做 SM2 签名sm2_cryptsm2.CryptSM2(private_keypriv_key_hex,public_key)signaturesm2_crypt.sign(random_str.encode())# 3. 发送登录请求resprequests.post(http://server/login,json{username:shangmibeiadmin,# ← 管理员账号cert:cert_pem,# ← 自己注册的合法证书signature:signature.hex()})# 4. 提取 JWT Token, 以管理员身份访问 flag 接口tokenresp.json()[token]flag_resprequests.get(http://server/admin/flag,headers{Authorization:fBearer{token}})print(flag_resp.json()[flag])# flag3{...}6. 攻击原理总结与防御为什么攻击能够成功系统设计了证书链密码学验证但忽略了授权的核心问题 证书持有者是谁 他有没有权限以这个用户名登录 ┌──────────────────────────────────────────────────────┐ │ 验证了什么 没验证什么 │ │ ─────────── ─────────── │ │ ✅ 证书是CA签发的吗 ❌ 证书是谁的 │ │ ✅ Issuer字段对吗 ❌ CommonName username? │ │ ✅ Subject硬编码对吗 ❌ 证书持有者 管理员? │ │ ✅ 有效期正常吗 │ │ ✅ 证书链签名有效吗 │ │ ✅ 挑战-应答签名对吗 │ └──────────────────────────────────────────────────────┘ 结果系统确认了证书是真的但没有确认证书是这个人的。 就像检查了身份证的防伪标识却没看照片和姓名。防御措施措施说明验证证书持有者登录时必须核对cert.Subject.CommonName username确保证书属于登录用户CA注册时验证身份不应允许任意用户以任意身份注册证书。CA签发前应验证申请者的真实身份公钥绑定服务端应预注册管理员公钥白名单而非从请求中的证书动态提取证书用途限制在证书扩展中设置 KeyUsage/ExtendedKeyUsage区分认证证书和签名证书OAuth/mTLS使用成熟的双向TLS认证或OAuth协议而非自建证书挑战-应答不信任用户提交的身份声明用户名用户声称的身份和证书密码学凭证必须交叉验证上一篇Flag2 — SM2协同签名 k3k2 攻击下一篇Flag4 — LCG状态恢复从IV破译SM4密钥
延伸阅读

更多相关文章

2026/10/24 6:35:46

JSP自定义标签深度解析:从原理到实战,掌握视图层组件化核心

1. 项目概述:为什么今天还要聊JSP标签?如果你是一位JavaWeb开发者,尤其是经历过从Servlet直接拼接HTML字符串“远古时代”走过来的朋友,看到“JSP标签”这个主题,可能会觉得有些“复古”。在前后端分离、各种现代化框架…

2026/10/31 16:42:19

AI工程师面试指南:理论与实战全解析

1. AI工程师面试全景解析:从基础理论到实战技巧最近在技术社区看到不少关于AI工程师面试的讨论,作为经历过数十场AI相关岗位面试的从业者,我想系统梳理一下这个领域的面试要点。不同于传统的软件开发岗位,AI工程师的面试往往兼具理…

2026/10/24 21:10:23

编程语言那么多,为何C语言能成为最成功的语言?

诞生五十多年后,C 仍然是历史上最具影响力的编程语言之一。每年都有新语言出现,承诺更高的生产力、更强的安全性或更简洁的语法。然而 C 仍在驱动着操作系统、嵌入式设备、数据库、编译器以及无数的软件项目。 为什么一门在 1970 年代初创造的语言能够保…

2026/11/4 17:13:15

HTTP 401认证失败全链路排查:从配置到请求头的深度解析

1. 一条401报错背后藏着多少层问题凌晨两点,监控面板上跳出一行红字:API call failed (attempt 1/3): AuthenticationError [HTTP 401]。很多人第一反应是"密钥过期了,换一个就行",然后改完配置重启,第二天同…

2026/11/4 17:13:15

WinForm 读串口电子秤重量:RS232 参数、帧解析与避坑指南

简介:这份资源面向需要在上位机软件中接入电子秤的 WinForm 开发者,聚焦耀华 3190-A12E 型号电子秤的串口(RS232)重量读取场景。代码区分了连续发送与指令两种工作模式:连续发送模式对应方案 2,指令模式对应…

2026/11/4 17:13:15

工业时序数据存储优化:TsFile架构与应用实践

1. 工业数据存储的范式转变在工业物联网和智能制造领域,我们正经历一场静默却深刻的数据存储范式迁移。传统的关系型数据库在面对高频传感器数据、设备状态日志等时序数据时,往往表现出"水土不服"——就像用Excel表格记录每秒1000次振动传感器…

2026/11/4 17:13:15

Linux软件包管理工具yum与开发工具vim/gcc实战指南

1. Linux软件包管理器yum深度解析1.1 软件安装的三种方式对比在Linux系统中,软件安装主要有三种方式,每种方式都有其适用场景和优缺点:源代码安装:原理:直接获取软件的源代码,手动编译安装典型流程&#xf…

2026/11/4 17:13:15

Agentic Coding与Doubao-Seed-Code结合提升代码质量

1. 项目概述:Agentic Coding与Doubao-Seed-Code的深度结合最近在代码优化领域出现了一个有趣的技术组合——将Agentic Coding理念与Doubao-Seed-Code工具相结合,实现对整个代码库的深度剖析与自动化改造。这种组合特别适合需要快速提升代码质量的中大型项…

2026/11/4 17:08:14

智能代理技术演进:从规则引擎到LLM的实践指南

1. 智能代理的认知进化之路在人工智能发展历程中,智能代理(Agent)的"大脑"构建方式经历了三次重大范式转移。早期基于硬编码规则的专家系统,如同用乐高积木搭建的固定结构,每个决策点都需要人工预先定义。随…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 0:03:20

AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年…

2026/11/4 0:03:20

从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你…

2026/11/4 0:03:20

32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑