
控制流完整性(CFI)是一种类似于栈保护(DEP)、数据执行保护(ASLR)的漏洞缓解技术。CFI的目标是防止程序漏洞被转化为可利用的安全问题。当程序存在缓冲区溢出、类型混淆或整数溢出等漏洞时,攻击者可能改变程序执行流程。CFI通过在运行时强制执行编译器在编译时确定的控制流图(CFG)来阻止这类攻击。
从图论角度理解,程序的控制流可以表示为有向图(CFG),其中节点是基本块,边是可能的控制流转移。CFI确保运行时遵循编译时确定的CFG。
Clang从3.7版本开始在主分支支持CFI,作为消毒剂套件的一部分。要启用CFI需要:
-flto-fvisibility=hidden和-fsanitize=cfi编译标志完整构建命令示例:
# 调试版本
clang-3.9 -fvisibility=hidden -flto -fno-sanitize-trap=all -fsanitize=cfi -o output input
# 发布版本
clang-3.9 -fvisibility=hidden -flto -fsanitize=cfi -o output input保护间接函数调用:
示例攻击场景:
// 攻击者将write()调用改为system()
typedef int (*func_ptr)(int);
func_ptr fp = (func_ptr)system;
fp(123); // CFI会阻止此非法调用限制:
保护虚函数调用:
示例攻击场景:
class Base { virtual void print(); };
class Evil { void makeAdmin(); };
Base* obj = new Evil();
obj->print(); // CFI会检测到类型混淆保护非虚成员函数调用:
示例攻击场景:
class Admin { void doAdminWork(); };
class User {};
User* user = new User();
((Admin*)user)->doAdminWork(); // CFI阻止权限提升防止不相关类型转换:
防止非法基类到派生类转换:
class Base {};
class Derived { int secret; };
Base* base = new Base();
Derived* derived = (Derived*)base; // CFI阻止内存泄露加强版派生类转换保护,针对特定边缘情况:
CFI是重要的漏洞缓解技术,能有效防止控制流劫持攻击。Clang提供了完整的CFI实现,通过7种不同的保护选项覆盖了各种攻击场景。虽然存在一些限制(如需要全程序LTO、特定架构支持等),但在支持的环境中使用CFI能显著提高软件安全性。
实际测试表明,CFI能有效阻止示例中的所有攻击场景,包括:
建议所有安全关键项目启用CFI保护,只需添加简单的编译标志即可获得强大的运行时保护。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。