查看原文
其他

浅谈国密算法在Linux内核文件完整性保护上的实践

乾越,熙羽 云巅论剑 2022-05-30

背景

随着近年来国际贸易冲突和技术封锁,互联网的快速发展,以及IOT领域的崛起,金融领域的变革愈演愈烈。摆脱对国外技术和产品的过度依赖,建设行业网络安全环境,增强我国行业信息系统的安全可信显得尤为必要和迫切。


密码算法是保障信息安全的核心技术,尤其是当下互联网核心领域长期以来都是沿用AES、SHA-2、RSA等国际通用的密码算法体系及相关标准。


Linux内核和OpenSSL作为互联网的基础软件底座,近几年才对国密算法做了有限的支持,比如内核只实现了基础的SM3摘要算法和SM4对称加密,鉴于以上原因,近期我们在Linux上游社区实现了SM2非对称算法和国密证书,补齐了国密算法在内核的这块短板,并且率先在Alibaba Cloud Linux发行版输出。同时蚂蚁的相关团队也积极投入,把国密标准推向了OpenSSL社区,并为国密标准的国际化做出了极大的贡献。


OS内核安全一直是安全界重点研究的课题,今天我们使用国密算法来支撑Linux内核IMA安全子系统,为客户输出值得信赖的安全可信技术。



IMA简介

IMA是Integrity Measurement Architecture的缩写,它是Linux内核中完整性子系统的一部分。目前Linux内核的完整性子系统支持EVM和IMA,前者用于保护文件的扩展属性。这篇文章讨论的是后者。


IMA所能做到的事情包括:


  • 能够对正在打开的文件进行完整性评估

  • 能够对正在执行exec的文件(可执行程序)进行完整性评估

  • 能够对正在执行mmap(PROT_EXEC)的文件(共享库)进行完整性评估

  • 能够对正在加载中的kernel模块和固件进行完整性评估


所谓的完整性评估指的是对内核对文件客体在执行特定的内核操作时,会主动对文件的内容进行完整性检查。为此,IMA子系统会借用内核的security子系统在open(), execve(), mmap()等系统调用中下的hook来执行自己的代码。


IMA签名验证

IMA在进行完整性验证时,会通过事先存储在文件系统中的文件扩展属性security.ima进行。具体来说,借用IMA签名工具evmctl,在系统部署的时候,管理员以特权用户身份将文件的完整性信息写入文件扩展属性security.ima中。


在系统运行时,IMA子系统会从该扩展属性中读取出文件的完整性信息,同时与实际计算出的完整性信息进行比较。如果结果一致,证明该文件没有遭到过篡改,则允许执行后续的操作;如果结果不一致,证明文件内容遭到了篡改,则后续操作禁止执行。


因此,即使攻击者通过密码破解拿到了本地特权,或者利用安全漏洞拿到了本地特权,但是在准备运行恶意程序或植入了后门的程序的时候,因为在没有IMA私钥的情况下是无法构造出合法的IMA签名的,因此导致恶意程序或被篡改了的程序均无法运行。即使带有IMA保护的存储设备受到离线攻击(比如把存储设备从主机上取下,拿到另一台机器上进行修改,然后再重新安装到主机上),被篡改的文件或攻击者植入的恶意软件在运行时依旧无法运行,这在一定程度上能够抑制类似Dirty Cow这样的内核漏洞所带来的危害。


IMA国密化


所谓IMA国密化,就是在IMA整个签名验证流程中,用国密算法SM3代替国际常用的哈希算法SHA256,SHA512等,用SM2算法的签名验签取代RSA算法。


本文中用到的主要是以下公开的国密算法:


  • SM2:基于椭圆曲线密码(ECC)的公钥密码算法标准,提供数字签名,密钥交换,公钥加密,用于替换RSA/ECDSA/ECDH等国际算法

  • SM3:消息摘要算法,哈希结果为256 bits,用于替换MD5/SHA1/SHA256等国际算法



Alibaba Cloud Linux简介

Alibaba Cloud Linux 操作系统(原名 Aliyun Linux)是一款开源且免费的 Linux 操作系统发行版,旨在为阿里云 ECS 客户提供丰富功能,高性能且稳定的操作系统服务。它为云上应用程序环境提供 Linux 社区的最新增强功能,在提供云上最佳用户体验的同时,也针对阿里云基础设施做了深度的优化。Alibaba Cloud Linux 2 OS 镜像可以运行在阿里云全规格系列 VM 实例上,包括弹性裸金属服务器 (神龙)。


