跳转到主要内容

用于处理污点分析结果的静态分析后处理器。

项目描述

lint tests pyre

SAPP

SAPP代表静态分析后处理器。SAPP接受PysaMariana Trench的原始结果,并通过命令行界面和Web UI使其可探索。

SAPP 还可在 GitHub Marketplace 上作为 GitHub Action 使用。

安装

要运行 SAPP,您需要 Python 3.8 或更高版本。您可以使用 pip install fb-sapp 通过 PyPI 安装 SAPP。

入门指南

本指南假设您已将 Pysa 运行的结果保存在 ~/example 目录中。如果您是 Pysa 的新手,可以按照 此教程 开始。

处理结果

后处理将包含每个分析函数模型的原始输出转换为更适合探索的格式。

[~/example]$ sapp --database-name sapp.db analyze taint-output.json

在结果被处理后,我们现在可以通过 UI 和命令行界面来探索它们。在这里我们将简要介绍这两种方法。

Web 界面

使用以下命令启动 Web 界面

[~/example]$ sapp --database-name sapp.db server --source-directory=<WHERE YOUR CODE LIVES>

并在您的浏览器中访问 http://localhost:13337(注意:当前代码输出中显示的 URL 将无法使用)。您将看到一个包含示例跟踪访问权限的问题列表。

命令行界面

同样可以通过命令行界面访问这些信息

[~/example]$ sapp --database-name sapp.db explore

这将启动一个连接到 sqlite 文件的定制 IPython 界面。在此模式下,您可以深入研究 Pyre 提出的问题。以下是如何使用各种命令的示例。

首先列出所有已知问题

==========================================================
Interactive issue exploration. Type 'help' for help.
==========================================================

[ run 1 ]
>>> issues
Issue 1
    Code: 5001
 Message: Possible shell injection Data from [UserControlled] source(s) may reach [RemoteCodeExecution] sink(s)
Callable: source.convert
 Sources: input
   Sinks: os.system
Location: source.py:9|22|32
Found 1 issues with run_id 1.

正如预期的那样,我们有一个问题。要选择它

[ run 1 ]
>>> issue 1
Set issue to 1.

Issue 1
    Code: 5001
 Message: Possible shell injection Data from [UserControlled] source(s) may reach [RemoteCodeExecution] sink(s)
Callable: source.convert
 Sources: input
   Sinks: os.system
Location: source.py:9|22|32

查看数据从源到汇的流动情况

[ run 1 > issue 1 > source.convert ]
>>> trace
     # ⎇  [callable]       [port]      [location]
     1    leaf             source      source.py:8|17|22
 --> 2    source.convert   root        source.py:9|22|32
     3    source.get_image formal(url) source.py:9|22|32
     4    leaf             sink        source.py:5|21|28

移动到下一个可调用对象

[ run 1 > issue 1 > source.convert ]
>>> n
     # ⎇  [callable]       [port]      [location]
     1    leaf             source      source.py:8|17|22
     2    source.convert   root        source.py:9|22|32
 --> 3    source.get_image formal(url) source.py:9|22|32
     4    leaf             sink        source.py:5|21|28

显示该可调用对象的源代码

[ run 1 > issue 1 > source.get_image ]
>>> list
In source.convert [source.py:9|22|32]
     4      command = "wget -q https:{}".format(url)
     5      return os.system(command)
     6
     7  def convert() -> None:
     8      image_link = input("image link: ")
 --> 9      image = get_image(image_link)
                              ^^^^^^^^^^

移动到下一个可调用对象并显示源代码

[ run 1 > issue 1 > source.get_image ]
>>> n
     # ⎇  [callable]       [port]      [location]
     1    leaf             source      source.py:8|17|22
     2    source.convert   root        source.py:9|22|32
     3    source.get_image formal(url) source.py:9|22|32
 --> 4    leaf             sink        source.py:5|21|28

[ run 1 > issue 1 > leaf ]
>>> list
In source.get_image [source.py:5|21|28]
     1  import os
     2
     3  def get_image(url: str) -> int:
     4      command = "wget -q https:{}".format(url)
 --> 5      return os.system(command)
                             ^^^^^^^
     6
     7  def convert() -> None:
     8      image_link = input("image link: ")
     9      image = get_image(image_link)

跳转到第一个可调用对象并显示源代码

[ run 1 > issue 1 > leaf ]
>>> jump 1
     # ⎇  [callable]       [port]      [location]
 --> 1    leaf             source      source.py:8|17|22
     2    source.convert   root        source.py:9|22|32
     3    source.get_image formal(url) source.py:9|22|32
     4    leaf             sink        source.py:5|21|28

[ run 1 > issue 1 > leaf ]
>>> list
In source.convert [source.py:8|17|22]
     3  def get_image(url: str) -> int:
     4      command = "wget -q https:{}".format(url)
     5      return os.system(command)
     6
     7  def convert() -> None:
 --> 8      image_link = input("image link: ")
                         ^^^^^
     9      image = get_image(image_link)

帮助

您可以通过 help 命令获取有关命令行界面中可用命令的更多信息。

$ sapp --help
Usage: sapp [OPTIONS] COMMAND [ARGS]...

Options:
  -v, --verbosity LVL             Either CRITICAL, ERROR, WARNING, INFO or
                                  DEBUG
  -r, --repository DIRECTORY      Root of the repository (regardless of the
                                  directory analyzed)
  --database-name, --dbname FILE
  --database-engine, --database [sqlite|memory]
                                  database engine to use
  --tool [pysa|mariana-trench]    tool the data is coming from
  -h, --help                      Show this message and exit.

