长亭百川云 - 文章详情

Xcheck之C/C++安全检查引擎

腾讯代码安全检查Xcheck

100

2024-07-13

0x00 C/C++安全检查引擎

Xcheck的 C/C++ 安全检查引擎,能够在不编译源码的情况下对 C 和 C++ 源代码进行安全检查,检测SQL注入、命令注入、SSRF、路径穿越、缓冲区溢出、格式化字符串漏洞等漏洞。

作为最古老的“现代”编程语言,C/C++ 的框架和库极为丰富,当前 Xcheck 优先支持了业界和公司内部的主流开发框架,如 gRPC-C++ 、tRPC-C++、SPP、Svrkit、TARS 等,同时,用户也可以编写自定义规则,快速适配自己的框架。

0x01 不编译代码进行安全检查

随着多年的社区发展,C 和 C++ 的版本多、语法杂,各项目使用的编译器、编译参数、编译环境配置等均不统一,导致大部分 C/C++ 源代码不能拿到就直接编译。

C/C++ 的各个版本

传统 SAST 工具针对 C/C++ 代码的安全检查,强依赖于编译的中间产物进行扫描,编译失败就无法正常执行,用户在使用时,需要配置 SAST 工具可用的编译脚本,或者将源代码改造为 SAST 工具可以直接编译的代码,增加了使用成本。

Xcheck 的 C/C++ 安全检查引擎,采用了自研的 Xparser 语法解析器,可以在 不编译代码 的情况下模糊解析出代码的语法信息,再结合 Xcheck 的语义分析算法和污点传播算法,高效快速地发现代码中的安全风险。

Xparser 支持在各类无法编译的场景模糊解析语法,最大程度保留语法信息,如:缺少相关头文件/库、编译时替换字符、特殊编译器语法等。

场景1:缺少相关头文件/库

include 的库不在代码中,会导致代码中存在未知的宏定义

TEST(xxx, xxx){}     // 单测代码,像 function 声明 for_each(a, b, c){}  // 封装了一层的 for 循环 __END_DECLS          // 未知语句块

也可能存在未知的类型

XXClass * a          // 未知类型,造成歧义,声明或者相乘

场景2:编译时替换字符

某些项目的代码会在编译时,编译脚本替换源代码中的关键字

namespace ${APP} {   // 编译时替换 ${APP} -> xxx_project ... } 

场景3:特殊编译器语法

一些编译器会有特殊的语法

int $a = 1;         // GNU C 支持标识符中包含 $

0x02 精准解析语法特性

和 Xcheck 的其他引擎一样,为了能够精准的发现安全漏洞,Xcheck 对 C/C++ 的各类语法特性都做了支持,包括:Template、流式操作、命名空间、指针等。

Template语法

Template(模板)是 C++ 中比较有代表性的语法之一,主要特点如下:

  • 语法复杂:包括函数模板的声明和调用、类模板的声明和调用,类外声明模板函数、模板类外定义模板函数,模板特化等

  • 编译器特殊处理:编译器在编译时,会根据传入参数的具体类型去实例化对应的函数/类

函数模板声明:

声明一个名为 Foo 的函数模板,函数中的 T 在这个时候是未知的

template <typename T> T foo(T b){  T a = b;  return a; }

函数模板调用:

调用 Foo,这里因为 Foo 是函数模板,会先用 a 的类型  int,去实例化一个真实的函数,然后调用

int a = 1; Foo(a);         // 实例化出 int Foo(int a){}

double b = 1.1; Foo(b);         // 实例化出 double Foo(double a){}

string c = “test”; Foo(b);         // 实例化出 string Foo(string a){}

类模板声明:

声明一个名为 Pair 的类模板,类中的 T 同样是未知的,类中有一个 value 属性和构造函数

template <class T> class Pair {  public:  T value;  Pair(T v): value(v) {  } }

类模板调用:

显示传入模板中需要的类型,这里传入了一个 int 类型,这时候会实例出一个真实的类,类中的 value 是 int 类型的,接着用这个类实例化一个对象,执行 Pair 的构造函数

Pair<int> a (1);

0x03 漏洞案例

以真实业务代码为例(已脱敏)

  1. 这是 SPP 框架的一个入口函数,其中 req 参数为外部传入的污点,经过参数提取和字符串拼接后,污点传递给 select_sql,然后作为参数传给 LogServicesInstance.exec_query

int GetXXMsg::execute(const DbProxy::CommonReq &req, DbProxy::CommonRsp &rsp) {     const DbProxy::GetXXReq &real_req = req.getservicelogtopic();     std::string select_sql = "SELECT xx FROM xxxxx "                              "WHERE uin=" + Util::toString((unsigned long)real_req.uin()) +                              " AND name= '" + real_req.name() + "'" +                              " AND tag = '" + SERVICE_LOG_TAG + "'";     std::vector<struct XXX> topic_rows;     int ret = LogServicesInstance.exec_query(select_sql, topic_rows,...);

  1. LogServicesInstance 实际上是一个宏

class LogServicesDb : public MysqlClient {}; #define LogServicesInstance   (CSingleton<LogServicesDb>::instance())

Xparser 在解析 C/C++ 源代码时会调用自研的预处理模块,将该代码宏展开为:

int ret = (CSingleton<LogServicesDb>::instance()).exec_query(select_sql, topic_rows,...)

  1. CSingleton 是一个单例模式的模板类,传入 LogServicesDb,再调用 instance 方法,就会返回 LogServicesDb 的一个实例

template<class T> class CSingleton {    public:       static T& instance(); }; template<class T> T& CSingleton<T>::instance(){    static T _instance;    return _instance;   }

  1. 在 2 中可以知道 LogServicesDb 实际上继承了 MysqlClient

class MysqlClient {     public:      ...         int exec_query(std::string& sql, ...);     private:      ...         xxxxx::MySQLPool _pool; }

具体的方法实现是在类外定义的

int MysqlClient::exec_query(std::string& sql, ...) {     if (interface <= 0)         return _pool.exec_query(sql, row_vec);     else     {         ...     } }

  1. 经过精准的语义分析和污点传播,Xcheck 检查到污点传入了 _pool.exec_query(sql, xx),而 _poolxxxxx::CSyncMySQLPool 的实例, Xcheck 已将该类的 exec_query 方法标记为漏洞函数,故此处触发 SQL 注入漏洞。

涉及到的语义:

  • 类声明/继承/实例化

  • 类模板声明/实例化

  • 函数调用

  • 赋值语句

  • 字符串拼接

  • ...

0x04 测试数据

Xcheck 在 8 月内部灰度上线了 C/C++ 检查引擎,同时也和多个安全团队联合进行了测试,相关数据如下:

灰度数据

项目数

34177

风险项目数

246

问题总数

2573

误报率

10%(抽检)

内部灰度测试漏洞类型分布

0x05 总结

Xcheck 的 C/C++ 引擎还在持续迭代中,后续会逐步支持更多主流框架和漏洞,同时也会尝试对开源项目进行静态代码分析,敬请期待。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2