Maleckidd/CypressExample-OWASPJuiceShop

GitHub: Maleckidd/CypressExample-OWASPJuiceShop

该项目是一个使用 Cypress 对 OWASP Juice Shop 进行端到端功能测试和安全挑战自动化求解的测试套件,同时记录了向 Playwright 迁移的完整过程。

Stars: 0 | Forks: 0

# CypressExample-OWASPJuiceShop ![Cypress](https://img.shields.io/badge/Cypress-10.2.0-17202C?logo=cypress) ![JavaScript](https://img.shields.io/badge/JavaScript-ES6-F7DF1E?logo=javascript&logoColor=black) ![Pattern](https://img.shields.io/badge/pattern-Page%20Object%20Model-blue) ## 🎯 问题描述 OWASP Juice Shop 是一个故意设计成包含漏洞的电子商务应用,用于学习安全测试。我不满足于仅仅进行“正常路径”的点击操作: - 在真实、动态的 Angular 应用程序上,对典型用户旅程(注册、登录、购物车、联系)进行**完整的 E2E 覆盖**。 - **自动化挑战求解** — 通过编程方式执行攻击(XSS、XXE、IDOR、API manipulation)并验证 Juice Shop 是否确实将其标记为已解决。 - **驯化动态 UI** — 该应用程序会在每次新会话时弹出欢迎弹窗和 Cookie 横幅,如果天真地处理它们,会破坏测试。 挑战不在于“写几个测试”——而在于构建一个测试套件,该套件能够在极其动态的 UI 上干净地运行,并且能够验证攻击的**效果**,而不仅仅是确认攻击被触发。 ## 🛠️ 我的实现方法 **Page Object Model 架构。** 所有 UI 交互逻辑都位于 `POM/` 中(9 个对象:`loginPage`、`registrationPage`、`headerBar`、`products`、`orders`、`contactPage`、`complaint`、`sideNav`、`FirstVisitPopups`)。`JuiceShopTests/` 中的测试描述了测试的*内容*;而 POM 知道*如何*测试。 **挑战代码化。** Attack payload 被提取到 `fixtures/challengesPayloads.json` 以及 `xxe.xml` / `test1.xml` 文件中。测试按难度分组: | 测试套件 | 场景数 | 范围 | |-------|:---------:|-------| | `1StarChallenges.cy.js` | 16 | Score Board、Bonus Payload、Confidential Document、Error Handling、Exposed Metrics… | | `2StarsChallenges.cy.js` | 17 | 中等难度的挑战 | | `3StarsChallenges.cy.js` | 23 | 高级攻击(XXE、IDOR、API manipulation) | | `homePage.cy.js` | 8 | 基础 UI 操作 — 参考资料 | | `recurseExamples.spec .cy.js` | 2 | 使用 `cypress-recurse` 的重试模式 | **通过网络而非 UI 进行验证。** 一个关键决策:自定义命令 `cy.checkIsAchivSolvedXHR()` 通过 API 响应检查挑战状态,而不是依赖于 UI 通知。这种方式不受动画和消失的 toast 影响。 **配置与测试分离。** 环境变量保存在 fixtures(`JuiceShop-dev.json` / `JuiceShop-stag.json`)中,并通过 `--env JuiceShop_ENV` 标志进行选择,因此 URL 和凭证不会被硬编码到测试用例中。实际上,所有测试都是针对运行在 `http://localhost:3000/` 的单个本地 Juice Shop 实例进行的。 ## ⚠️ 遇到的问题 坦诚面对局限性——因为它们推动了后续的发展: - **DOM XSS 在框架级别被阻止。** 测试 `it.skip('3 - DOM XSS')` — 触发 XSS 后,会弹出一个 Cypress 无法关闭的原生 `alert()`,导致超时。挑战*确实*被解开了,但测试无法干净地完成。保留为 `skip` 状态并添加注释,而不是假装它通过了。 - **对抗欢迎和 Cookie 弹窗。** 需要一个专门的 `FirstVisitPopups.pom` 以及测试之间的手动 Cookie 保留(`Cypress.Cookies.preserveOnce`)——这种方式很脆弱且依赖于执行顺序。 - **单线程运行架构。** Cypress 在浏览器的事件循环中运行——某些攻击(那些依赖原生对话框或多个标签页的攻击)很难或根本无法自动化。 ## 🚀 结果:AI 辅助迁移至 Playwright Cypress 的局限性成为了迁移到 **[PlaywrightExample-OWASPJuiceShop][pw]** 的理由——该迁移在 AI 的协助下完成,并已完整记录在案。 **发生的变化:** | | Cypress(之前) | Playwright(之后) | |---|---|---| | 框架 | Cypress 10.2.0 | Playwright 1.58.2 | | 语言 | JavaScript (ES6) | **TypeScript**(带有类型的 POM) | | 选择器 | `cy.get('[id=email]')` | web-first **Locators** | | Page Objects | 9 个 `.pom.js` 文件 | 7 个类 + `BasePage` | | 测试数据 | `faker` | 自定义 `testDataGenerator` | | 浏览器 | Chrome | Chromium + Firefox,并行运行 | | 等待 | 显式 `wait`/重试 | 内置 auto-waiting | **迁移成果:** - ✅ **强类型代码** — 选择器和方法错误在编译时捕获,而不是在运行时。 - ✅ **Web-first 断言** — 不再需要手动管理 Cookie 或脆弱的 `wait`。 - ✅ **开箱即用的跨浏览器和并行测试**。 - ✅ **完整文档化的过程** — [`MIGRATION_GUIDE.md`][pw]、`MIGRATION_SUMMARY.md` 和 `QUICK_REFERENCE.md`,其中包含每个 POM 和模式的 1:1 映射。 ## 📦 设置 需要 [Cypress][cypress] 和一个正在运行的 [OWASP Juice Shop](https://github.com/bkimminich/juice-shop) 实例。 ``` git clone https://github.com/Maleckidd/CypressExample-OWASPJuiceShop.git cd CypressExample-OWASPJuiceShop npm i ``` **运行测试:** ``` npm run cypress:open # interactive mode (env: stag) npm run cypress:headless # headless in Chrome (env: stag) npm run cypress:open:dev # interactive mode (env: dev) ``` Juice Shop 默认运行在 `http://localhost:3000/`(即 `cypress.config.js` 中的 `baseUrl`)。 ## 🗂️ 结构 ``` CypressExample-OWASPJuiceShop/ ├── JuiceShopTests/ # test suites (challenges 1–3⭐ + homePage) ├── POM/ # Page Object Model (9 objects) ├── fixtures/ # attack payloads, env data, XML files ├── support/ # custom commands (checkIsAchivSolvedXHR) ├── plugins/ # node events config └── cypress.config.js # baseUrl, specPattern, supportFile ```
标签:CISA项目, CMS安全, Cypress, E2E测试, JavaScript, 安全测试, 攻击性安全, 数据可视化, 特征检测, 自动化攻防, 自定义脚本