概述

剑桥大学的研究人员在11月1日公开了一个影响大多数编译器和软件开发环境的漏洞,并命名为Trojan Source。该漏洞存在于Unicode中,有两种利用方法:第一种是使用Unicode的Bidi算法(CVE-2021-42574),对字符进行视觉上的重新排序,使其呈现与编译器和解释器所不同的逻辑顺序;第二种是同形文字攻击(CVE-2021-42694),也就是利用在视觉上看起来相似的不同字符。该漏洞适用于C、C++、C#、JavaScript、Java等广泛使用的编程语言,可以用于供应链攻击。

本文描述的攻击技术正是来自剑桥大学的Nicholas Boucher和Ross Anderson研究人员发现的被称为 Trojan-Source 的其中一种攻击方法:利用不同字符编码中的细微差别,构造出常人难以察觉的恶意隐藏代码,即将恶意构造的代码伪造为注释或是其他信息隐藏于正常代码中。其具体体现在代码执行时会扰乱原有代码执行逻辑或是篡改正常函数为恶意函数。

此外,通过这种方式还可以实现对真实文件类型的隐藏,达到伪装为其他文件诱使受害者操作的目的。奇安信威胁情报中心红雨滴团队对该论文进行了分析与解读。

引用论文地址:https://trojansource.codes/trojan-source.pdf

Trojan Source的攻击方法

该方法可以让攻击者更隐蔽的将恶意代码注入到软件项目中,让使用者在使用到该有问题的项目代码时不容易发现藏在其中的恶意代码,攻击者可以将项目上传到各个平台的代码管理网站中,比如:Github,gitee,GitLab,Coding,BitBuck等等网站上,从而导致其他需要该项目的人员下载对方的代码并进行编译。

由于编译后的代码文件逻辑因为 Trojan-Source 的攻击方法从而发生改变,导致运行后很有可能发生本身电脑中毒,以及盗取本机信息这类的攻击事件。

Trojan Source 依赖一个简单的技巧,他不需要修改编译器来创建攻击的二进制文件。该方法适用于当今一些最广泛使用的编程语言,攻击者可以将其用于供应链攻击。

编译器安全中的文本编码简介

一个编译器将高级语言转化的编译过程可以分为,扫描(scanner),语法分析(Parser),语义分析(Semantic Analyzer),源代码优化(Source Code Optimizer),代码生成(Code Generator)和目标代码优化(Code Optimizer)。

总的来说编译器会将我们的高级语言翻译成特定体系结构的机器语言,或者是可移植性的字节。

编译器输出的逻辑大多都源于编译器优化后的结果,但是这些优化的结果很有可能导致具有安全隐患的副作用。Unicode规范中有如下表所示的一些方向指示字符,一旦使用了这些方向转换字符,文字方向就会改变。

字符重新排序方式

Unicode标准规定,内存表示顺序称为逻辑顺序,当文本在一行的时候,大多数脚本从左往右显示字符。然而,也有一些脚本(如阿拉伯语或希伯来语)显示文本的自然顺序是从右往左。如果所有文本为统一的方向,那么显示的文本顺序则是明确的顺序。但是如果方向不一致,那么显示的顺序也会发生歧义。

所以规定了每个字符都有一个隐式双向类型。从左到右和从右到左的双向类型称为强类型,具有这些类型的字符被称为强方向字符。与数字相关的双向类型被称为弱类型,具有这些类型的字符被称为弱方向字符。除了方向格式码,剩下的双向类型和字符被称为中性。

因为在某些场景中,有的语言是从右往左的,有的是从左往右的,然后实现了一个双向的算法Bidirectional algorithm,又叫bidi,标准bidi算法提供的显示顺序还不够,所以对于这些情况,提供了覆盖控制字符。Bidi算法覆盖是不可见的字符,从而可以切换字符组的显示顺序。

假设Unicode 字符为:RLI 1 2 3 PDI

那么将显示为:3 2 1

隔离重新排序方式

在Bidi规范中,隔离是将一组字符当作了一个实体,当显示顺序被重写时,整个一组字符将作为单个块移动,隔离可以嵌套。

假设Unicode 字符为:RLI LRI 4 5 6 PDI LRI 1 2 3 PDI PDI

那么将显示为:1 2 3 4 5 6

相互多次的嵌套RLI,LRI,就可以实现块的嵌套,以及单个字符的嵌套,那么攻击者就可以将杂乱的字符,经过这种方式,来将自己想要的功能插入到当前的开源的项目中,来让下载后的执行,从而在不知情的情况下来执行shellcode。

Trojan Source在编译器中利用

因为大多数设计比较好的编程语言,以及编译器,都不允许我们在源代码中来使用任意控制字符,因为如果使用了任意控制字符后,会被当作影响逻辑的控制字符,所以在源代码中来使用Bidi从而覆盖字符篡改,会导致编译器解析语法错误,所以在利用的方式中,可以使用注释或者字符串。

• 注释:很多的编程语言允许注释中出现所有的文本字符,因为在预编译时,编译器会实现忽略的规则,所以在注释中出现任意控制字符,会被编译器和解析器忽略。

• 字符串:很多的编程语也允许字符串可以包含任意字符,同理也包括任意控制字符。

注释和字符串都有特定于语法的语义,从而来表示它们的开始和结束,但是任意控制字符并不遵守这些规则,因此,通过将任意控制字符专门放在注释和字符串中,从而可以瞒住大多数编译器,让编译器以接受的方式将它们偷偷放入源代码中。

比如作者论文中提到的C语言:通过任意控制字符 来改变了代码逻辑,这个代码中的if条件根本没有执行,而是被放置在注释部分,只是因为显示效果才起到了对人的欺骗作用。

作者对编辑器,包括GitHub和BitBucket在线代码显示功能)进行了测试,发现攻击者的攻击代码在这些编辑器上显示出来的效果都能起到同样的欺骗作用,作者也在github提供了概念验证 (PoC) 脚本,用于演示 Trojan Source 攻击的威胁程度:https://github.com/nickboucher/trojan-source

总结

Trojan Source可能是一种新型的供应链攻击方法:其可以被利用于将恶意代码注入开源软件项目中,且在源代码层面很难察觉。如果相关软件项目使用了被感染的开源代码,则使用该软件的所有用户都可能成为攻击者直接攻击的目标。

参考链接

https://trojansource.codes/trojan-source.pdf

http://www.unicode.org/reports/tr9/

https://github.com/nickboucher/trojan-source

声明:本文来自奇安信威胁情报中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。