在 2020 年,Alibaba Cloud Linux 操作系统加入了 OpenAnolis 社区,OpenAnolis 是一个开源操作系统社区及系统软件创新平台,致力于通过开放的社区合作,推动软硬件及应用生态繁荣发展,共同构建云计算系统技术底座。现如今,Alibaba Cloud Linux 是社区发行版 Anolis OS 的下游发行版之一。


Alibaba Cloud Linux 2 是 Alibaba Cloud Linux 的下一代版本,其开发团队是阿里巴巴操作系统团队,前身是淘宝内核组。九年来,团队成员大多是活跃在内核社区的开发者,积累了深厚的操作系统和内核开发底蕴。


可以访问 Alibaba Cloud Linux 2 的产品文档以获取产品更多信息。


BabaSSL简介

BabaSSL是在OpenSSL开源协议下发布的开源且免费的密码学库,在提供了完整国密算法的基础上,完全兼容OpenSSL 1.1.1版本。


BabaSSL是诞生于蚂蚁、后成为整个阿里集团的底层密码库产品,为集团的各种业务提供基础的密码学功能,目前BabaSSL正在服务的、以及即将服务的对象包括但不限于:支付宝手机App、spanner、mosn、tengine、OceanBase、钉钉App、阿里云…… BabaSSL在阿里集团内部替换掉了开源的OpenSSL版本,并根据集团的需求提供了特有功能,其中包括对在大规模互联网场景下合规使用国密算法的能力。BabaSSL是支持整个阿里集团应对《密码法》所要求的监管合规需求的核心组件。


可以访问BabaSSL官方仓库以获取更多详细信息。



准备环境

主要的环境包括操作系统和上层密码学相关工具包,操作系统这里选择ECS上开箱即用的Alibaba Cloud Linux,目前最新的版本已经完整支持了全套国密算法SM2/SM3/SM4以及SM2-with-SM3类型的国密证书,也是当下国内唯一支持国密的Linux发行版,并且默认开启了IMA特性。


关于上层工具,由于IMA的安全性完全构建在密码学基础上的,因此IMA实践就离不开openssl的使用。能比较好的支持国密算法和国密证书的openssl版本是3.0版本,当下这个版本仍处于alpha阶段,还未正式发布,经过权衡,这里我们选择babassl,这是蚂蚁集团基于openssl 1.1.1稳定版开发的,是完整实现了国密标准的密码学库,babassl目前已经在Alibaba Cloud Linux 的yum源了,可以直接通过yum install安装。


安装实践IMA必要的工具包,为了不影响系统基础库,babassl会安装到/opt/babassl目录。


sm-ima-evm-utils作为ima用户态工具包,主要用于为文件做IMA签名,sm-ima-evm-utils是基于ima-evm-utils重新编译的依赖babassl的版本。


yum install babassl sm-ima-evm-utils keyutils
# 更新环境变量export LD_LIBRARY_PATH=/opt/babassl/libexport PATH=/opt/babassl/bin:$PATH


生成相关的国密秘钥和证书

为了使用IMA功能,先要准备以下密钥和证书:


  • IMA私钥,与IMA证书对应的SM2私钥,用于签名文件

  • IMA证书,由CA根证书签名,系统启动后动态导入内核

  • CA根证书,自签名的证书,作为信任根内置到内核里


