徽州骆驼 · 2023年03月13日

谈谈QNX安全之软件编译安全

以下文章来源于汽车信息安全 ,作者theoneandone

image.png
QNX作为微内核系统,被广泛的应用在车载娱乐系统、Tbox和智驾系统中。相对于Unix这类宏内核系统,QNX的微内核结构只有几十KB,因此启动速度非常快,稳定性也非常高。那么QNX有哪些安全机制可以使用呢?

     笔者在此推出QNX安全系列,给大家介绍下QNX的安全防护技术,本篇是QNX安全系列的第一篇,我们重点讲述软件编译保护机制。在进入正文之前,笔者还是给大家简单介绍下QNX与Linux的区别。

1. QNX与Linux的区别

如图1、2所示,QNX之所以那么小,是因为作为微内核,它将驱动、系统服务、应用、协议栈、文件系统等都剔除在内核外,以可加载模块的形式运行,QNX内核只完成最基础的服务,如时钟同步、进程间通信、进程调度等。Linux作为宏内核,包含了许多服务,如文件系统、网络、驱动程序等。

image.png

2. 软件编译保护

Qnx为我们提供了很多安全编译选项,这些选项有的可以帮我们在开发时定位问题,编译出更健壮的代码,有的可以帮助我们对软件进行保护。典型的有下面几个编译选型:

  • 编译时警告选项

检测到易受攻击的代码时输出警告。有问题的代码容易崩溃、产生错误或意外行为,或为攻击创造机会,在开发阶段如果能充分识别并处理这些信息,能显著提高我们的代码健壮性,典型的编译如表1所示。

表1 QNX警告编译选项

image.png

  • 地址无关代码

对可执行文件、库文件编译时开启下面的编译选型,并启用ASLR。启用该选项后系统对可执行文件、库文件装载时地址空间布局会随机化。一般而言,QNX会默认开启-fPIC、-fPIE和ASLR。

表2 地址无关代码编译选项

image.png

在这里简单介绍下ASLR。ASLR,即地址空间布局随机化(Address Space Layout Randomization),如图3所示,每次加载可执行文件时,地址空间布局随机化会改变数据和指令的位置。要支持 ASLR,二进制文件必须编译为与位置无关,因此需要使用 -fPIC编译库,使用-fPIE编译二进制文件。

image.png

图3 地址随机化效果

地址空间布局随机化针对以下系统元素实施:

Ø可执行代码——由动态加载器加载的标记为可执行的程序段。应用程序必须使用 PIE 编译。

Ø堆栈——页面和页面内的偏移量都是随机的。

Ø——页面是随机的。

Ø共享内存——多个进程之间共享的内存映射到每个进程中不同的随机虚拟地址。

Ølibc 和动态加载器——libc 的位置和动态加载器的位置在进程的虚拟地址空间中都是随机的。虽然 libc 和动态加载器等共享对象映射到随机地址,但如果加载顺序保持不变,则它们相对于彼此映射到相同地址。

Ø命令行参数——命令行参数在进程的虚拟地址空间中的位置是随机的。

  • 堆栈保护

编译时针对应用程序、共享库使用,在函数返回之前检查堆栈canary以确保它们没有被修改(例如,由于堆栈分配的变量上的缓冲区溢出)。对堆栈上的堆栈canary的任何修改都将导致进程中止。可用的编译选项如表3所示。

表3 堆栈保护编译选项

image.png
默认,在 -fstack-protector 和 -fstack-protector-all 之间进行平衡,此option的目的是通过扩大堆栈保护范围而不将其扩展到程序中的每个函数来获得性能,同时牺牲很少的安全性。

  • 阻止未定义符号

编译时防止目标文件中有未定义符号,通过指定-Wl,-z,defs选项,这也是减少攻击面的措施之一。当然也可以不指定,未定义符号在进行代码审计后也基本能识别出。

表4 阻止未定义符号编译选项

image.png

  • GOT表保护

编译时对可执行指定表5中编译选项,可利用RELRO技术,在动态加载程序完成加载和链接可执行文件后,编译器可以将可执行文件的重定位部分标记为只读。 如果出现 .bss 或数据溢出错误,RELRO(只读重定位)保护 ELF 二进制文件中的全局偏移表 (GOT) 不被覆盖。

表5 GOT表保护编译选项

image.png

  • 检查未定义行为

编译时启用sanitizer编译代码,从而增加在代码中发现错误的可能性。目前,QNX Neutrino 支持 Undefined Behavior Sanitizer (UBSAN)。

表6 检查未定义行为选项

image.png

在此强调一下,

3.查看编译时保护选项

上面介绍了那么多编译选项,特别是对于堆栈保护、GOT表保护、地址无关代码,我们如何识别运行的应用程序或库文件已经开启了对应的编译呢?笔者在此推荐两种方法:

  • 通过readelf读取

readelf是一个可用于检查ELF(Executable and Linkable Format)文件的工具,该文件格式是Linux和QNX等操作系统上可执行文件和共享库的标准格式之一。

image.png

  • 通过qchecksec读取

类似于Linux中的checksec,qchecksec是一个用于检查二进制文件的安全性选项的工具。可以从github上的qchecksec存储库下载qchecksec源代码,然后使用GNU Autotools进行编译和安装。一旦安装完成,可以使用qchecksec命令来检查二进制文件的安全性选项。例如,要检查名为test的二进制文件的选项,可以运行以下命令:

qchecksec test

这将输出有关二进制文件的各种安全选项的信息。例如,以下是一些可能的输出:

RELRO STACK  CANARY  NX  PIE  RPATH    RUNPATH  FORTIFY  Fortified

Full No   NX enabled    PIE enabled    No         No        Yes     2

输出中的每一列都对应于一种安全选项,其中:

·RELRO:表示RELRO保护的级别。

·STACK CANARY:表示堆栈保护是否已启用。

·NX:表示内存不可执行是否已启用。

·PIE:表示位置无关执行是否已启用。

·RPATH:表示是否设置了RPATH。

·RUNPATH:表示是否设置了RUNPATH。

·FORTIFY:表示是否启用了FORTIFY Source。

输出中的最后一列"FORTIFIED"表示是否已应用FORTIFY_SOURCE保护。如果数字大于0,则该文件已使用FORTIFY_SOURCE进行了保护,并且数字表示保护级别。

小结

这些编译器选项并不意味着在量产二进制文件中启用。 每个选项都针对代码的不同方面。 要充分利用这些选项的功能,请确保检测代码像在量产环境一样被执行。

作者:theoneandone
文章来源:汽车信息安全

推荐阅读

更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
5613
内容数
329
汽车电子与软件行业的相关技术报道及解读。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息