背景

OpenSSL是一个知名的开源安全套接字层密码库。全球成千上万的web服务器的网站加密技术使用OpenSSL。

网银、在线支付、电商网站、门户网站、电子邮件等互联网应用广泛使用OpenSSL实现数据的安全传输和安全存储。

历史上,OpenSSL多次出现安全漏洞。

2014年,OpenSSL爆出Heartbleed(心脏滴血)漏洞,网络出现了“致命内伤”。

心脏滴血称为互联网安全历史上最严重的漏洞之一,当时全球三分之二的网站可被该漏洞攻击。

心脏滴血漏洞的CVE编号是CVE-2014-0160,CVSS3.1打分7.5,属于严重漏洞。

业界使用CVE ID作为漏洞编号。CVE是通用漏洞披露(Common Vulnerabilities and Exposures)的英文缩写。

业界采用CVSS量化漏洞影响。CVSS是通用漏洞评分系统(Common Vulnerability Scoring System)的英文缩写。

CVSS得分最大为10,最小为0。得分7~10的漏洞通常认为严重,得分在4~6.9之间是中级漏洞,0~3.9是低级漏洞。

2021年8月24日,OpenSSL发布了OpenSSL 1.1.1l,该版本修复了一个高危漏洞:CVE-2021-3711。

根据

https://access.redhat.com/security/cve/cve-2021-3711

该漏洞的CVSS3.1打分8.1,属于严重漏洞。

该漏洞影响OpenSSL 1.1.1l之前的所有包含SM2商密算法版本。业界一些基于OpenSSL改造过的商用国密算法版本也可能受该漏洞影响。

本文结合OpenSSL公告、修复前后的OpenSSL代码和触发漏洞的sm2密文数据,分析CVE-2021-3711漏洞原理,并评估对腾讯自研国密算法库的影响。

漏洞分析

根据官网披露的信息细节https://www.openssl.org/news/secadv/20210824.txt

得出如下分析:

漏洞原因:SM2解密时分配了一块内存,解密后的结果可能大于该分配内存的容量,造成内存越界写。

以下是具体分析,使用CVE-2021-3711漏洞修复之前的OpenSSL 1.1.1代码。
1、OpenSSL EVP解密操作

OpenSSL EVP将常用的密码算法进行了封装,提供统一的密码学各种函数。

看示例图找规律,OpenSSL对密文的解密是什么样的操作?
示例1:crypto/evp/p_open.c

示例2:crypto/crmf/crmf_lib.c

示例3:crypto/cms/cms_env.c

示例4:crypto/pkcs7/pk7_doit.c

实际应用中密文的解密一般需要调用两次EVP_PKEY_decrypt。

第一次调用EVP_PKEY_decrypt,指针out为NULL,返回长度keylen。

通过OPENSSL_malloc分配一块keylen大小的堆内存。

第二次调用EVP_PKEY_decrypt,指针out为第一次调用所分配的内存,运算结束后存放解密结果。

2、EVP_PKEY_decrypt实现

在初始化EVP_PKEY_CTX结构后,通过EVP_PKEY_decrypt可以调用到具体的密码算法执行解密运算。

int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,unsigned char *out, size_t *outlen,const unsigned char *in, size_t inlen)
{int ret;...if (ctx->op.ciph.algctx == NULL)goto legacy;ret = ctx->op.ciph.cipher->decrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);return ret;legacy:...}

3、pkey_sm2_decrypt实现

对于SM2解密,EVP_PKEY_decrypt中的ctx->op.ciph.cipher->decrypt对应的是pkey_sm2_decrypt。

pkey_sm2_decrypt函数位于crypto/sm2/sm2_pmeth.c。

static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx,unsigned char *out, size_t *outlen,const unsigned char *in, size_t inlen)
{EC_KEY *ec = ctx->pkey->pkey.ec;SM2_PKEY_CTX *dctx = ctx->data;const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;if (out == NULL) {if (!sm2_plaintext_size(ec, md, inlen, outlen))return -1;elsereturn 1;}return sm2_decrypt(ec, md, in, inlen, out, outlen);
}

根据第一节OpenSSL EVP解密操作可知,第一次调用EVP_PKEY_decrypt函数时,指针out为NULL,返回长度作为接下来分配堆内存的大小。

这里sm2_plaintext_size函数返回outlen,作为接下来分配堆内存的大小。

4、sm2_plaintext_size实现

sm2_plaintext_size函数位于crypto/sm2/sm2_crypt.c

int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,size_t *pt_size)
{const size_t field_size = ec_field_size(EC_KEY_get0_group(key));const int md_size = EVP_MD_size(digest);size_t overhead;if (md_size < 0) {SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_DIGEST);return 0;}if (field_size == 0) {SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_FIELD);return 0;}overhead = 10 + 2 * field_size + (size_t)md_size;if (msg_len <= overhead) {SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING);return 0;}*pt_size = msg_len - overhead;return 1;
}

注意:返回的长度等于msg_len - overhead,而overhead = 10 + 2 * field_size+(size_t)md_size。

