codex / docs /anti-detection-critical-analysis.md
webhook's picture
Upload 137 files
89419ea verified
|
Raw History Blame Contribute Delete
8.25 kB
# HTTP-Only 设备指纹补强方案 — 批判性深度分析(v2 修订版)
> 以反检测专家视角,**结合代码实查**,对原始分析文档以及 v1 批判报告的逐项复核。
> ⚠️ v2 修正了 v1 中 3 处事实性错误,并新增了 3 个代码中发现的**真实 bug**。
---
## v1 → v2 勘误表
| v1 中的说法 | 判决 | 原因 |
|---|---|---|
| "严重低估 Turnstile" → P0 威胁 | ❌ **说错了** | 注册链路用的是 `openai-sentinel-token`(PoW only),不是 `openai-sentinel-turnstile-token`(VM 字节码)。两条链路完全独立。项目能跑通即为实证。 |
| "`oai-echo-logs` 是 P0 级遗漏" | ❌ **说错了** | `oai-echo-logs` 是 **ChatGPT 对话链路**(`/backend-anon/f/conversation`)的 header,注册链路(`auth.openai.com/api/accounts/*`)从未出现过。混淆了两条链路。 |
| "Auth0 内置 ML bot detection" | ⚠️ **不准确** | 代码中 OpenAI 使用的是 **自有 auth 端点**(`auth.openai.com/api/accounts/authorize/continue` 等),不是标准 Auth0 Universal Login。不能直接套用 Auth0 商业版的 bot detection 文档。 |
| Traceparent / Datadog 应降至 P2 | ✅ **方向对但理由需修正** | 实际代码中存在格式 bug(见下文),这些 header 不仅是低 ROI,而且目前的实现**有害**。 |
| Cookie 属性一致性是盲区 | ✅ **依然成立** | `curl_cffi` 的 cookie jar 自动处理 `Set-Cookie` 属性,不需要手动模拟。但如果有**手动硬编码 cookie**,需要确认属性匹配。 |
| Client Hints 不完整 | ✅ **依然成立,比想象中更严重** | 整个 `src/` 目录中 **零个** `sec-ch-ua` header。 |
---
## 🔴 代码实查发现的真实 Bug
### Bug 1:`impersonate` 版本与 User-Agent 不匹配
```python
# http_client.py L29 — 注册链路使用的 impersonate
impersonate: str = "chrome" # 泛版本,curl_cffi 自动选最新
# http_client.py L258-259 — 硬编码的 User-Agent
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/120.0.0.0 Safari/537.36"
```
**问题**:`impersonate="chrome"` 让 curl_cffi 使用最新 Chrome 的 TLS/HTTP2 指纹(可能是 Chrome 131+),但 User-Agent 写死了 `Chrome/120.0.0.0`。TLS 指纹说 Chrome 131,UA 说 Chrome 120 —— **这是一个典型的指纹分裂信号**。
**对比**:项目其他模块统一使用 `impersonate="chrome110"`,至少内部一致。
**修复建议**:将 impersonate 固定为具体版本(如 `chrome120`),或动态匹配 UA 版本。
---
### Bug 2:`traceparent` 与 `x-datadog-trace-id` 不一致
```python
# register.py L279-288
def _make_trace_headers(self) -> Dict[str, str]:
trace_id = random.randint(10 ** 17, 10 ** 18 - 1) # 十进制整数
parent_id = random.randint(10 ** 17, 10 ** 18 - 1) # 十进制整数
return {
"traceparent": f"00-{uuid.uuid4().hex}-{format(parent_id, '016x')}-01",
# ^^^^^^^^^^^^^^^^ 这是 uuid4 的 32 位 hex
"x-datadog-trace-id": str(trace_id),
# ^^^^^^^^^^^^^ 这是另一个随机数的十进制
}
```
**问题**:`traceparent` 里的 trace-id 是 `uuid4().hex`(32位hex),但 `x-datadog-trace-id` 是另一个完全不相关的十进制随机数。真实 Datadog RUM SDK 中,这两个值**必须对应同一个 trace**。这个不一致比不发这些 header 更糟糕 —— 它变成了一个"我在伪造追踪头"的强信号。
**修复建议**:要么不发这些 header(推荐),要么从同一个 trace-id 派生两个值。
---
### Bug 3:`_submit_login_password` 发送裸 headers
```python
# register.py L456-464
response = self.session.post(
OPENAI_API_ENDPOINTS["password_verify"],
headers={
"referer": "https://auth.openai.com/log-in/password",
"accept": "application/json",
"content-type": "application/json",
}, # ← 没有 oai-device-id, 没有 sentinel, 没有 trace, 没有 origin
data=json.dumps({"password": self.password}),
)
```
**问题**:对比 `_submit_auth_start`(提交邮箱阶段),它会注入 `openai-sentinel-token`。但 `_submit_login_password`(提交密码阶段)**完全没有 sentinel**,也没有 `oai-device-id`。这造成了同一会话中两个连续请求之间的 header 风格突变。
**风险**:这正是原始分析文档说的"同一会话像多个不同浏览器"的问题。
**修复建议**:用 `_build_oauth_json_headers` 统一构建 headers,至少加 `origin` 和 `oai-device-id`。
---
## ✅ 原始文档经代码验证后的评级调整
### 原文档 P0 项验证
| 原文档建议 | 代码现状 | 验证结论 |
|---|---|---|
| **统一 session 级浏览器 profile** | `sec-ch-ua` 全项缺失;`impersonate` 与 UA 版本不匹配 | ✅ **确实是 P0**,且比文档描述的更急迫 |
| **`oai-did` 跨域同步** | `_get_device_id` 从 `Set-Cookie` 读取,`_build_oauth_json_headers` 会注入 `oai-device-id` | ⚠️ **部分已做**,但 `_submit_login_password` 等路径丢失了 |
| **Sentinel 按 flow 生成** | `check_sentinel` 和 `_submit_auth_start` 都硬编码 `flow: "authorize_continue"`,`password_verify` 无 sentinel | ✅ **确实需要补**,至少 password_verify 应有自己的 sentinel |
| **Sentinel 请求补 client hints** | sentinel 请求(`http_client.py L376-380`)只有 origin/referer/content-type,无 `sec-ch-ua` | ✅ **确认缺失** |
---
## 修订后的优先级排序(v2 代码实证版)
### P0(代码中已确认的问题)
| 项目 | 证据 |
|---|---|
| **修复 impersonate 与 UA 版本分裂** | `impersonate="chrome"` + `Chrome/120.0.0.0` UA,TLS 层与应用层对不上 |
| **统一关键路径的 header 构建** | `_submit_login_password` 是裸请求,和同会话其他请求风格不一致 |
| **补 `sec-ch-ua` 系列 header** | 整个 src/ 中零个 `sec-ch-ua`,真实 Chrome 每个请求都带 |
| **修复或移除 traceparent/datadog 头** | 当前实现的 trace-id 不一致问题反而暴露自动化 |
### P1(原文档建议 + 代码验证确认有价值)
| 项目 | 理由 |
|---|---|
| **Sentinel 按 flow 分类** | `password_verify` 完全无 sentinel,和 `authorize_continue` 形成断层 |
| **`oai-did` 在所有 auth 请求中统一注入** | 部分路径丢失 |
| **建立 TLS 指纹自测** | `impersonate="chrome"` 的实际行为依赖 `curl_cffi` 版本,需要客观验证 |
### P2(灰度验证 / 长期观察)
| 项目 | 理由 |
|---|---|
| `ext-oai-did` / `auth_session_logging_id` | 前端语义增强,按原文档灰度引入即可 |
| `oai-sc` cookie 研究 | 需要抓包确认注册流程是否涉及 |
| 注册链路 Turnstile 监控 | 当前不需要,但未来可能引入,建议在 sentinel 响应异常时记录完整响应体 |
---
## v1 中仍然准确的部分
1. **"一致性 > 随机性"** — 核心判断正确,代码中 Bug 1-3 都是一致性问题
2. **Cookie 属性关注** — `curl_cffi` 自动处理 `Set-Cookie` 属性,但值得确认无手动覆盖
3. **网络环境是指纹的一部分** — datacenter IP + `curl_cffi` 的 TLS 即使匹配也不够
4. **请求时序模拟** — 虽然 `oai-echo-logs` 不适用于 auth 链路,但步骤间延迟仍是好建议
5. **不堆随机** — 代码实证再次证明,不一致远比缺少更危险
---
## 最终建议(v2)
> [!IMPORTANT]
> **最大的威胁不是"缺什么 header",而是已经发的 header 自相矛盾。** 你的注册链路能跑通,说明 PoW + oai-did 这条路线是可行的。现在最值得投入的是修复 Bug 1-3 这种**自我暴露**的问题,而不是追加更多 header。
**建议落地顺序**:
1. 修 impersonate/UA 版本对齐(10 分钟)
2. 统一 `_submit_login_password` 的 header 构建(30 分钟)
3. 修复或移除 traceparent/datadog 头(15 分钟)
4. 补 `sec-ch-ua` 系列,绑定到 session profile(1-2 小时)
5. 后续按 P1/P2 灰度推进
> 关于 headless browser 兜底:v1 的建议仍成立,但紧迫度降低。当前注册链路能跑通,先把 HTTP-only 的一致性全面修复,headless 作为长期保险即可。