Commands:
  analyze  parse static analysis output and save to disk
  explore  interactive exploration of issues
  filter
  lint     Output DB models in a lint-friendly format
  server   backend flask server for exploration of issues
  update

术语

单个 SAPP 数据库可以跟踪的不仅仅是单个运行。这为在代码库中推理 新引入的问题 打开了可能性。

每次调用

[~/example]$ sapp --database-name sapp.db analyze taint-output.json

将向数据库添加单个 运行。一个问题可以存在于多个运行中(我们通常将单个运行中的问题称为 实例)。您可以从 Web UI 选择一个运行并查看该运行的所有实例。您还可以在筛选菜单中选择仅显示在本运行中引入的新问题实例。

每个实例由从特定源类型(例如用户控制的输入)到 可调用对象(即函数或方法)的数据流以及从该可调用对象到特定汇类型(例如 RCE)的数据流组成。

注意:数据可以来自同一类型的不同来源并流入同一类型的不同汇。单个实例的跟踪视图代表了许多跟踪,而不仅仅是单个跟踪。

筛选器

SAPP 筛选器用于根据您选择的问题属性来包含/排除哪些问题显示给您。筛选器对于从静态分析工具的输出中去除噪声非常有用,这样您就可以关注您关心的特定问题属性。

可以通过 Web 界面或 sapp filter 的子命令访问 SAPP 功能。

文件格式

筛选器必须有一个 name 和至少一个其他键,不包括 description。筛选器可以以下格式存储为 JSON:

{
  "name": "Name of filter",
  "description": "Description for the filter",
  "features": [
    {
      "mode": "all of",
      "features": ["via:feature1", "feature2"]
    },
    {
      "mode": "any of",
      "features": ["always-via:feature3"]
    },
    {
      "mode": "none of",
      "features": ["type:feature5"]
    }
  ],
  "codes": [5005],
  "paths": ["filename.py"],
  "callables": ["main.function_name"],
  "traceLengthFromSources": [0, 3],
  "traceLengthToSinks": [0, 5],
  "is_new_issue": false
}

您可以在 pyre-check 仓库 中找到一些示例筛选器以供参考。

导入筛选器

您可以通过运行以下命令从文件中导入过滤器:

[~/example]$ sapp --database-name sapp.db filter import filter-filename.json

您也可以通过运行以下命令导入目录中所有的过滤器:

[~/example]$ sapp --database-name sapp.db filter import path/to/list_of_filters

导出过滤器

您可以通过运行以下命令在 SAPP 数据库中查看过滤器:

[~/example]$ sapp --database-name sapp.db filter export "filter name"

您可以通过运行以下命令将 SAPP 数据库中的过滤器导出到文件:

[~/example]$ sapp --database-name sapp.db filter export "filter name" --output-path /path/to/filename.json

删除过滤器

您可以使用以下命令按名称删除过滤器:

[~/example]$ sapp --database-name sapp.db filter delete "filter name 1" "filter name 2" "filter name 3"

过滤问题列表

您可以通过运行号应用过滤器到问题列表。例如,以下命令将在运行号 1 上应用 example-filter 过滤器,并显示问题列表:

[~/example]$ sapp --database-name sapp.db filter issues 1 example-filter.json

您也可以通过运行号将多个过滤器应用到一个问题列表中。SAPP 会将您指定的目录中的每个过滤器单独应用到问题列表中,并将结果合并为一个问题列表显示。例如,以下命令将在运行号 1 上应用 list_of_filters 目录中的所有过滤器,并显示问题列表:

[~/example]$ sapp --database-name sapp.db filter issues 1 path/to/list_of_filters

SARIF 输出

您可以通过在 SAPP 中首先存储静态分析工具的警告代码信息,然后运行带有 --output-format=sarif 选项的 sapp filter issues 命令来获取过滤运行的 SARIF 输出。

sapp --database-name sapp.db update warning-codes taint-metadata.json

然后运行 sapp filter issues 命令,并使用 --output-format=sarif 选项。

sapp --database-name sapp.db filter issues 1 path/to/list_of_filters --output-format sarif

开发环境设置

首先克隆仓库并设置虚拟环境。

$ git clone git@github.com:facebook/sapp.git && cd sapp
$ python3 -m venv ~/.venvs/sapp
$ source ~/.venvs/sapp/bin/activate
(sapp) $ pip3 install -r requirements.txt

以调试模式运行 Flask 服务器。

(sapp) $ python3 -m sapp.cli server --debug

解析静态分析输出并将其保存到磁盘。

(sapp) $ python3 -m sapp.cli analyze taint-output.json

安装前端依赖项

(sapp) $ cd sapp/ui/frontend && npm install

要使用 Web UI 的热重载运行 SAPP,您需要同时运行前端和后端。在生产环境中,前端应用由后端在 13337 端口上暴露直接编译和提供服务。但在开发环境中,如果未设置 PORT 环境变量,则前端默认在 3000 端口上运行,后端在 13337 端口上运行。您可以使用 debug 标志指示 SAPP 在开发环境中运行。

以开发模式运行 Flask 服务器和 React 应用。

(sapp) $ python3 -m sapp.cli server --debug
(sapp) $ cd sapp/ui/frontend && npm run-script start

然后访问 http://localhost:3000(如果您已设置 HOST 和/或 PORT 环境变量,则为 http://<HOST>:<PORT>)。

许可证

SAPP 使用 MIT 许可证。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解更多关于 安装包 的信息。

源分发

fb-sapp-0.5.6.tar.gz (1.8 MB 查看哈希)

上传

构建分发

fb_sapp-0.5.6-py3-none-any.whl (1.9 MB 查看哈希)

上传于 Python 3

由以下支持