arkanzasfeziii/Race-Condition-Vulnerability-Scanner
GitHub: arkanzasfeziii/Race-Condition-Vulnerability-Scanner
一款结合静态AST分析与动态多线程压力测试的Python竞态条件漏洞扫描器,用于自动检测代码中的TOCTOU缺陷、原子性违规及各类并发同步隐患。
Stars: 0 | Forks: 0
# 竞态条件漏洞扫描器
[](https://www.python.org/)
[](LICENSE)
[](https://github.com/arkanzasfeziii/Race-Condition-Vulnerability-Scanner/actions/workflows/lint.yml)
[]()
一款针对 Python 代码库的专业静态与动态竞态条件漏洞扫描器。通过同步的多线程请求突发检测 TOCTOU 缺陷、Read-Modify-Write 原子性违规、未同步的共享资源访问、数据库并发问题以及 asyncio 竞态。
## 什么是竞态条件?
**竞态条件**(Race Condition)是指程序的执行结果取决于并发操作的相对执行时间。其中影响最大的两类是:
### TOCTOU (Time-of-Check to Time-of-Use)
资源在独立的、非原子的步骤中被检查(例如 `os.path.exists(f)`),然后被使用(例如 `open(f)`)。攻击者或并发线程可以在检查与使用之间的时间窗口内修改该资源。
**现实世界中的影响:**
- 通过符号链接攻击实现权限提升
- 支付系统中的双重消费(检查余额,然后扣款 —— 两个线程都通过了检查)
- 优惠券绕过:两个并发请求在任何一个将其标记为已使用之前,都验证了同一张一次性优惠券
### Read-Modify-Write (RMW) 原子性违规
像 `counter += 1` 这样的操作并不是原子性的。它们会展开为 `READ counter`、`ADD 1`、`WRITE counter` —— 这三个独立的步骤可能会在线程之间发生交错,从而导致更新丢失。
## 检测技术
| 技术 | 描述 |
|-----------|-------------|
| **静态 AST 分析** | 使用 `ast` 解析 Python 源代码,以查找 TOCTOU 模式、针对共享变量的增强赋值以及锁对象跟踪 |
| **动态压力测试** | 针对提取的函数生成 N 个并发线程/进程,并比较输出的哈希值以检测不一致性 |
| **同步请求突发** | 通过随机的微秒级延迟同时启动所有 worker,以扩大竞态窗口 |
| **响应差异分析** | 将所有结果序列化为 JSON 并比较 SHA-256 哈希值 —— 任何差异都标志着存在真实的竞态 |
| **数据库竞态探测** | 创建内存中的 SQLite 测试环境,并运行并发的 Read-Modify-Write 事务 |
## 功能
- 检测 **9 种竞态条件类型**:TOCTOU、Read-Modify-Write、未同步访问、文件竞态、信号处理程序竞态、复合操作、全局变量、数据库竞态、asyncio 竞态
- **双重分析模式**:快速的纯静态分析或静态与动态结合分析
- 带有可配置阈值的**置信度评分**
- 为每个检测到的问题生成 **ASCII 时序图**
- 用于 CI/CD 流水线集成的 **JSON 输出**
- 用于自定义阈值和忽略模式的 **YAML 配置**
- 用于扩展检测逻辑的**插件系统**
- 在动态测试中绕过 Python GIL 的**多进程支持**
- 带有按严重程度分类结果的**彩色终端输出**
## 安装
```
git clone https://github.com/arkanzasfeziii/Race-Condition-Vulnerability-Scanner.git
cd Race-Condition-Vulnerability-Scanner
pip install -r requirements.txt
```
可选依赖:
```
pip install pyyaml colorama hypothesis
```
## 用法
```
# 扫描单个文件
python race_detector.py --file myapp.py
# 扫描项目目录
python race_detector.py --path ./src --threads 16 --iterations 1000
# 仅静态分析(快速,无 subprocess spawning)
python race_detector.py --path . --static-only --ignore "test,venv"
# 用于 CI/CD 的 JSON 输出
python race_detector.py --file app.py --output json > races.json
# 使用 config 文件
python race_detector.py --path ./src --config example/detector.yaml
# 加载自定义 plugins
python race_detector.py --path . --plugin-dir ./plugins
# 运行内置自测
python race_detector.py --self-test --verbose
```
### CLI 参考
| 标志 | 默认值 | 描述 |
|------|---------|-------------|
| `--file FILE` | — | 要扫描的单个 Python 文件 |
| `--path DIR` | — | 要递归扫描的目录 |
| `--snippet CODE` | — | 要分析的内联代码字符串 |
| `--threads N` | 8 | 用于动态测试的并发 worker |
| `--iterations N` | 1000 | 每个候选函数的测试迭代次数 |
| `--static-only` | false | 跳过动态执行 |
| `--ignore PATTERNS` | — | 要跳过的路径子字符串(以逗号分隔) |
| `--config FILE` | — | YAML 配置文件(参见 `example/detector.yaml`) |
| `--plugin-dir DIR` | — | 包含插件 `.py` 文件的目录 |
| `--output text\|json` | text | 报告格式 |
| `--verbose / -v` | false | 调试日志记录 |
**退出代码:** `0` = 未发现竞态,`1` = 检测到竞态,`2` = 致命错误,`130` = 被中断。
## 示例输出
```
================================================================================
RACE CONDITION DETECTION REPORT
by arkanzas.feziii
================================================================================
Scan Statistics:
Files Analyzed: 1
Lines of Code: 42
Race Conditions Found: 2
Min Confidence: 70%
Severity Breakdown:
HIGH : 1
MEDIUM : 1
[1] [HIGH] HIGH - Read-Modify-Write Atomicity Violation
--------------------------------------------------------------------------------
File: counter.py
Line: 8
Method: STATIC
Confidence: 92%
Variable: counter
Description:
Non-atomic read-modify-write on 'counter'. Compound operations like '+='
are not atomic and lose updates in concurrent execution.
Visualization:
Thread A Thread B
| Read counter | Read counter
| (counter=10) | (counter=10)
| Modify (+1) | Modify (+1)
| Write counter=11 | Write counter=11
Lost update! Final value: 11 (should be 12)
Recommended Fix:
Use threading.Lock() for compound operations, or use atomic types
from multiprocessing.Value/Array if using processes.
```
## 插件系统
将一个 `.py` 文件放入 `plugins/` 目录(或通过 `--plugin-dir` 指定的自定义目录)。每个插件必须继承 `PluginInterface` 并实现 `analyze()` 方法:
```
from race_detector import PluginInterface, RaceCondition, RaceType, Severity, DetectorConfig
class MyCustomDetector(PluginInterface):
def analyze(self, code: str, file_path: str, config: DetectorConfig):
races = []
# ... your detection logic using ast or regex ...
return races
```
有关完整的接口约定,请参阅 `plugins/README.md`。
## 配置
复制 `example/detector.yaml` 并进行自定义:
```
min_confidence: 0.75 # Only report findings above this threshold
max_threads: 16 # Dynamic test concurrency
iterations: 1000 # Iterations per candidate function
timeout_per_test: 10 # Seconds before killing a test subprocess
ignore_patterns:
- "test"
- "__pycache__"
- ".venv"
enable_multiprocessing: true
enable_asyncio_detection: true
enable_db_detection: true
```
## CI/CD 集成
```
# .github/workflows/race-check.yml
- name: Race condition scan
run: |
python race_detector.py --path . --output json --static-only > races.json
if [ $? -eq 1 ]; then echo "Race conditions detected!"; exit 1; fi
```
## 检测到的竞态条件类型
| 类型 | 描述 |
|------|-------------|
| `TOCTOU` | 文件/资源在使用前进行了检查,且没有原子性保证 |
| `READ_MODIFY_WRITE` | 在共享状态上执行非原子的复合操作 (+=, -= 等) |
| `UNSYNCHRONIZED_ACCESS` | 在没有锁保护的情况下写入共享变量 |
| `FILE_RACE` | 在并发环境中进行文件操作 |
| `SIGNAL_RACE` | 在多线程程序中注册信号处理程序 |
| `COMPOUND_OPERATION` | 通过不一致的输出动态确认的竞态 |
| `GLOBAL_VARIABLE` | 使用全局变量的多线程且没有 Lock 对象 |
| `DATABASE_RACE` | 没有事务锁的并发数据库操作 |
| `ASYNCIO_RACE` | 多个 async 函数在没有 asyncio.Lock 的情况下共享状态 |
| `TEMPFILE_RACE` | 在并发环境中使用带 delete=False 的 NamedTemporaryFile |
## 作者
**arkanzas.feziii** — MIT License
有关负责任的披露,请参阅 [SECURITY.md](SECURITY.md);有关贡献指南,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
标签:Python, 加密, 并发安全, 无后门, 漏洞扫描器, 竞态条件, 计算机取证, 逆向工具, 错误基检测, 静态代码分析