# 创建签名证书请求使用的配置文件openssl.cnfcat > openssl.cnf << EOF[ req ]default_bits = 2048distinguished_name = req_distinguished_nameprompt = nostring_mask = utf8onlyx509_extensions = v3_req
[ req_distinguished_name ]O = TestOU = TestCN = Test keyemailAddress = test@foo.com
[ v3_req ]basicConstraints=critical,CA:FALSEkeyUsage=digitalSignaturesubjectKeyIdentifier=hashauthorityKeyIdentifier=keyid:alwaysEOF
# 生成SM2私钥private.pemopenssl ecparam -genkey -name SM2 -out private.pem
# 从私钥生成证书请求openssl req -new \ -key private.pem \ -out csr.pem \ -sm3 -sigopt "sm2_id:1234567812345678" \ -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Alibaba/OU=OS/CN=test/emailAddress=test@foo.com"
# 生成一个自签名的根证书ca.crt,作为CA证书openssl ecparam -genkey -name SM2 -text -out ca.keyopenssl req -new \ -x509 -days 3650 \ -key ca.key \ -out ca.crt \ -sm3 -sigopt "sm2_id:1234567812345678" \ -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Alibaba/OU=OS/CN=CA/emailAddress=ca@foo.com"
# 使用CA证书给SM2证书请求签名,生成IMA要使用的国密证书cert.pemopenssl x509 \ -req -days 3650 \ -in csr.pem \ -out cert.pem \ -sm3 \ -sigopt "sm2_id:1234567812345678" \ -sm2-id "1234567812345678" \ -CA ca.crt -CAkey ca.key -CAcreateserial \ -extfile openssl.cnf -extensions v3_req



编译内核

生成了CA证书之后,我们就需要把CA根证书内置到内核,这就需要重新编译内核。


首先参考以下地址下载Alibaba Cloud Linux代码,按如下方法编译并安装集成了CA证书的内核:


# alinux2上modsign_alinux.pem就是默认配置的系统信任根证书# 用上一步生成好的ca.crt替换掉这个证书,使用默认配置编译内核cp -f cert.pem <kernel_src>/certs/modsign_alinux.pem
# 进入内核源码目录,使用默认配置编译内核cd <kernel_src>cp -f configs/config-4.19.y-x86_64 .configmake -j8
# 安装modulesmake modules_install
# 安装内核,这一步也会自动生成initramfs并更新grub.cfgmake install
# 如果上一步没有更新grub.cfg,就需要手动更新grub配置文件# 注意grub.cfg的位置,一般来说,# 传统BIOS启动时grub.cfg路径是/boot/grub2/grub.cfg,# EFI引导的路径是/boot/efi/EFI/alinux/grub.cfg# grub2-mkconfig -o /boot/grub2/grub.cfg
# 必要的话使用grub2-set-default调整grub的启动顺序,确保下次启动运行的是新内核reboot


重启机器后,通过/proc/keys或者keyctl可以看到我们的SM2根证书已经内置到了内核中:


# cat /proc/keys029ff3ba I------ 2 perm 1f0b0000 0 0 keyring .builtin_trusted_keys: 209792b49 I--Q--- 3 perm 1f3f0000 0 65534 keyring _uid.0: empty12a07ca6 I--Q--- 1 perm 1f3f0000 0 65534 keyring _uid_ses.0: 115832663 I------ 1 perm 1f0f0000 0 0 keyring .evm: empty1e407f54 I------ 1 perm 1f030000 0 0 asymmetri Build time autogenerated kernel key: 8a9b02b3b7b2c8b27e92a0ab370905d79f310478: X509.rsa 9f310478 []278c7bfc I------ 1 perm 1f0f0000 0 0 keyring .ima: empty2e317b59 I--Q--- 6 perm 3f030000 0 0 keyring _ses: 12f5c960a I------ 1 perm 1f0f0000 0 0 keyring .secondary_trusted_keys: 1377880b2 I------ 1 perm 1f0f0000 0 0 keyring .ima_blacklist: empty38272dc6 I------ 1 perm 1f0b0000 0 0 keyring .blacklist: empty39620425 I------ 1 perm 1f030000 0 0 asymmetri Alibaba: CA: 10024aa19b7b8d73f4b3b413f70bcf94806f9ca2: X509.sm2 806f9ca2 []
# keyctl show %:.secondary_trusted_keysKeyring 794596874 --alswrv 0 0 keyring: .secondary_trusted_keys 44037050 --alswrv 0 0 \_ keyring: .builtin_trusted_keys 507543380 --alswrv 0 0 \_ asymmetric: Build time autogenerated kernel key: 8a9b02b3b7b2c8b27e92a0ab370905d79f310478 962724901 --alswrv 0 0 \_ asymmetric: Alibaba: CA: 10024aa19b7b8d73f4b3b413f70bcf94806f9ca2



IMA实践

导入IMA证书到内核

为了使用IMA功能,我们需要把前面用CA证书签名的IMA证书cert.pem导入到内核,之后才能用该证书正确验签IMA私钥签名的文件,因为内核已经集成了CA证书,也只有CA签名的证书才能成功导入内核。