5、overhead存在的问题

sm2国密算法知识

关于overhead的设置,涉及SM2算法和SM2密文格式的知识,在此进行补充。

  1. SM2(SM是“商密”拼音的缩写)是我国商用密码的公钥密码标准,标准号为:GM/T 0003-2012。
  2. SM2标准中规定采用256比特的椭圆曲线域参数。
  3. SM2算法采用SM3算法作为算法步骤中的哈希算法,SM3算法的输出是256比特的哈希值。
  4. 根据GM/T 0009-2012,SM2密文格式如下:

这里,XCoordinate和YCoordinate是加密过程基于随机数计算出的椭圆曲线点的X坐标和Y坐标。

overhead取值分析

查看sm2_plaintext_size函数:

  1. field_size = ec_field_size(EC_KEY_get0_group(key)),对于SM2算法,field_size等于32。
  2. md_size = EVP_MD_size(digest),SM2算法采用SM3算法,因此md_size等于32。

从上述2点可知,sm2_plaintext_size函数中的overhead取值等于106(10+2*32+32)。

这里的magic number 10背后有什么含义呢?

  1. 对于SM2密文,ASN.1包括5个Tag和5个Length,ASN.1编码引入的长度不小于10个字节。分析如下:每个Tag占1个字节,5个Tag占5个字节。XCoordinate、YCoordinate和HASH由于值的长度范围相对固定,这3个Length占3个字节。取决于CipherText值,CipherText和第一个tag后面的Length长度不定,这2个Length可能超过2个字节。
  2. 这里overhead选择10,是选择SM2密文ASN.1编码引入的长度的最小值。

返回的长度等于msg_len - overhead,若overhead取值小,则返回长度大,分配内存大于实际需要,不会溢出。

这里的field_size没有考虑XCoordinate和YCoordinate的具体取值,有没有风险?

1)XCoordinate和YCoordinate是加密过程基于随机数计算出的椭圆曲线点的X坐标和Y坐标,满足以下方程:
YCoordinate * YCoordinate ≡ XCoordinate * XCoordinate * XCoordinate - 3 * XCoordinate + b(mod p)
这里,≡表示方程的左右两边模p的结果相等,p和b是SM2国密标准中规定的常数。

2)满足上述方程的XCoordinate和YCoordinate通常都是占32字节的大数。

3)如果密文中携带的XCoordinate占31字节,YCoordinate占32字节,则真实的overhead可能小于106。

此时使用msg_len - 106的结果去会分配空间,导致分配的空间小于解密后的结果,内存越界写。

4)存在满足上述方程的占31字节甚至更少的XCoordinate或YCoordinate吗?

OpenSSL给出的SM2密文数据示例给出了肯定的回答。

触发漏洞的数据示例

1、SM2密文数据

OpenSSL给出的密文数据示例如下:

3072022070DAD60CDA7C30D64CF4F278A849003581223F5324BFEC9BB329229BFFAD21A6021F18AFAB2B35459D2643243B242BE4EA80C6FA5071D2D847340CC57EB9309E5D04200B772E4DB664B2601E3B85E39C4AA8C2C1910308BE13B331E009C5A9258C29FD040B6D588BE9260A94DA18E0E6

2、解析SM2密文

这组密文的长度是116字节。按照ASN.1格式解析这组密文:
3072 //30表示SEQUENCE类型,72表示后续的数据总长度是114字节

0220 //02表示INTEGER类型,20表示该整数的长度是32字节

70DAD60CDA7C30D64CF4F278A849003581223F5324BFEC9BB329229BFFAD21A6 //32字节的XCoordinate

021F //02表示INTEGER类型,1F表示该整数的长度是31字节

18AFAB2B35459D2643243B242BE4EA80C6FA5071D2D847340CC57EB9309E5D //31字节的YCoordinate

0420 //04表示OCTETSTRING类型,20表示该字符串的长度是32字节

0B772E4DB664B2601E3B85E39C4AA8C2C1910308BE13B331E009C5A9258C29FD //32字节的HASH

040B //04表示OCTETSTRING类型,0B表示该字符串的长度是11字节

6D588BE9260A94DA18E0E6 //11字节的密文

经过验证,上述的XCoordinate和YCoordinate满足SM2椭圆曲线方程。

3、触发堆溢出

  1. 第一次调用pkey_sm2_decrypt,指针out为NULL,msg_len等于116。sm2_plaintext_size函数返回10(msg_len - overhead = 116 - 106)。
  2. 通过OPENSSL_malloc分配10字节的内存,out指向该内存。
  3. 第二次调用pkey_sm2_decrypt,由于密文有11字节,因此解密结果也是11字节。

out指向的内存是10字节,而解密结果是11字节,导致越界写1字节。

腾讯自研国密库不受该漏洞影响

近年来,国家积极推进国产密码基础设施的建设,推广与应用。

为贯彻落实国家密码战略,推进公司产品信息安全,腾讯自研了TencentSM国密算法库,摆脱对国外开源密码算法库的依赖。

TencentSM符合国密SM2、SM3以及SM4算法标准,已在腾讯多个业务中平稳运行。

TencentSM自研了SM2解密实现,未使用和参考OpenSSL该部分所对应的代码,不受该漏洞影响。

OpenSSL国密爆出8.1分高危漏洞CVE-2021-3711相关推荐

  1. OpenSSL 修复可导致 DoS攻击的高危漏洞

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 周二,OpenSSL 发布更新修复了一个可导致 DoS 攻击的高危漏洞. OpenSSL Project 表示该漏洞编号为 CVE-2 ...

  2. Fastjson 爆出远程代码执行高危漏洞,更新版本已修复

    漏洞介绍 fastjson在1.2.24以及之前版本近日曝出代码执行漏洞,当用户提交一个精心构造的恶意的序列化数据到服务器端时,fastjson在反序列化时存在漏洞,可导致远程任意代码执行漏洞. 风险 ...

  3. rsa签名算法实现_国密算法在链化未来区块链中的运用

    密码学是区块链的基础,区块链中大量采用了密码学算法,包括对称加密,非对称加密,单向散列算法,数字签名等技术. 为了实现密码学技术的自主可控,中国也定义了自己的国密标准,2020年央行颁布的<金融 ...

  4. 国密SM1、SM2、SM3、SM4算法资料大全

    SM2国密算法证书解析: http://blog.csdn.net/yyfzy/article/details/46798965 http://blog.csdn.net/sunboy2718/art ...

  5. Heartbleed第一篇:“心脏流血”高危漏洞情况通报(4月9日结果)

    /*************************************************************************************************** ...

  6. nvidia旧版驱动_N卡用户注意:老版驱动存在5个高危漏洞,赶紧更新

    8月5日消息,NVIDIA发布安全公告称,在目前的Windows显卡驱动中发现了五个高危级别的安全漏洞,用户可通过升级至最新版的431.60版本显卡驱动来修复这些漏洞. 据NVIDIA公告显示,这些漏 ...

  7. linux高危漏洞怎么处理,Struts2高危漏洞解决方案一览

    Apache Struts2作为世界上最流行的Java Web服务器框架之一,3月7日带来了本年度第一个高危漏洞--CVE编号CVE-2017-5638.其原因是由于Apache Struts2的Ja ...

  8. 记自己发现的—SM2国密算法应用的高危漏洞—CVE-2021-3711

    openssl在8月24日发布了openssl 1.1.1l的稳定版,其中修复了一个高危漏洞:CVE-2021-3711.该漏洞会影响openssl 1.1.1l 之前的所有包含SM2商密算法版本,其 ...

  9. openssl解析国密X509证书

    openssl解析国密X509证书,把公钥拿出来重写一下就行了         x = strToX509(pbCert, pulCertLen); dwRet = getCertPubKey(x,  ...

最新文章

  1. 【转载】基于AFNetWorking3.0的图片缓存分析
  2. ActionBarSherlock ViewPagerIndicator
  3. 场景联创 施耐德电气“绿色智能制造创赢计划”第二季收官
  4. layer弹出层 iframe层去掉滚动条 content : [url , 'no']
  5. 注册表应用100例—注册表使用全攻略之十一
  6. java设计模式,百度网盘
  7. 【数字图像处理课程设计】期中、期末综合考试题目整理总结(共四个图像处理算法应用题)
  8. 大学毕业生如何成功应聘高薪IT职位 [转]
  9. 浅谈标签概念及应用场景
  10. 关于dell戴尔笔记本磁盘空间莫名被占及删除System Volume Information
  11. 微信小程序编写一个试卷demo
  12. Vue3定义全局变量/方法
  13. 编写一个函数int isPrime(int x),当x是素数时,返回1,否则返回0; 在main函数中,输入一个正整数,如果是素数输出Y,否则输出N。
  14. CENTOS 8上安装极点五笔(自已测过)
  15. 90后魔术师李孟孟受邀参加中国圈子联合会活动
  16. 电机参数与脉冲当量的计算方法
  17. yapi接口导出为word_接口文档神器YApi
  18. 通用后台管理系统(2)-项目搭建
  19. python数据处理电脑配置_『大数据python计算机基础教学视频教程』入门学python需要什么配置的电脑...
  20. python3.8安装教程

热门文章

  1. 无人机拉力测试台螺旋桨的正确安装方式
  2. 无监督算法——自组织映射算法(Self-Organizing Map , SOM)
  3. STM32 GPIO_INIT()库函数的程序含义
  4. 什么是Web 2.0
  5. python升级pip版本后,pycharm还是显示老版本的解决办法
  6. 【报告分享】2021Q2中国线上高增长消费市场白皮书-魔镜市场情报 (附下载)
  7. 2022年茶叶市场分析报告
  8. 程序员职业发展的绊脚石-思想的枷锁
  9. 内存泄漏检测C版小工具
  10. Duolingo推出聊天学习机器人 让你免费学英语