敏感数据在使用后应被有效清理
1.3 ID_unsafeCleanup
及时清理不再使用的敏感数据是重要的安全措施,且应保证清理过程不会因为编译器的优化而失效。
程序会反复利用内存,敏感数据可能会残留在未初始化的对象或对象之间的填充数据中,如果被存储到磁盘或传输到网络就会造成敏感信息的泄露,可参见 ID_secretLeak 和 ID_ignorePaddingData 的进一步讨论。
示例:
void foo() {
char password[8] = {};
....
memset(password, 0, sizeof(password)); // Non-compliant
}
示例代码调用 memset 覆盖敏感数据以达到清理目的,然而保存敏感信息的 password 为局部数组且 memset 之后没有再被引用,根据相关标准,编译器可将 memset 过程去掉,使敏感数据没有得到有效清理。C11 提供了 memset_s 函数以避免这种问题,某些平台和库也提供了相关支持,如 SecureZeroMemory、explicit_bzero、OPENSSL_cleanse 等不会被优化掉的函数。
在 C++ 代码中,可使用 volatile 关键字限定相关对象以避免编译器的优化,再使用 std::fill_n 等方法清理,如:
void foo() {
char password[8] = {};
....
volatile char* v_address = password;
std::fill_n(v_address, sizeof(password), '\0'); // Compliant
}
例中 v_address 指向的对象由 volatile 关键字限定,对 *v_address 的读写不会被优化。
相关
依据
ISO/IEC 9899:1999 5.1.2.3(3)
ISO/IEC 9899:2011 5.1.2.3(4)
ISO/IEC 9899:2011 K.3.7.4.1