G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

admin 2025年4月10日21:12:25评论4 views字数 2852阅读9分30秒阅读模式

开源安全基金会(OpenSSF)成立于2020年8月3日,是开源社区中专门关注软件代码和系统安全的组织。今天我们要介绍的文章 Compiler Options Hardening Guide for C and C++ 就来自OpenSSF,详细介绍了在编译C和C++代码的过程中,通过编译器选项的特定设定带来的安全加固优势:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

在日常开发过程中,很多人可能都知道,为了保证代码的质量,在编译的过程中可以考虑使用-Wall选项,让编译器尽可能告警,然后消除可能的不安全代码风格。但是除了-Wall选项,你还知道多少其他的可以使用的选项呢?

在这篇技术博客的第三章,详细介绍了两大类安全加固的编译选项。第一类安全加固编译选项是编译期安全检查,主要是在编译过程中开展各种严格的静态分析检查,让潜在的问题代码在编译期就直接被检测出来;第二类安全加固编译选项是运行时安全检查,主要是让编译器给binary code加入更多的运行期检查插桩代码。接下来我们逐一看看各个具体的选项(注意,这里面只涉及到GCC编译器的选项,以及LLVM为了兼容GCC基本上也包括了同类的选项;M$家的VC编译器的选项目前还没包含进来)。

首先是最标准的两个参数-Wall-Wextra,这个基本上严格一点的开发团队都会要求:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

其次是-Wformat选项,主要是为了检查printfscanf的格式化参数是否存在类型误用。注意还有一个-Wformat=2选项,能够检查更多的printfscanf格式化参数问题,可以参考原文。

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

接下来是-Wconversion-Wsign-conversion选项,顾名思义是对数值类型转换的严格检查:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

大家对-Wtrampolines这个选项是否有点眼熟?可以去看看我们去年的文章《G.O.S.S.I.P 阅读推荐 2024-10-24 To Write & To Execute》了解具体细节:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

对于switch结构中某些case中(可能无意)缺少break的检查,可以用-Wimplicit-fallthrough这个选项来进行严格的检查:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

针对最近几年出现的Trojan source code,最新的编译器(可以从下图中看到,GCC从12.0以后才开始支持)对一些人类可能会误读(例如从右往左字符集合)的代码可以开启-Wbidi-chars=检查(默认不允许这些情况):

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

接下来,有一系列-Werror=的检查选项,会把一些默认作为warning的代码问题都视为代码错误(并且阻止编译器生成binary),例如下面的代码写法就不能通过编译:

printf(fmt);
printf(gettext("Hello Worldn"));
fprintf(stderr, fmt);
G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道
G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道
G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

上面介绍的都是静态编译期的检查,接下来的是选项是对生成的二进制代码加入安全检查插桩代码的选项:

首先是FORTIFY_SOURCE选项,这个选项能够对GNU C library(就是我们常说的glibc)加入针对缓冲区溢出攻击的运行时检查,主要针对如下这些函数:

memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, strcat, strncat, sprintf, vsprintf, snprintf, vsnprintf, gets

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

接下来是-D_GLIBCXX_ASSERTIONS选项,这个主要是针对C标准库(libstdc)中的容器和字符串的越界等问题的动态检查:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

下面这个-fstrict-flex-arrays选项大家可能有点陌生,加入编译器的时间也比较晚,不过下面的代码例子大家可能知道,就是在C语言的结构体里面,如果一个数组放在最后(叫做trailing arrays),那么编译器是不会管它声明时候定义的size,而是允许在运行时才初始化这个指针(也就是说这个数组的长度范围不确定),这样虽然有历史原因,但是开发者可以要求编译器严格执行声明,杜绝对这种灵活性。

structtrailing_array {
int a;
int b;
int c[4];
};
structtrailing_array *trailing;
G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

-fstack-clash-protection-param stack-clash-protection-guard-size这两个选项,主要是针对所谓的“stack clash”问题的防护。Stack clash问题是一种奇怪的stack越界,它并不是说函数对于局部变量的越界读写,而是指整个stack在不断增长的过程中,入侵到了某个其他内存区域,然后攻击者可以藉由栈指针来访问某些并不是stack的内存区域:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

而针对stack overflow的检查,当然有专门的参数-fstack-protector-*来对应:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

对应我们大家都很关心的控制流劫持问题,现代编译器提供了一系列的-fcf-protection予以回应:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

在移动平台上,对于运行时代码加载有比较严格的限制,而在桌面平台这方面的限制好像没那么严格,不过现在可以使用-Wl,-z,nodlopen选项来对dlopen进行一定的限制:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

下面这个-Wl,-z,noexecstack选项好像有点啰嗦,目前应该所有的操作系统都默认执行了stack的可写不可执行策略了吧?

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

然后是一些对relocation table的防护,不给一些针对此类table改写攻击可乘之机:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

对于PIE和PIC代码生成的选项,好像又是有点啰嗦,2025年应该新代码都是按照这些选项编译了吧?

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

这个-fno-delete-null-pointer-checks看起来非常简单:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

对于算术运算中的有符号数的overflow,有一系列选项可以开启运行时检查:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

-fno-strict-aliasing是一个很有意思的选项,在很早期版本的GCC就支持了,但是LLVM/Clang直到18.0之后才开始支持。不过这里其实似乎是放松了对安全的检查?

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

-ftrivial-auto-var-init这个选项很好理解:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

-fexceptions是一个非常古老的选项了,主要是对多线程代码的安全加固:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

-fhardened-Whardened是将一些预设的安全加固规则的整体应用:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

最后是一系列链接器的安全加固选项:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

文章的第五章是对于sanitizer的参数建议:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

而第七章和第八章很有趣,是假定你在编译一个编译器/链接器时应该遵循的选项:

G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道
G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

总之,对于编译器的使用绝对是一门手艺,大家平时如果只会用IDE去编译,可能就会越来越难以理解底层的知识,随着人工智能时代的来临,多学一点冷门的底层细节永远不会有错!

原文:https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html

原文始发于微信公众号(安全研究GoSSIP):G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月10日21:12:25
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   G.O.S.S.I.P 阅读推荐 2025-04-09 编译器的安全之道https://cn-sec.com/archives/3936510.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息