0%

静态分析实验记录_record

CSA

Clang Static Analyzer(CSA) 是 Clang/LLVM 编译器框架中自带的静态分析器,主要基于符号执行(Symbolic Execution)计数,支持 C/C++/Object-C 等语言的编码规范和安全漏洞的检测。
CSA 支持包括 stack/heap overflow, uninitialize, format 等在内的各类静态漏洞检测,以不同 Checkers 的形式集成,并支持自定义扩展。

CodeChecker

CodeChecker 是一个著名的代码分析管理平台,集成了以 CSA 为主的各类分析器,也支持 Fuzzing Sanitizers、GCC编译器中的static analyzer等,CodeChecker是建立在 LLVM/Clang 静态分析器工具链上的静态分析基础设施,取代了 Linux 或 macOS(OS X)开发环境中的scan-build。

Main features

  • Command line C/C++ Analysis: 集成众多静态分析工具
  • Web-based report storage:
  • Command line features: CodeChecker 命令包含众多子命令可以用于打印日志和分析你的项目、打印结果或开启一个 web server,可使用 CodeChecker --help 进行查看

符号执行

参考:https://firmianay.gitbook.io/ctf-all-in-one/5_advanced/5.3_symbolic_execution
基本原理:

  • 符号执行起初应用于基于源代码的安全检测,它通过符号表达式来模拟程序的执行,将程序的输出表示成包含这些符号的逻辑或数学表达式,从而进行语义分析。
  • 符号执行可分为 过程内分析过程间分析(或 全局分析)。过程内分析是指只对单个函数的代码进行分析,过程间分析是指在当前函数入口点要考虑当前函数的调用信息和环境信息。
  • 符号执行优点是代价小、效率高,但缺点是存在路径状态空间的爆炸问题。
  • 动态符号执行 是指将符号执行和具体执行结合起来,并交替使用静态分析和动态分析,在具体执行的同时对执行到的指令进行符号化执行。

Usage flow

  1. CodeChecker log 运行给定的构建命令并记录执行的编译步骤,这些步骤会被以 JSON 格式写入一个输出文件(编译数据库)。
  2. CodeChecker analyze 使用先前创建的JSON格式的编译数据库对项目进行一次分析,以机器可读的格式(plist)输出分析结果。
  3. 在这一步,你可以做多种事情:
    • 解析并漂亮地打印来自分析结果文件的摘要和结果(CodeChecker parse)。
    • 将结果存储到正在运行的CodeChecker服务器(CodeChecker存储)。
    • 比较两个分析结果/运行,以显示两者之间的不同结果(CodeChecker cmd diff)。

实验

实验环境

实验过程

本次实验是对 Openssl 库文件的编译过程进行静态分析,实验步骤:

执行CodeChecker check -b 'make CC="$CC -g -fsanitize=address,fuzzer-no-link"' -o ./results_openssl命令对make CC="$CC -g -fsanitize=address,fuzzer-no-link"Openssl 库文件编译过程进行静态分析,相当于先后执行了 2 条命令:

  • CodeChecker log --build "make CC="$CC -g -fsanitize=address,fuzzer-no-link"" --output ./compile_commands.json: 记录编译过程中执行的编译步骤,这些步骤会被以 JSON 格式写入一个输出文件(编译数据库)
  • CodeChecker analyze ./compile_commands.json --output ./results_openssl: 先前创建的JSON格式的编译数据库对项目进行一次分析,以机器可读的格式输出分析结果到 result_openssl 目录中

开始静态分析:

执行 CodeChecker server &: 在后台启动静态分析服务

执行 CodeChecker store ./results_openssl -n openssl: 将分析结果加入 Server,并命名为 openssl

通过 Web 图形化界面,可以看到本次静态分析汇报了 2371 个潜在的安全问题,其中大部分并不是存在安全漏洞,而是类似于 Value stored to 'ret' is never read之类的编码规范的问题:

选择其中安全级别为 High 的一项进行分析,报告的问题是可能存在空指针解引用的问题:

具体查看潜在的路径:

指针 aux 先初始化为 it->funcs,假设 pval 不为 null,进一步假设 aux 为 null,即 it->funcs 为 null,然后在 switch 语句中假设 it->itype 的值为ASN1_ITYPE_EXTERN,从而将 ef 赋值为 it->funcs,根据前面的假设,此时 ef 为 null,因此 return 语句中的 ef->asn1_ex_d2i()会导致空指针解引用。

因此,此处空指针解引用触发的条件是 it 指针所指对象的 funcs 为 null,同时 it 指针所指的 itype 值为ASN1_ITYPE_EXTERN,因此需要能够构造该函数的输入参数 it 使得其满足条件,但是是否能够手动构造 it 是一个问题。如果 it 能够满足这 2 个条件,同时 ASN1_item_ex_d2i 函数能够同时被调用,从而触发空指针解引用,将引起程序崩溃或其他未定义的行为。