Xcheck之C/C++安全检查引擎
2021-10-22 15:54:12 Author: mp.weixin.qq.com(查看原文) 阅读量:1 收藏

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>
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<inta (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>
TCSingleton<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++ 引擎还在持续迭代中,后续会逐步支持更多主流框架和漏洞,同时也会尝试对开源项目进行静态代码分析,敬请期待。


文章来源: https://mp.weixin.qq.com/s?__biz=Mzg2ODQ3ODE1NA==&mid=2247485861&idx=1&sn=66de2ef0b3a0b7ab3f88a9db4425fb03&chksm=ceaaf400f9dd7d16585bcdc0a0906601c6708fb9cabca687eb29c5bdc68ad7e0d433f97c4ad7&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh