第三节:签名算法基础(RSA/PKI)
各位同学,今天我们来聊聊RSA数字签名和PKI体系。说实话,这部分内容在固件安全分析中特别重要。我见过不少团队,逆向能力很强,但一碰到签名验证就卡住了。说白了,不懂签名算法,你就没法真正理解固件更新包的安全机制。
3.1 RSA数字签名原理
RSA签名,本质上就是「用私钥签名,用公钥验签」。这个逻辑很简单,但实际应用中坑不少。
我习惯把RSA签名比作「数字印章」。你有一枚私章(私钥),盖在文件上(签名),别人用你的公章印模(公钥)来验证。如果对得上,说明文件确实是你盖的,而且没被篡改过。
具体流程是这样的:
- 签名方:对固件哈希值用私钥加密,生成签名
- 验证方:用公钥解密签名,得到哈希值A
- 验证方:重新计算固件哈希值B
- 比对:A == B 则签名有效
核心公式:
签名 = (hash)^d mod n
验证 = (signature)^e mod n == hash
其中 (n, e) 是公钥,d 是私钥
我在分析某款路由器固件时,发现它的签名长度是2048位。嗯,这个长度现在还算安全。但有些老设备还在用1024位,那就有点危险了。
3.2 PKI体系在固件签名中的应用
PKI(公钥基础设施)说白了就是一套管理公钥的规则。在固件签名场景中,它主要解决一个问题:你怎么知道手里的公钥是真的?
思科的做法是:
- 根CA证书:思科自己签发的顶级证书
- 中间CA证书:由根CA签发,用于日常签名
- 固件签名证书:由中间CA签发,直接用于固件签名
这个链条叫「证书链」。验证固件时,设备会从固件签名证书开始,一路验证到根证书。只要根证书是设备信任的,整个链条就成立。
实战经验:我曾经在分析一台Cisco Catalyst交换机时,发现它的根证书硬编码在BootROM里。这意味着即使你替换了Flash中的固件,只要BootROM没被改,签名验证就绕不过去。
3.3 公钥提取与验证流程
公钥提取是逆向工程中的关键步骤。我一般这么干:
- 从固件中定位证书或公钥数据
- 识别证书格式(DER、PEM等)
- 提取公钥模数n和指数e
- 验证公钥有效性
下面是一个典型的公钥提取代码示例:
# 从固件中提取RSA公钥
import struct
def extract_rsa_pubkey(firmware_data, offset):
# 假设已知偏移位置
# 读取模数n(2048位 = 256字节)
n_bytes = firmware_data[offset:offset+256]
# 读取指数e(通常为65537,4字节)
e_bytes = firmware_data[offset+256:offset+260]
n = int.from_bytes(n_bytes, 'big')
e = int.from_bytes(e_bytes, 'big')
return (n, e)
# 验证公钥
def verify_pubkey(n, e):
# 检查n是否为素数乘积
# 检查e是否为常用值
if e != 65537:
print("警告:指数不是标准值")
# 检查n的长度
if n.bit_length() != 2048:
print("警告:模数长度不是2048位")
注意:提取公钥时,一定要确认字节序。思科设备通常使用大端序,但有些厂商会用小端序。我踩过这个坑,花了两天才发现是字节序搞反了。
3.4 签名验证的完整流程
理解了原理,我们来看看实际验证流程。我画了一张流程图,帮你理清思路:
这个流程看起来简单,但实际逆向时你会发现很多变种。比如有些设备会先验证证书链,再验证签名;有些则直接把公钥硬编码在代码里。
3.5 常见绕过思路
了解了签名验证的原理,我们来看看常见的绕过思路。注意,这些内容仅供学习研究使用。
| 绕过方式 | 原理 | 难度 |
|---|---|---|
| 公钥替换 | 找到公钥存储位置,替换为自己的公钥 | 中等 |
| 签名验证函数patch | 修改验证函数,使其始终返回成功 | 较低 |
| 证书链攻击 | 利用中间CA证书的漏洞签发假证书 | 较高 |
| 哈希碰撞 | 构造与原固件哈希相同的恶意固件 | 极高 |
避坑指南:我曾经尝试公钥替换,结果发现公钥被校验和保护了。改完公钥后,设备直接变砖。所以动手前一定要先做完整备份。
3.6 实战中的注意事项
最后,分享几个我在实际项目中总结的经验:
- 先定位,再分析:用binwalk或hexdump先找到签名数据的位置
- 注意填充方式:RSA签名常用的填充方式有PKCS#1 v1.5和PSS,别搞混了
- 哈希算法要确认:思科常用SHA-256,但老设备可能用SHA-1
- 备份!备份!备份!:重要的事情说三遍
嗯,关于RSA和PKI的基础知识就讲到这里。这些内容虽然偏理论,但后面分析具体固件时都会用到。你想想看,如果连签名算法都不懂,怎么去分析签名验证的漏洞呢?