ispras/casr
GitHub: ispras/casr
CASR 是一套崩溃分析与严重性报告工具,用于收集、去重聚类模糊测试产生的崩溃报告并评估其可利用性。
Stars: 357 | Forks: 36
[](https://crates.io/crates/casr)
[](https://docs.rs/libcasr)
[](https://app.codecov.io/github/ispras/casr)
[](https://github.com/ispras/casr/blob/master/LICENSE)
[](https://github.com/ispras/casr/actions/workflows/amd64.yml)
[](https://github.com/ispras/casr/actions/workflows/aarch64.yml)
[](https://github.com/ispras/casr/actions/workflows/riscv64.yml)
[](https://github.com/ispras/casr/actions/workflows/darwin-arm64.yml)
[](https://github.com/ispras/casr/actions/workflows/fuzzing.yml)
# CASR:崩溃分析与严重性报告
CASR – 收集崩溃(或 UndefinedBehaviorSanitizer 错误)报告、进行分类并评估严重性。
它基于 [exploitable](https://github.com/jfoote/exploitable) 和
[apport](https://github.com/canonical/apport) 的思想。
CASR 由以下人员维护:
* [Andrey Fedotov](https://github.com/anfedotoff) \
* [Alexey Vishnyakov](https://github.com/SweetVishnya) \
* [Georgy Savidov](https://github.com/Avgor46) \
* [Ilya Yegorov](https://github.com/hkctkuy) \
* [Darya Parygina](https://github.com/PaDarochek) \
## 概述
CASR 是一套工具,允许您通过不同方式收集崩溃报告。
使用 `casr-core` 二进制文件处理 coredump。使用 `casr-san` 分析
ASAN 报告,或使用 `casr-ubsan` 分析
UBSAN 报告。尝试使用 `casr-gdb` 从
gdb 获取报告。使用 `casr-python` 分析 python 报告并从
[Atheris](https://github.com/google/atheris) 获取报告。使用 `casr-java` 分析
java 报告并从
[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer) 获取报告。使用 `casr-js` 分析
JavaScript 报告并从
[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js) 或
[jsfuzz](https://github.com/fuzzitdev/jsfuzz) 获取报告。使用 `casr-csharp` 分析 C#
报告并从 [Sharpfuzz](https://github.com/Metalnem/sharpfuzz) 获取报告。
使用 `casr-lua` 分析 Lua 报告。
崩溃报告包含许多有用信息:针对 x86、x86\_64、arm32、aarch64、rv32g、rv64g 架构的严重性(类似于 [exploitable](https://github.com/jfoote/exploitable)),
操作系统和软件包版本、命令行、堆栈跟踪、寄存器值、
反汇编,甚至是崩溃发生处的源代码片段。报告以 JSON 格式存储。
`casr-cli` 旨在提供 TUI 用于查看报告并将它们转换为 SARIF 报告。
报告的分类(去重、聚类)由 `casr-cluster` 完成。
分类基于来自 [gdb-command](https://github.com/anfedotoff/gdb-command) 的堆栈跟踪比较。
`casr-afl` 用于对由 [AFL++](https://github.com/AFLplusplus/AFLplusplus)
和基于 AFL 的 fuzzer [Sharpfuzz](https://github.com/Metalnem/sharpfuzz) 发现的崩溃进行分类。
`casr-libfuzzer` 可以对由基于
[libFuzzer](https://www.llvm.org/docs/LibFuzzer.html) 的 fuzzer
(C/C++/[go-fuzz](https://github.com/dvyukov/go-fuzz)/[Atheris](https://github.com/google/atheris)
/[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer)/[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js)/
[jsfuzz](https://github.com/fuzzitdev/jsfuzz)/[luzer](https://github.com/ligurio/luzer))
或 [LibAFL](https://github.com/AFLplusplus/LibAFL)
基于的 [fuzzer](https://github.com/AFLplusplus/LibAFL/tree/main/fuzzers) 发现的崩溃进行分类。
`casr-dojo` 允许将新的且唯一的 CASR 报告上传至
[DefectDojo](https://github.com/DefectDojo/django-DefectDojo) (通过
`dojo` feature 启用)。
有关严重性分类的说明请参见 [此处](docs/classes.md)。
您可以在 [此处](docs/usage.md) 查看更详细的使用细节。


### LibCASR
LibCASR 提供 API 用于解析堆栈跟踪、收集崩溃报告、
对崩溃进行分类(去重和聚类)以及评估崩溃的
严重性。
它可以分析来自不同来源的崩溃:
* AddressSanitizer
* MemorySanitizer
* UndefinedBehaviorSanitizer
* Gdb 输出
以及不同的编程语言:
* C/C++
* C#
* Go
* Java
* JavaScript
* Lua
* Python
* Rust
它可以在构建时启用 `exploitable` feature,以评估从 gdb 收集的崩溃的严重性。
要使用 json 保存崩溃报告,请启用 `serde` feature。
## 依赖项
安装运行时依赖项:
```
$ sudo apt install gdb lsb-release
```
从源码构建时安装构建依赖项:
```
$ sudo apt install build-essential clang
```
安装 [Rust](https://www.rust-lang.org/tools/install) 或更新现有的 Rust 安装:
```
$ rustup update
```
## 安装
下载最新的 64 位 Linux
[发布版本](https://github.com/ispras/casr/releases/latest/download/casr-x86_64-unknown-linux-gnu.tar.xz)
或按照下文说明从源码构建。
从 Git 仓库构建:
```
$ git clone https://github.com/ispras/casr
$ cargo update
$ cargo build --release
```
或者您也可以直接从 [crates.io](https://crates.io/crates/casr) 安装 Casr:
```
$ cargo install casr
```
如果您想安装 `casr-dojo`,请添加 `dojo` feature (执行 `cargo build` 时同理):
```
$ cargo install -F dojo casr
```
## 使用说明
**在 Docker 中运行:** 为了获得更好的
去重效果,CASR 会禁用地址随机化,并使用 ptrace 来运行 GDB。因此,启动 Docker 时必须加上
`--cap-add=SYS_PTRACE --security-opt seccomp=unconfined`。
从 coredump 创建报告:
```
$ casr-core -f casr/tests/casr_tests/bin/core.test_destAv -e casr/tests/casr_tests/bin/test_destAv -o destAv.casrep
```
从 AddressSanitizer 输出创建报告:
```
$ clang++ -fsanitize=address -O0 -g casr/tests/casr_tests/test_asan_df.cpp -o test_asan_df
$ casr-san -o asan.casrep -- ./test_asan_df
```
从 MemorySanitizer 输出创建报告:
```
$ clang++ -fsanitize=memory -O0 -g casr/tests/casr_tests/test_msan.cpp -o test_msan
$ casr-san -o msan.casrep -- ./test_msan
```
从 UndefinedBehaviorSanitizer 输出创建报告:
```
$ clang++ -fsanitize=undefined -O0 -g casr/tests/casr_tests/ubsan/test_ubsan.cpp -o test_ubsan
$ casr-ubsan -i casr/tests/casr_tests/ubsan/input1 -o output -- ./test_ubsan @@
$ casr-cli output
```
从 gdb 创建报告:
```
$ casr-gdb -o destAv.gdb.casrep -- casr/tests/casr_tests/bin/test_destAv $(printf 'A%.s' {1..200})
```
从 python 创建报告:
```
$ casr-python -o python.casrep -- casr/tests/casr_tests/python/test_casr_python.py
```
从 java 创建报告:
```
$ casr-java -o java.casrep -- java casr/tests/casr_tests/java/Test1.java
```
从 JavaScript 创建报告:
```
$ casr-js -o js.casrep -- node casr/tests/casr_tests/js/test_casr_js.js
```
从 C# 创建报告:
```
$ casr-csharp -o csharp.casrep -- dotnet run --project casr/tests/casr_tests/csharp/test_casr_csharp/test_casr_csharp.csproj
```
从 Lua 创建报告:
```
$ casr-lua -o lua.casrep -- casr/tests/casr_tests/lua/test_casr_lua.lua
```
查看报告:
```
$ casr-cli casr/tests/casr_tests/casrep/test_clustering_san/load_fuzzer_crash-120697a7f5b87c03020f321c8526adf0f4bcc2dc.casrep
```
查看关于崩溃聚类的汇总统计信息:
```
$ casr-cli casr_reports
```
将报告转换为 SARIF 报告:
```
$ casr-cli --sarif out.sarif --tool libfuzzer --source-root /xlnt casr/tests/casr_tests/casrep/test_clustering_san
```
```
$ casr-san --stdin seed -o san_bin.casrep -- ./san_bin
```
对报告进行去重:
```
$ casr-cluster -d casr/tests/casr_tests/casrep/test_clustering_gdb out-dedup
```
对报告进行聚类:
```
$ casr-cluster -c out-dedup out-cluster
```
使用 casr-afl 对 AFL++ fuzzing 后的崩溃进行分类:
```
$ cp casr/tests/casr_tests/bin/load_afl /tmp/load_afl
$ cp casr/tests/casr_tests/bin/load_sydr /tmp/load_sydr
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-xlnt -o casr/tests/tmp_tests_casr/casr_afl_out
$ # You may also additionally generate crash reports for uninstrumented binary with casr-gdb
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-xlnt -o casr/tests/tmp_tests_casr/casr_afl_out -- /tmp/load_sydr @@
```
使用 casr-afl 对 Sharpfuzz fuzzing 后的崩溃进行分类:
```
$ cp -r casr/tests/casr_tests/csharp/test_casr_afl_csharp /tmp/test_casr_afl_csharp
$ cp -r casr/tests/casr_tests/csharp/test_casr_afl_csharp_module /tmp/test_casr_afl_csharp_module
$ dotnet publish /tmp/test_casr_afl_csharp/test_casr_afl_csharp.csproj -c Debug -o /tmp/test_casr_afl_csharp/bin
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-sharpfuzz -o casr/tests/tmp_tests_casr/casr_afl_csharp_out
$ # You may force your own run arguments using --ignore-cmdline
$ casr-afl --ignore-cmdline -i casr/tests/casr_tests/casrep/afl-out-sharpfuzz -o casr/tests/tmp_tests_casr/casr_afl_csharp_out -- dotnet run --no-build --project /tmp/test_casr_afl_csharp/test_casr_afl_csharp.csproj @@
$ # If you use vanilla AFL for fuzzing with Sharpfuzz, force your own run arguments via --
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-sharpfuzz/afl_main-worker -o casr/tests/tmp_tests_casr/casr_afl_csharp_out -- dotnet run --no-build --project /tmp/test_casr_afl_csharp/test_casr_afl_csharp.csproj @@
```
使用 casr-libfuzzer 对 libFuzzer 崩溃进行分类:
```
$ casr-libfuzzer -t 30 -i casr/tests/casr_tests/casrep/libfuzzer_crashes_xlnt -o casr/tests/tmp_tests_casr/casr_libfuzzer_out -- casr/tests/casr_tests/bin/load_fuzzer
```
使用 casr-libfuzzer 对 Atheris 崩溃进行分类:
```
$ unzip casr/tests/casr_tests/python/ruamel.zip
$ casr-libfuzzer -i casr/tests/casr_tests/casrep/atheris_crashes_ruamel_yaml -o casr/tests/tmp_tests_casr/casr_libfuzzer_atheris_out -- casr/tests/casr_tests/python/yaml_fuzzer.py
```
使用 casr-libfuzzer 对 Jazzer.js 崩溃进行分类(Jazzer.js 安装[指南](https://github.com/CodeIntelligenceTesting/jazzer.js#quickstart)):
```
$ unzip casr/tests/casr_tests/js/xml2js.zip -d xml2js
$ mkdir -p casr/tests/tmp_tests_casr/xml2js_fuzzer_out
$ cp casr/tests/casr_tests/js/test_casr_libfuzzer_jazzer_js_xml2js.js casr/tests/tmp_tests_casr/xml2js_fuzzer_out/xml2js_fuzzer.js
$ sudo npm install xml2js
$ sudo npm install --save-dev @jazzer.js/core
$ casr-libfuzzer -i ./xml2js -o casr/tests/tmp_tests_casr/xml2js_fuzzer_out/out -- npx jazzer casr/tests/tmp_tests_casr/xml2js_fuzzer_out/xml2js_fuzzer.js
```
使用 casr-libfuzzer 对 luzer 崩溃进行分类:
```
$ unzip casr/tests/casr_tests/lua/xml2lua.zip && cd xml2lua && luarocks --local build && cd .. && rm -rf xml2lua
$ git clone https://github.com/ligurio/luzer.git && cd luzer && luarocks --local build && cd .. && rm -rf luzer
$ eval $(luarocks path)
$ casr-libfuzzer -i casr/tests/casr_tests/casrep/luzer_crashes_xml2lua -o casr/tests/tmp_tests_casr/casr_libfuzzer_luzer_out -- casr/tests/casr_tests/lua/stdin_parse_xml.lua
```
使用 casr-libfuzzer 对 LibAFL 崩溃进行分类:
```
$ casr-libfuzzer -i casr/tests/casr_tests/casrep/test_libafl_crashes -o casr/tests/tmp_tests_casr/casr_libafl_out -- casr/tests/casr_tests/bin/test_libafl_fuzzer @@
```
将新的且唯一的 CASR 报告上传至
[DefectDojo](https://github.com/DefectDojo/django-DefectDojo):
```
$ echo '[product]' > dojo.toml
$ echo 'name = "xlnt"' >> dojo.toml
$ echo '[engagement]' >> dojo.toml
$ echo "name = \"load_fuzzer $(date -Isec)\"" >> dojo.toml
$ echo '[test]' >> dojo.toml
$ echo 'test_type = "CASR DAST Report"' >> dojo.toml
$ casr-dojo -i casr/tests/casr_tests/casrep/test_clustering_san -u http://localhost:8080 -t 382f5dfdf2a339f7c3bb35442f9deb9b788a98d5 dojo.toml
```
## Fuzzing 崩溃分类流水线
当您通过 fuzzing 获得崩溃后,可以执行以下步骤:
1. 通过 `casr-san`、`casr-gdb`(如果没有使用 sanitizer)、
`casr-python`、`casr-java`、`casr-js` 或 `casr-csharp` 为所有崩溃创建报告。
2. 通过 `casr-cluster -d` 对收集到的崩溃报告进行去重。
3. 通过 `casr-cluster -c` 对去重后的崩溃报告进行聚类。
4. 通过 `casr-ubsan` 为所有 UBSAN 错误创建报告并进行去重。
5. 使用 `casr-cli` 查看聚类中的报告,或使用
`casr-dojo` 将它们上传至
[DefectDojo](https://github.com/DefectDojo/django-DefectDojo)。
如果您使用 [AFL++](https://github.com/AFLplusplus/AFLplusplus) 或基于 AFL 的
fuzzer [Sharpfuzz](https://www.llvm.org/docs/LibFuzzer.html),该流水线
(不包含 `casr-ubsan` 和 `casr-dojo`)可由
`casr-afl` 自动完成。
如果您使用基于 [libFuzzer](https://www.llvm.org/docs/LibFuzzer.html) 的 fuzzer
(C/C++/[go-fuzz](https://github.com/dvyukov/go-fuzz)/[Atheris](https://github.com/google/atheris)
/[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer)/[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js)/
[jsfuzz](https://github.com/fuzzitdev/jsfuzz)) 或基于 [LibAFL](https://github.com/AFLplusplus/LibAFL) 的 fuzzer,
该流水线(不包含 `casr-ubsan` 和 `casr-dojo`)可由 `casr-libfuzzer` 自动完成。
## 引用我们
Savidov G., Fedotov A. Casr-Cluster: Crash Clustering for Linux Applications. 2021 Ivannikov ISPRAS Open Conference (ISPRAS), IEEE, 2021, pp. 47-51. DOI: [10.1109/ISPRAS53967.2021.00012](https://www.doi.org/10.1109/ISPRAS53967.2021.00012) \[[论文](https://arxiv.org/abs/2112.13719)\] \[[幻灯片](https://sydr-fuzz.github.io/papers/casr-cluster.pdf)\]
```
@inproceedings{savidov2021casr,
title = {{{Casr-Cluster}}: Crash Clustering for Linux Applications},
author = {Savidov, Georgy and Fedotov, Andrey},
booktitle = {2021 Ivannikov ISPRAS Open Conference (ISPRAS)},
pages = {47--51},
year = {2021},
organization = {IEEE},
doi = {10.1109/ISPRAS53967.2021.00012},
}
```
Andrey Fedotov, Alexey Vishnyakov. CASR: Your Life Vest in a Sea of Crashes. OFFZONE 2023. \[[幻灯片](https://vishnya.xyz/mirror/casr-offzone2023.pdf)\] \[[俄语视频](https://youtu.be/EgEeICZQD9M?si=hiFEwPmDqnh0cEq6)\]
Yegorov I., Savidov G. Crash Report Accumulation During Continuous Fuzzing with CASR. Ivannikov Memorial Workshop 2024, IEEE, 2024. \[[论文](https://arxiv.org/abs/2405.18174)\] \[[幻灯片](https://sydr-fuzz.github.io/papers/crash-accumulation.pdf)\] \[[俄语视频](https://www.youtube.com/live/xI1LQS3C7eQ?si=dHNdm4-nZFc2QdQf&t=27620)\]
```
@inproceedings{yegorov2024accum,
title = {Crash Report Accumulation During Continuous Fuzzing},
author = {Yegorov, Ilya and Savidov, Georgy},
booktitle = {Ivannikov Memorial Workshop 2024},
publisher = {IEEE},
year = {2024},
url = {https://arxiv.org/abs/2405.18174},
}
```
## 许可证
采用 [Apache-2.0](LICENSE) 许可。
标签:Hakrawler, IPv6支持, 可视化界面, 通知系统