# 外网黑盒探测记录 — 生产 api.synaglobal.vip

**日期**：2026-06-06  
**目标**：`https://api.synaglobal.vip`  
**脚本**：`scripts/security_probe_external.sh`  
**约束**：无 JWT、无真实 API Key、无登录暴破、无破坏性写操作（除只读探测外仅单次错误登录与假 Key 请求）

## 执行命令

```bash
NEXUS_PROBE_BASE=https://api.synaglobal.vip bash scripts/security_probe_external.sh
```

日志：`/tmp/nexus-external-probe/probe-20260606T160732Z.txt`

## 探测结果摘要

| 探测项 | 期望 | 实际 | 判定 |
|--------|------|------|------|
| `GET /health` | 200 纯文本 ok | 200 `ok` | PASS |
| `GET /health/detail` | 401 | **200** + redis/mysql/ws 状态 | **FAIL (P2)** |
| `GET /openapi.json` | 记录 | 200 全量 OpenAPI 3.1 | WARN (H) |
| `GET /docs` | 记录 | 200 Swagger UI | WARN (H) |
| `GET /redoc` | 记录 | 200 ReDoc | WARN (H) |
| `GET /api/install/status` | 404（已锁定） | 404 空 body | PASS |
| `GET /api/install/env-check` 等 | 403/404 | 403「安装向导已锁定」 | PASS |
| `POST /api/install/*` | 403 | 422（探测 body 不满足 Pydantic；锁定逻辑在合法 body 前亦会 403） | INFO |
| `GET /api/settings/bing-wallpapers` | 200 只读 URL | 200 urls[] | PASS |
| `POST /api/settings/bing-wallpapers/sync` | 401 | **200** + downloaded=8 | **FAIL (P2)** |
| `GET/POST /api/servers/` | 401 | 401 Missing Authorization | PASS |
| `GET /api/audit/` | 401 | 401 | PASS |
| `POST /api/agent/heartbeat` 无 Key | 拒绝 | 422（缺 Header） | PASS（仍拒绝） |
| `POST /api/agent/heartbeat` 假 Key | 401 | 401 | PASS |
| `POST /api/agent/script-callback` 假 Key | 401/404 | 422（缺字段；带 Key 时预期 401/404） | PASS |
| `POST /api/auth/login` 错误用户 | 统一错误文案 | `用户名或密码错误` | PASS |
| `GET /agent/install.sh` | 200 | 200 安装脚本 | INFO（设计如此） |
| `WS /ws/alerts` 无 token | 4001 或拒绝 | **HTTP 403**（反代层） | INFO |
| `WS /ws/alerts` 假 token | 4401 或拒绝 | **HTTP 403** | INFO |

## 响应片段（关键 FINDING）

### `/health/detail` 未授权可读

```http
GET /health/detail HTTP/1.1
Host: api.synaglobal.vip

HTTP/1.1 200 OK
{"status":"ok","checks":{"python":"ok","redis":"ok","mysql":"ok","websocket_clients":0}}
```

### `bing-wallpapers/sync` 未授权可触发外联同步

```http
POST /api/settings/bing-wallpapers/sync HTTP/1.1
Content-Type: application/json

HTTP/1.1 200 OK
{"urls":[...],"count":8,"downloaded":8}
```

### OpenAPI 可访问（节选）

`GET /openapi.json` → 200，含全部管理 API path（含 `/api/servers/pending/add-by-ip` 等）。

## WebSocket 说明

外网经 `wss://api.synaglobal.vip/ws/*` 握手在到达应用前被反代返回 **403**，无法在公网直接观测应用层 close code **4001/4401**。应用代码（`server/api/websocket.py`）在无 token 时设计为 4001。

## 结论

- **0 个 P0/P1**（未授权 RCE、未授权写库、未授权读密文）
- **2 个 P2**：`/health/detail` 组件指纹泄露；`bing-wallpapers/sync` 未授权触发外联下载
- **多项 H**：OpenAPI/Swagger/ReDoc 暴露；WS 外网 403 无法验证 ADR-011 关闭码

详见 [`2026-06-06-external-attack-surface-audit.md`](2026-06-06-external-attack-surface-audit.md)。