导入证书一般有两种方法,以下两者任选其一:


  • 持久性导入,一般在产品化时使用,需要更新initramfs,把ima证书放到initramfs的/etc/keys/x509_ima.der,这也是内核启动时识别的路径,之后中IMA证书会在启动阶段由dracut自动导入

# 内核只支持导入DER格式的证书openssl x509 -in cert.pem -out cert.der -outform der
# 持久性导入sudo mkdir /etc/keysdracut --include ima.der /etc/keys/x509_ima.der \ /boot/initramfs-`uname -r`.img --force# 确保initramfs中正确打包了IMA证书lsinitrd /boot/initramfs-`uname -r`.img | grep x509_ima.der


  • 非持久性导入,临时用keyctl导入,系统重启后会失效

# 非持久性导入, 重启后失效keyctl padd asymmetric "IMA" %:.ima < cert.der


IMA证书导入成功后,我们可以从/proc/keys看到证书信息:

# cat /proc/keys03cd0857 I------ 1 perm 1f030000 0 0 asymmetri Alibaba: CA: 10024aa19b7b8d73f4b3b413f70bcf94806f9ca2: X509.sm2 806f9ca2 []069ced19 I--Q--- 1 perm 39010000 0 0 asymmetri IMA: X509.sm2 604c5d8c []... ...


IMA签名

接下来给系统中需要IMA验证的文件加上SM3的签名,这里简单粗暴的给常用目录下文件全部签名,如果文件比较多的话,这个过程会持续几分钟。


# 使用SM3哈希算法,private.pem是签名用的私钥,给系统主要目录下所有文件做IMA签名# 注意,private.pem要用绝对路径,否则会提示 Failed to open keyfile: private.pemevmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f \ /bin /sbin /usr /lib /lib64 /etc /home
# 通过getfattr可以查看添加到文件扩展属性中的签名数据(不是必需)getfattr -n security.ima /path/to/file


导入IMA策略

IMA策略是使能IMA的必备步骤,策略的内容可以根据实际需要进行定制。为了方便说明问题,这里以用户imatest来测试,在下面的规则示例中,当以imatest身份运行可执行程序和共享库时,会进行IMA度量以及apprase检查。


# 创建用户imatestuseradd imatest
# 用户ID可以从/etc/passwd中看到,这里是1000,用户ID会在IMA规则中用到# tail /etc/passwd# imatest:x:1000:1000::/home/imatest:/bin/bash


将下面的文件内容另存为ima.policy文件:


appraise appraise_type=imasig uid=1000 func=BPRM_CHECKmeasure uid=1000 func=BPRM_CHECKappraise appraise_type=imasig uid=1000 func=MMAP_CHECKmeasure uid=1000 func=MMAP_CHECK


上面的规则表示:


  • 度量以uid=1000身份运行的程序和共享库,并将度量值记录在/sys/kernel/security/ima/ascii_runtime_measurements文件中。

  • 评估以uid=1000身份运行的程序和共享库,如果程序的完整性被破坏,程序将被拒绝运行。


然后写入IMA规则到内核:

cat ima.policy > /sys/kernel/security/ima/policy


IMA验证


IMA策略写入内核后,IMA特性就已经在内核生效了,此时可以以imatest用户身份执行一些操作


su imatest
... ...


通过ascii_runtime_measurements我们可以看到IMA运行时度量的信息,这些都是通过IMA验证的文件,以下是部分度量日志:


