clang-tidy 中新增的代码检查规则可以检测到(一些)特洛伊木马源代码
特洛伊木马源代码
原始的 特洛伊木马源代码论文 包含了一系列攻击,这些攻击利用 Unicode 属性使代码看起来与编译器处理的方式不同。例如,以下代码摘自论文
#include <stdio.h>
#include <stdbool.h>
int main() {
bool isAdmin = false;
/* } if (isAdmin) begin admins only */
printf("You are an admin.\n");
/* end admins only { */
return 0;
}
看起来对 isAdmin
进行了保护,而实际上编译器读取的字节流如下
/* <U+0x202E> } <U+0x2066> if (isAdmin) <U+0x2069> <U+0x2066> begin admins only */
这个问题在正式发布之前提交给了 LLVM 安全小组,虽然我们一致认为这更多是一个显示问题,而不是一个实际的编译器相关问题,但我们也一致认为,为论文中描述的每个缺陷添加一个 clang-tidy
检查并不会造成任何损害。
使用 clang-tidy
名为 clang-tidy
的工具可以在代码库上运行一系列额外的代码检查规则,以检测编码规范问题、API 误用、安全漏洞等。我们添加了三个新的检查规则
检测误导性的双向字符
新的检查规则 misc-misleading-bidirectional
解析代码库中的每个注释和字符串文字,并查找未结束的双向序列,即越过注释或字符串文字结尾的序列,导致正常的代码从右到左显示,而不是通常的从左到右显示。在上面的例子中,我们会得到一个接近以下内容的警告
5:3: warning: comment contains misleading bidirectional Unicode characters [misc-misleading-bidirectional]
检测误导性的标识符
C++ 允许在标识符中使用一些 Unicode 代码点,包括具有强右到左方向的标识符,这会导致误导性的语句。例如,在以下代码中,
int א = ג;
我们是在给 א
赋值,还是给 ג
赋值?实际上我们是在给后者赋值,这很令人困惑。misc-misleading-identifier
代码检查规则检测到这种配置并输出类似以下内容的警告
10:3: warning: identifier has right-to-left codepoints [misc-misleading-identifier]
检测令人困惑的标识符
谁没有收到过使用看起来像 ASCII 字符的 Unicode 字符来绕过假设的反垃圾邮件扫描的垃圾邮件?C 类语言并没有摆脱这种趋势,而且在程序的某个地方定义
int foo;
,而在另一个地方定义
int 𝐟oo;
,这是完全有效的,也是令人困惑的。misc-homoglyph
检查规则根据 Unicode 联盟维护的 confusables.txt 列表检测这种易混淆的标识符(也称为同形异义词)。在上面的例子中,你会得到一个类似以下内容的警告
7:5: warning: 𝐟oo is confusable with foo [misc-homoglyph]
总结
如本文所述,我们选择将特洛伊木马源代码防御措施实现为多个 clang-tidy
检查规则。这样做而不是将它们实现为 Clang 警告,是在解析时间上的权衡。
感兴趣的读者可以在 这篇专门的博客文章 中了解 GCC 的替代方法!