Google 开源 Atheris,Python 代码安全扫描工具

Atheris 使用模糊测试技术扫描 Python 代码中的漏洞

最近更新时间 2020-12-14 12:35:56

Atheris

2020年12月4日,Google 发布了一款开源代码安全扫描工具 Atheris Python Fuzzer。

模糊测试是一种软件测试技术。其核心思想是将自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言失败,以发现可能的程序错误,比如内存泄漏。模糊测试常常用于检测软件或计算机系统的安全漏洞。Google 使用此技术发现了数千个安全漏洞和其他错误。传统上的模糊处理是在 C 或 C ++ 等本地语言上使用的。但是去年,Google 构建了一个新的 Python 模糊处理引擎。12月4日,Google 终于将 Atheris 模糊引擎作为开源发布。

Atheris 能做什么?

Atheris 可用于自动查找 Python 代码和本机扩展中的错误。 Atheris 是一个“覆盖率导向”的模糊器,这意味着 Atheris 将在观察程序如何执行的同时反复尝试对程序的各种输入,并尝试找到有趣的代码执行路径。

Atheris 支持的版本?

Atheris 于去年10月在 Google 内部进行开发,并支持以 Python 2.7 和 Python 3.3+ 编写的 Python 代码和使用 CPython 创建的本机扩展。但在最新的申明中,Google 强烈建议使用 Python 3.8+,因为它可以提供更好的覆盖率信息。在对本机扩展进行模糊处理时,可以将 Atheris 与 Address Sanitizer 或 Undefined Behavior Sanitizer 结合使用。

未来会在 OSS-Fuzz 中支持 Atheris。

怎样安装 Atheris?

Atheris 已经在 Github 上开源发布。Atheris 支持 Linux (32- and 64-bit) and Mac OS X。

使用 pip3 命令安装

yum install clang
使用 pip 3安装
pip3 install atheris
Installing collected packages: atheris
    Running setup.py install for atheris ... done
Successfully installed atheris-1.0.7

注意:Atheris 依赖 Clang 发行的 libFuzzer。如果您已安装 Clang 版本,则安装非常简单。如果您没有安装 Clang 或版本太旧,则需要下载并构建最新版本的 LLVM。

# coding=utf-8

# Python3 代码
# 怎样使用 Atheris

import atheris
import sys

def TestOneInput(data):
    if data == b"bad":
        raise RuntimeError("Badness!")

atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
INFO: Configured for Python tracing with opcodes.
WARNING: Failed to find function "__sanitizer_acquire_crash_state".
WARNING: Failed to find function "__sanitizer_print_stack_trace".
WARNING: Failed to find function "__sanitizer_set_death_callback".
INFO: Seed: 3042541424
INFO: Loaded 2 modules   (1024 inline 8-bit counters): 512 [0x2554460, 0x2554660), 512 [0x2556e90, 0x2557090), 
INFO: Loaded 2 PC tables (1024 PCs): 512 [0x2554e80,0x2556e80), 512 [0x25578b0,0x25598b0), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
	NEW_PY_FUNC[1/2]: TestOneInput() /data/python/code.py:9
INFO: A corpus is not provided, starting from an empty corpus
#2	INITED cov: 7 ft: 7 corp: 1/1b exec/s: 0 rss: 29Mb

 === Uncaught Python exception: ===
RuntimeError: Badness!
	NEW_PY_FUNC[1/2]: _find_and_load() :1002
	NEW_PY_FUNC[2/2]: __init__() :152
Traceback (most recent call last):
  File "/data/python/code/code.py", line 11, in TestOneInput
    raise RuntimeError("Badness!")

==64413== ERROR: libFuzzer: fuzz target exited
SUMMARY: libFuzzer: fuzz target exited
MS: 3 InsertByte-CMP-EraseBytes- DE: "bad"-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
0x62,0x61,0x64,
bad
artifact_prefix='./'; Test unit written to ./crash-1902e3d6fc4e78a0bcc50ba12b882769afbf4a8c
Base64: YmFk
rss_feed