# cat /sys/kernel/security/ima/ascii_runtime_measurements10 bcb0e518b79de0d7f2cd20b8a29a7092e65db7ef ima-sig sha1:0000000000000000000000000000000000000000 boot_aggregate10 d20bcf8ea6f3f8c03dd475766dfe18ccc14d264b ima-sig sm3:66acf6555ad2f6e5b89e1a80644eae4fd0015e5b811be63d1a58415e2f4f2b0e /usr/bin/bash 030211604c5d8c00473045022100ce91713b9aa37a2f8ce16f95acc00a7f072d7d3cc90ad8fae916ffc6072b10f402410 b829e4761f7a717dde6daab8089c8bac15fbb139 ima-sig sm3:1bcd4a4cb2a2c4418aa7075f5c012de03a383f3af172579132e5ad21bd5752c5 /usr/lib64/ld-2.17.so 030211604c5d8c0046304402203db3c575be22d35abe49d6e9f7fde0be22be02fdd9211feebf7ae172b8c6610 be220df2bc614980a06eff27f7286305c7afbdc2 ima-sig sm3:66acf6555ad2f6e5b89e1a80644eae4fd0015e5b811be63d1a58415e2f4f2b0e /usr/bin/bash 030211604c5d8c00473045022100e66e7f2d356668c1779cfbe05838979c789d9f81c8b5cd0e19022b8255ea13f102410 d262c29452b0d575a81786c49453fe6f14c0969d ima-sig sm3:1bcd4a4cb2a2c4418aa7075f5c012de03a383f3af172579132e5ad21bd5752c5 /usr/lib64/ld-2.17.so 030211604c5d8c004730450220432ee49d0fe84c36633365afdd1fc138316e5ea2cb854c5dc5b0c9d03619f10 26bf0fc75828783a0013b9f52045c9a56e8b4853 ima-sig sm3:18781f4c910453fdbcb36a359092128df86a660e230db4bb52765e32e209cf94 /usr/lib64/libtinfo.so.5.9 030211604c5d8c00473045022100fb46c2b15aef6f1005fea3f96d23d95a2d036d5da761d593b7689110 28ee84f368f892180efaefb3d9b68c90ded73268 ima-sig sm3:1c568b3aa88a2bafe543d4aa1db95c12e7e062f54de5c55c50729fa3ac786ab2 /usr/lib64/libdl-2.17.so 030211604c5d8c00483046022100930e63c0325013bfdbdbe098bc13ac514703af2ff7998fe44767591010 88120ffffa110b3621947f937117739f46cc8a46 ima-sig sm3:a53099f1946d13df1cf2561be1989cafbf4f1e4908294b315f80b8b07936c6d8 /usr/lib64/libc-2.17.so 030211604c5d8c00473045022010f571c748201ddc229f5b9cbbc4d471fb892b98653f8f73dc614eacfa210 1c83184c6b11f31ca8f1090aafc4ee5be8e336b0 ima-sig sm3:a591bc1f9eb1d1b89f0a1a83f6236302132a973515edebec1664499e32e42f12 /usr/lib64/libnss_files-2.17.so 030211604c5d8c00483046022100b51c03e638f2d71f6a4368592d8e055c231441962b1fb0989... ...


注意其中第一条日志,boot_aggregate是系统启动阶段TPM PCR的汇聚值,这个值是汇聚TPM设备对应PCR bank的值做一个digest,所使用的摘要算法是根据TPM设备版本以及支持的PCR bank决定,默认是SHA1,当然这个摘要也可以通过配置成默认优先SM3,这个也是我们将来要做的工作,例子中没有TPM设备,所以这里值是0。


接下来,我们再构造一个没有经过签名的可执行文件并执行:


su imatestcd ~
echo 'int main(){}' > dummy.cgcc -o dummy dummy.c


运行dummy可执行文件,提示没有权限,通过dmesg查看审计日志,也会看到文件没有签名的信息,这是符合预期的,同样,如果文件的签名是错误的,没有通过签名验证,也是会被拒绝执行的。


# ./dummybash: ./dummy: Permission denied
# dmesgaudit: type=1800 audit(1611820344.972:10): pid=1785 uid=1000 auid=0 ses=1 op=appraise_data cause=IMA-signature-required comm="bash" name="/home/imatest/dummy" dev="sda1" ino=263026 res=0


未来展望


当下的国密标准或多或少已经在基础软件库中有了支持,虽然一些基础的安全能力也可以在国密算法的基础上建立起来,但是还有部分空白领域仍然需要持续的开拓,以应对我国信息安全行业的安全可信。


  • 持续推进国密标准的国际化,在TLS通信中支持使用国密算法套件

  • 支持从启动,内核到上层应用的可信链完全建立在国密之上

  • 在更多基础软件工具中支持使用国密标准




往期精彩回顾

1、入选高性能计算著名顶会SC20长论文!详解阿里“Alita”

2、阿里云官方推出操作系统“等保合规”镜像 -- Alibaba Cloud Linux 等保2.0三级版

3、你认为 io_uring 只适用于存储 IO?大错特错!

4、面对疾风吧!io_uring 优化 nginx 实战演练



欢迎钉钉扫码入群交流:



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存