█████╗ ███████╗ ██████╗███████╗███╗ ██╗██████╗
██╔══██╗██╔════╝██╔════╝██╔════╝████╗ ██║██╔══██╗
███████║███████╗██║ █████╗ ██╔██╗ ██║██║ ██║
██╔══██║╚════██║██║ ██╔══╝ ██║╚██╗██║██║ ██║
██║ ██║███████║╚██████╗███████╗██║ ╚████║██████╔╝
╚═╝ ╚═╝╚══════╝ ╚═════╝╚══════╝╚═╝ ╚═══╝╚═════╝
### 离线 Linux 提权 · 攻击面映射工具
**结构化、强类型、只读。** 映射本地提权攻击面,将其与
内置的离线数据集进行关联,并获取一份**经过排序和解释**的可操作报告 ——
具备 LinPEAS 风格的覆盖率,但每一项发现都是一个包含*原因*和*修复方案*的一等对象。
[](https://github.com/FlinnZee/ascend/releases)
[](LICENSE)







[**安装**](#installation) · [**使用方法**](#usage) · [**收集器**](#the-collectors-in-this-build) · [**架构**](#architecture) · [**扩展**](#extending-writing-a-collector) · [**致谢**](#credits)
`ascend` 是大型枚举脚本的结构化、强类型、可测试替代方案:它会提出
相同的“攻击者能在这里滥用什么?”的问题,但每个答案都会作为一个
一等 **finding** 返回,包含 id、严重性、具体证据、通俗的
**原因** (why) 以及 **修复步骤** (remediation)。
## ascend 是什么 —— 以及不是什么
`ascend` 是一款**防御性审计与强化工具**。
* **只读。** 它绝不对受审计的系统进行写入、修改或执行任何操作。
收集器仅通过完全不暴露任何修改方法的只读文件系统
接口来访问外界 —— 只读是架构的固有属性,而不仅仅是文档中的承诺。
* **离线。** **没有任何网络调用**。所有关联数据
(已知的高风险二进制文件、危险 capabilities、修复文本、示例内核 CVE 集)都打包在程序内并在本地加载。
* **无利用行为。** 它不尝试、展示或提供提权
步骤。它只报告某个二进制文件在具有 SUID 时*是*危险的,并从抽象层面解释*原因* —— 绝不说明*如何*滥用它。没有 payload,没有 PoC,没有 shell 调用。
* **无 LLM,无遥测。** 它是一个确定性的静态分析器:相同的主机
必定生成相同的报告。
可用于审计你拥有或被授权评估的机器,建立 SUID/
capability 基线并在发生偏移时发出警报,或者作为附带详细
推理说明的强化检查清单。
## 为什么结构化收集器 + 离线数据层胜过单体脚本
通常的做法是使用一个庞大的单体枚举脚本。但它存在三个
问题,而此架构正是为了解决这些问题而设计的:
| 关注点 | 单体脚本 | `ascend` |
| --- | --- | --- |
| **可扩展性** | 新的检查项被不断追加到一个日益庞大的文件中;执行顺序、输出格式和全局变量都变成了人人避之不及的共享状态。 | 收集器是一个仅实现一个方法的独立类。只需放入一个模块,对其进行装饰,排序 / JSON / 终端报告就会自动识别它 —— 无需更改引擎代码。 |
| **可测试性** | 检查项会针对真实主机运行实际命令,因此如果没有一个存在漏洞的 VM 就很难进行测试,且结果依赖于运行它的机器。 | 每个收集器都通过注入的 `FileSystem` 进行读取。测试时可以构建一个带有精确权限位的内存树,并对强类型的 finding 进行断言 —— 无需 root,无需 VM,不对主机进行修改,可跨任意 OS 移植。 |
| **误报分诊** | 输出是一大面扁平的文本墙;决定哪些内容重要完全留给读者自己判断。 | Finding 是强类型且经过排序的,每个都带有结构化的**证据**、稳定的 `rule_id` 以及**原因**说明。你可以按严重性过滤、按规则抑制、对比两次 JSON 运行的结果,并查看某项*为何*被标记 —— 从而实现快速且可重复的分诊。 |
具体而言,这种结构能带来以下优势:
* **关联即数据,而非代码。** “哪些二进制文件在具有 SUID 时是危险的”
这类知识以可编辑的 YAML 格式存储,因此可以在不触及 Python 代码的情况下进行审查、扩展或
本地化 —— 并且同样的模式可扩展至未来的
内核版本 → CVE 数据集。
* **审计离线镜像。** 由于收集器接受一个文件系统根目录,`ascend
--root /mnt/target` 可以审计已挂载的磁盘镜像,同时 finding 仍然会报告诸如
`/usr/bin/find` 这样的逻辑路径。
* **机器可读的契约。** 带有稳定规则 id 的 JSON 输出可轻松接入 CI
(`--fail-on high`)、仪表板或工单系统。
## 架构
```
ascend/
├── pyproject.toml # packaging, ruff + mypy + pytest config
├── README.md
├── LICENSE # MIT — Dr.v0id (TK NiRMAL)
├── src/
│ └── ascend/
│ ├── __init__.py # package + version
│ ├── __main__.py # `python -m ascend`
│ ├── cli.py # argparse entrypoint, output selection, exit codes
│ ├── engine.py # collector selection + orchestration + ranking → ScanReport
│ ├── ranking.py # deterministic severity ordering & severity filter
│ ├── report.py # JSON + dark terminal reporters
│ ├── models.py # Severity, Evidence, Finding, HostFingerprint, ScanReport
│ ├── context.py # ScanContext: the injected world a collector sees
│ ├── fs.py # FileSystem protocol + OsFileSystem + MemoryFileSystem
│ ├── util.py # pure permission-bit helpers
│ ├── caps.py # security.capability xattr decoder (getcap-style)
│ ├── rules.py # stable rule-id constants
│ ├── data_layer.py # typed data records + pluggable KernelCveDataset
│ ├── catalog.py # loads bundled YAML into a typed Catalog
│ ├── py.typed # PEP 561 marker (ships type information)
│ ├── collectors/
│ │ ├── base.py # Collector ABC + registry + @register
│ │ ├── _common.py # shared depth-limited walk / path join
│ │ ├── suid.py # SUID/SGID enumeration + risky-binary correlation
│ │ ├── world_writable.py # world-writable sensitive files/dirs + PATH exposure
│ │ ├── cron.py # cron definitions + writable target scripts
│ │ ├── capabilities.py # file-capability enumeration + correlation
│ │ └── kernel.py # kernel/OS fingerprint + kernel-CVE plug-point
│ └── data/
│ ├── risky_binaries.yaml # GTFOBins-style reference data (no exploits)
│ ├── dangerous_capabilities.yaml # root-equivalent capabilities + why
│ ├── remediation.yaml # remediation text keyed by rule id
│ ├── sensitive_paths.yaml # scan scope for world-writable checks
│ └── kernel_cves.sample.yaml # SAMPLE schema for CVE correlation
└── tests/ # pytest suite over the in-memory filesystem
```
### 模块职责
* **`models.py`** —— 统一契约的核心:`Severity`(一个 `IntEnum`,因此
排序就是整数比较)、`Evidence`(事实观察结果)、`Finding`
(id、规则 id、类别、严重性、原因、修复、证据)以及
`ScanReport`(元数据 + 主机指纹 + 排序后的 finding,包含用于
JSON 的 `to_dict()` 方法)。
* **`fs.py`** —— 与外界交互的唯一接口。`FileSystem` 是一个只读的
`Protocol`;`OsFileSystem` 基于可选的
`root` 前缀在主机上实现该接口;`MemoryFileSystem` 是一个完全在内存中运行的后端,带有测试使用的合成
模式和 xattrs(也可用于审计快照)。
* **`context.py`** —— `ScanContext` 封装了收集器可能接触到的所有内容:
文件系统、已加载的目录、运行时的 uid/gid 以及正在被
审计的 PATH。收集器没有其他任何环境依赖,因此它们是纯粹且
可重现的。
* **`catalog.py` / `data_layer.py`** —— 将内置的 YAML 加载为强类型记录,
并暴露可插拔的 `KernelCveDataset` 接口。
* **`collectors/`** —— 每个攻击面对应一个模块(见下文)。`base.py` 定义了
`Collector` ABC 和注册表;导入包后会自动注册所有的收集器。
* **`engine.py`** —— 选择收集器(`--only` / `--skip`),隔离运行每个
(失败的收集器会变成一个低严重性的 finding,而不会
中止扫描),进行排序并组装 `ScanReport`。
* **`report.py`** —— 渲染 JSON 或深色终端视图。在脱离 TTY、
设置 `NO_COLOR` 或使用 `--no-color` 时会自动禁用颜色。
### 当前构建版本中的收集器
| 收集器 | 映射的攻击面 | 标记内容 |
| --- | --- | --- |
| `suid` | set-user-ID / set-group-ID 可执行文件 | 已知的危险 SUID/SGID 二进制文件(与内置列表关联),以及未经审查的特权二进制文件。 |
| `world_writable` | 敏感文件/目录 + `$PATH` | 敏感根目录下的全局可写文件、无粘滞位 (non-sticky) 的全局可写目录,以及可写 / 相对路径 / 空的 `PATH` 元素。 |
| `cron` | 定时任务 | 可写的 crontab 定义、任务引用的可写 *目标脚本*,以及全局/组可写的周期性 (`cron.daily`, …) 目录。 |
| `capabilities` | 文件 capabilities | 解码 `security.capability` xattrs 并标记等效于 root 的 capabilities(`cap_setuid`、`cap_dac_override`、`cap_sys_admin` 等)。 |
| `kernel` | 内核 + OS 身份 | 对内核/发行版进行指纹识别,并将版本与可插拔的(示例)CVE 数据集进行关联 —— 定位为 *根据你的补丁级别进行验证*。 |
### Finding 模型
每个收集器都会返回 `Finding` 对象:
```
{
"id": "suid.known_dangerous:/usr/bin/find",
"rule_id": "suid.known_dangerous",
"category": "suid",
"title": "SUID on known-risky binary 'find'",
"severity": "HIGH",
"severity_rank": 3,
"why": "Can execute arbitrary commands via its action flags; ...",
"remediation": "Remove the SUID/SGID bit unless this binary genuinely needs it ...",
"evidence": [
{ "path": "/usr/bin/find", "mode": "-rwsr-xr-x", "mode_octal": "4755", "uid": 0, "gid": 0 }
],
"references": []
}
```
`severity` 的级别为 `INFO < LOW < MEDIUM < HIGH < CRITICAL`。排序规则为
严重性降序,其次是类别,再其次是 id —— 结果是确定性的,因此两次运行的结果能清晰地对比出差异。
## 安装说明
要求 Python 3.10+。`ascend` 旨在 Linux(即其审计的
攻击面)上运行;该包本身可以正常导入,且其完整的测试套件可在任何 OS 上运行。
```
git clone https://github.com/FlinnZee/ascend
cd ascend
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # runtime dep: PyYAML
```
## 使用方法
```
# 本地 host 的完整审计,dark terminal 报告
ascend
# 用于 CI / dashboards / diffing 的机器可读输出
ascend --json -o audit.json
# 仅保留最高 signal 的 findings
ascend --min-severity high
# 运行特定的 collectors
ascend --only suid,capabilities
# 离线审计已挂载的 image(findings 仍显示逻辑路径)
ascend --root /mnt/target --json
# 如果存在 HIGH 或更高等级的项则中断 pipeline
ascend --fail-on high
# 列出可用的 collectors
ascend --list-collectors
```
退出代码:`0` 成功,`1` 调用错误(例如未知的收集器),`2` 设置了
`--fail-on` 且存在匹配的 finding。
## 离线数据层
关联知识以 YAML(而非代码)的形式存在于 `src/ascend/data/` 中:
* **`risky_binaries.yaml`** —— 关于二进制文件在具有 SUID/SGID 时为何危险的参考数据(生成 shell、运行任意代码、读写文件)。它只记录
*capability 和原因* —— 没有命令,也没有利用步骤。
* **`dangerous_capabilities.yaml`** —— 实际上等效于 root 的文件 capabilities,以及每个 capabilities 重要的原因。
* **`remediation.yaml`** —— 以 `rule_id` 为键的修复文本,运维人员可以
在不触及收集器的情况下调整措辞或指向内部操作手册。
* **`sensitive_paths.yaml`** —— 全局可写文件收集器的扫描范围,因此
信号能保持高信噪比(`/tmp` 下的全局可写文件是预期内的;但在
`/etc` 下则会被标记为一项 finding)。
* **`kernel_cves.sample.yaml`** —— 一个展示 CVE 关联
模式的**示例**。`data_layer.py` 将 `KernelCveDataset` 定义为 `Protocol` 并执行
纯离线的版本范围比对;内置的数据集是刻意保持较少且
非权威性的。策划一套完善的数据集是未来的工作(见下文)。
## 扩展:编写收集器
```
from collections.abc import Iterable
from ascend.collectors.base import Collector, register
from ascend.context import ScanContext
from ascend.models import Evidence, Finding, Severity
@register
class MyCollector(Collector):
name = "my_surface"
title = "My surface"
description = "One line describing what this inspects."
def collect(self, ctx: ScanContext) -> Iterable[Finding]:
# Read-only access only, always through ctx.fs.
if ctx.fs.is_file("/etc/something"):
yield Finding(
id="my_surface.example:/etc/something",
rule_id="my_surface.example",
category=self.name,
title="Something noteworthy",
severity=Severity.MEDIUM,
why="Why this could contribute to escalation.",
remediation="How to fix it.",
evidence=(Evidence(path="/etc/something"),),
)
```
导入你的模块(将其添加到 `collectors/__init__.py` 中),引擎、排序、
JSON 和终端报告就会自动识别它。
## 开发说明
```
ruff check . # lint
mypy # strict type-check (src + tests)
pytest # full suite, runs entirely against the in-memory filesystem
```
测试套件永远不会触碰真实系统:场景全部基于
带有明确权限位的 `MemoryFileSystem` 构建,因此结果是确定性的
且可跨平台移植。
## 路线图
`ascend` 的定位是有意限制在一定范围内的。计划中的后续步骤包括:在现有的 `KernelCveDataset` 接口之上提供一套完善的内核
CVE 关联数据集,增加更多的
收集器(sudo 策略、systemd units 和 timers、NFS/`no_root_squash`、SSH 和
PAM 配置、`/etc/passwd` & `/etcadow` 卫生检查),以及 HTML 报告。
## 许可证
基于 **MIT License** 发布 —— © 2026 **Dr.v0id (TK NiRMAL)**。参见 [LICENSE](LICENSE)。
ascend · 只读的提权攻击面映射工具 · 由 Dr.v0id (TK NiRMAL) 制作