1、被污染的格式化字符串
格式化字符串函数可以接受可变数量的参数,函数的调用者可以自由的指定函数参数的数量和类型。常见的格式化字符串函数有: scanf、 printf、 fprintf、 vprintf、 vfprintf、 sprintf、 snprintf、 vsprintf、 vsnprintf 等等。当程序使用了格式化字符串作为参数,且该格式化字符串来自外部输入时,如果没有外部输入进行有效过滤,就有可能触发格式化字符串漏洞,本篇文章分析被污染的格式化字符串产生的原因及修复方法。详细请参见:CWE-134: Use of Externally-Controlled Format String。
2、 被污染的格式化字符串
直接将被污染的数据作为格式化字符串进行操作,由于污染数据内容的不确定性,可能导致格式化匹配混乱、解析错误甚至系统运行崩溃或者执行恶意代码。如在使用 printf() 函数时:
scanf("%s",str);printf(str);
这段代码的目的是输出字符串,但是由于这段字符串来源于被污染的数据,且直接使用了printf(str) 这种形式,就可能会把栈上的偏移当做数据输出。通过构造格式化字符串的方法,就可以实现任意地址的读或者写。
CVE中也有一些与之相关的漏洞信息,从2018年1月至2019年3月,CVE中就有11条相关漏洞信息。漏洞信息如下:
CVE | 概述 |
---|---|
CVE-2018-6875 | KEY HODLERS KeepKey4.0.0 版本中存在格式化字符串漏洞。攻击者可利用该漏洞访问无权访问的信息。 |
CVE-2018-6317 | ClaymoreDualMiner 是一款用于挖矿(虚拟货币计算)的 GPU 监控软件。ClaymoreDualMiner10.5 及之前版本中的远程管理界面存在未授权的格式化字符串漏洞。远程攻击者可利用该漏洞读取内存或造成拒绝服务。 |
CVE-2018-17336 | udisks(前称DeviceKit-disks)是一个Linux系统上的系统服务,它主要用于列举出设备并提供设备相关的信息。 udisks2.8.0 版本中的 udiskslogging.c 文件的‘udisks_log’函数存在格式化字符串漏洞。攻击者可借助畸形的文件系统标签利用该漏洞获取敏感信息(栈内容)并造成拒绝服务(内存损坏)。 |
CVE-2018-15749 | Pulse Secure Desktop 是美国 Pulse Secure 公司的一套用于访问 Juniper Pulse Secure 网关的终端设备的客户端软件。PulseSecure Desktop (macOS) 5.3R5 之前的 5.3RX 版本和9.0R1版本中存在格式化字符串漏洞。本地攻击者可利用该漏洞获取信息。 |
3、示例代码
示例源于Samate Juliet Test Suite for C/C++ v1.3 (https://samate.nist.gov/SARD/testsuite.php),源文件名:CWE134_Uncontrolled_Format_String__char_environment_fprintf_01.c。
3.1缺陷代码
在上述示例代码中,第42行使用 GETENV() 函数获取环境变量并使用 strncat() 函数读取环境变量信息至 data 中,在第51行使用 fprintf() 函数,没有明确指定格式说明符而直接使用了 data 数据,因此存在“被污染的格式化字符串”问题。
使用360代码卫士对上述示例代码进行检测,可以检出“被污染的格式化字符串”缺陷,显示等级为“高”。如图1所示:
图1:被污染的格式化字符串的检测示例
3.2 修复代码
在上述修复代码中,Samate 给出的修复方式为: 在第51行对 fprtinf() 函数的格式说明符进行了明确定义,从而避免了被污染的格式化字符串。
使用360代码卫士对修复后的代码进行检测,可以看到已不存在“被污染的格式化字符串”缺陷。如图2:
图2:修复后检测结果
4 、如何避免被污染的格式化字符串
(1)明确指定格式化说明符,避免来自被污染的数据作为格式化字符串。
(2)使用源代码静态分析工具,可以有效发现这类问题。