From 1468b7cd0677e47c35aa1c44b9d9f25ebdeb1be5 Mon Sep 17 00:00:00 2001 From: Ilya Date: Tue, 9 Jun 2026 15:48:55 +0300 Subject: [PATCH 1/3] feat(lab1): add PR template --- .github/PULL_REQUEST_TEMPLATE.md | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..0c908e123 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,51 @@ +# Goal + +Briefly describe what this PR delivers. + +# Changes + +- Added: +- Modified: +- Removed: + +# Testing + +Commands used: + +```bash +# Example: +docker ps +curl http://127.0.0.1:3000 +``` + +Observed results: + +```text +# Paste relevant output here +``` + +# Artifacts & Screenshots + +- Link to submission file(s) +- Screenshots (if applicable) + +## Checklist + +- [ ] Title is clear (`feat(labN): `) +- [ ] No secrets/large temp files committed +- [ ] Submission file at `submissions/labN.md` exists# Goal + +Describe what this PR delivers. + +# Changes + +- Added: +- Modified: +- Removed: + +# Testing + +Commands executed: + +```bash +# commands here From 328a5f757a6661f97ef8b475f5e19e84aee458cf Mon Sep 17 00:00:00 2001 From: Ilya Date: Tue, 9 Jun 2026 16:10:48 +0300 Subject: [PATCH 2/3] feat(lab1): juice shop deploy + PR template + triage report --- submissions/lab1.md | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 submissions/lab1.md diff --git a/submissions/lab1.md b/submissions/lab1.md new file mode 100644 index 000000000..0b7c62326 --- /dev/null +++ b/submissions/lab1.md @@ -0,0 +1,102 @@ +# Lab 1 — Submission + +## Triage Report: OWASP Juice Shop + +### Scope & Asset +- Asset: OWASP Juice Shop (local lab instance) +- Image: `bkimminich/juice-shop:v20.0.0` +- Image digest: +- Host OS: +- Docker version: <29.2.1> + +### Deployment Details +- Run command used: `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v20.0.0` +- Access URL: http://127.0.0.1:3000 +- Network exposure: 127.0.0.1 only? [x] Yes [ ] No (explain if No) +- Container restart policy: + +### Health Check +- HTTP code on `/`: +- API check: {"status":"success","data":[{"id":1,"name":"Apple Juice (1000ml)","description":"The all-time classic.","price":1.99,"deluxePrice":0.99,"image":"apple_juice.jpg","createdAt":"2026-06-09T10:48:09.331Z"% + +- Container uptime: + +### Initial Surface Snapshot (from browser exploration) +- Login/Registration visible: [x] Yes [ ] No — notes: <...> +- Product listing/search present: [x] Yes [ ] No — notes: <...> +- Admin or account area discoverable: [x] Yes [ ] No — notes: <...> +- Client-side errors in DevTools console: [x] Yes [ ] No — notes: < +:3000/rest/user/login:1 + Failed to load resource: the server responded with a status of 401 (Unauthorized) +:3000/rest/user/login:1 + Failed to load resource: the server responded with a status of 401 (Unauthorized) +:3000/rest/user/login:1 + Failed to load resource: the server responded with a status of 401 (Unauthorized)> +- Pre-populated local storage / cookies: cookieconsent_status dismiss 127.0.0.1 / 2027-06-09T10:50:23.000Z 27 Medium +language ru_RU 127.0.0.1 / 2027-06-09T10:52:06.000Z 13 Medium +welcomebanner_status dismiss 127.0.0.1 / 2027-06-09T10:50:16.000Z 27 Medium + +### Security Headers (Quick Look) +- Run: curl -I http://127.0.0.1:3000 2>&1 | head -20. Paste output: + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 9903 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +Feature-Policy: payment 'self' +X-Recruiting: /#/jobs +Accept-Ranges: bytes +Cache-Control: public, max-age=0 +Last-Modified: Tue, 09 Jun 2026 10:48:09 GMT +ETag: W/"26af-19eabff34bc" +Content-Type: text/html; charset=UTF-8 +Content-Length: 9903 +Vary: Accept-Encoding +Date: Tue, 09 Jun 2026 11:27:33 GMT +Connection: keep-alive +Keep-Alive: timeout=5 + +Which of these are MISSING? (cross-reference Lecture 1 OWASP Top 10:2025 — A06) + + - [x] Content-Security-Policy + - [x] Strict-Transport-Security + - [] X-Content-Type-Options: nosniff + - [] X-Frame-Options + +### Top 3 Risks Observed + +1. Missing Content Security Policy + +The application does not send a Content-Security-Policy header. Without CSP, the browser has fewer restrictions on loading and executing scripts, which can increase the impact of Cross-Site Scripting (XSS) vulnerabilities if they are discovered. + +OWASP Top 10:2025 A05 Security Misconfiguration + +2. Missing Strict-Transport-Security + +The Strict-Transport-Security header is not present. HSTS helps ensure that browsers always use HTTPS connections and prevents downgrade attacks. Although this lab runs locally, missing HSTS would be a security concern in a production environment. + +OWASP Top 10:2025 A05 Security Misconfiguration + +3. Publicly Accessible API Endpoints + +Several API endpoints, such as product listings and reviews, are accessible without authentication. While this may be intended for application functionality, publicly exposed endpoints increase the attack surface and provide information that could be useful during reconnaissance. + +OWASP Top 10:2025 A01 Broken Access Control + +## PR Template Setup + +- File: `.github/PULL_REQUEST_TEMPLATE.md` +- Sections included: Goal / Changes / Testing / Artifacts & Screenshots +- Checklist items: + - Title is clear (`feat(labN): `) + - No secrets/large temp files committed + - Submission file at `submissions/labN.md` exists +- Auto-fill verified: [x] Yes + +## GitHub Community + +I starred the course repository and the simple-container-com/api project. I also followed the professor, teaching assistants, and several classmates. + +Starring repositories helps increase project visibility, supports maintainers, and allows developers to bookmark useful projects for future reference. Following other developers helps discover new projects, stay informed about their work, and build professional connections that can be useful for collaboration and career growth. From ca1fba2f1e171184f0afbadec78122db97a291ef Mon Sep 17 00:00:00 2001 From: Ilya Date: Wed, 10 Jun 2026 13:03:44 +0300 Subject: [PATCH 3/3] feat(lab2): Threagile threat model + secure variant + auth flow --- labs/lab2/threagile-model-secure.yaml | 374 ++++++++++++++++++++++++++ submissions/lab2.md | 80 ++++++ 2 files changed, 454 insertions(+) create mode 100644 labs/lab2/threagile-model-secure.yaml create mode 100644 submissions/lab2.md diff --git a/labs/lab2/threagile-model-secure.yaml b/labs/lab2/threagile-model-secure.yaml new file mode 100644 index 000000000..7e58b956c --- /dev/null +++ b/labs/lab2/threagile-model-secure.yaml @@ -0,0 +1,374 @@ +threagile_version: 1.0.0 + +title: OWASP Juice Shop — Local Lab Threat Model +date: 2025-09-18 + +author: + name: Ilya Pushkarev + homepage: https://example.edu + +management_summary_comment: > + Threat model for a local OWASP Juice Shop setup. Users access the app + either directly via HTTP on port 3000 or through an optional reverse proxy that + terminates TLS and adds security headers. The app runs in a container + and writes data to a host-mounted volume (for database, uploads, logs). + Optional outbound notifications (e.g., a challenge-solution WebHook) can be configured for integrations. + +business_criticality: important # archive, operational, important, critical, mission-critical + +business_overview: + description: > + Training environment for DevSecOps. This model covers a deliberately vulnerable + web application (OWASP Juice Shop) running locally in a Docker container. The focus is on a minimal architecture, STRIDE threat analysis, and actionable mitigations for the identified risks. + + images: + # - dfd.png: Data Flow Diagram (if exported from the tool) + +technical_overview: + description: > + A user’s web browser connects to the Juice Shop application (Node.js/Express server) either directly on **localhost:3000** (HTTP) or via a **reverse proxy** on ports 80/443 (with HTTPS). The Juice Shop server may issue outbound requests to external services (e.g., a configured **WebHook** for solved challenge notifications). All application data (the SQLite database, file uploads, logs) is stored on the host’s filesystem via a mounted volume. Key trust boundaries include the **Internet** (user & external services) → **Host** (local machine/VM) → **Container Network** (isolated app container). + images: [] + +questions: + Do you expose port 3000 beyond localhost?: "" + Do you use a reverse proxy with TLS and security headers?: "" + Are any outbound integrations (webhooks) configured?: "" + Is any sensitive data stored in logs or files?: "" + +abuse_cases: + Credential Stuffing / Brute Force: > + Attackers attempt repeated login attempts to guess credentials or exhaust system resources. + Stored XSS via Product Reviews: > + Malicious scripts are inserted into product reviews, getting stored and executed in other users’ browsers. + SSRF via Outbound Requests: > + Server-side requests (e.g. profile image URL fetch or WebHook callback) are abused to access internal network resources. + +security_requirements: + TLS in transit: Enforce HTTPS for user traffic via a TLS-terminating reverse proxy with strong ciphers and certificate management. + AuthZ on sensitive routes: Implement strict server-side authorization checks (role/permission) on admin or sensitive functionalities. + Rate limiting & lockouts: Apply rate limiting and account lockout policies to mitigate brute-force and automated attacks on authentication and expensive operations. + Secure headers: Add security headers (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, etc.) at the proxy or app to mitigate client-side attacks. + Secrets management: Protect secret keys and credentials (JWT signing keys, OAuth client secrets) – keep them out of code repos and avoid logging them. + +tags_available: + # Relevant technologies and environment tags + - docker + - nodejs + # Data and asset tags + - pii + - auth + - tokens + - logs + - public + - actor + - user + - optional + - proxy + - app + - storage + - volume + - saas + - webhook + # Communication tags + - primary + - direct + - egress + +# ========================= +# DATA ASSETS +# ========================= +data_assets: + + User Accounts: + id: user-accounts + description: "User profile data, credential hashes, emails." + usage: business + tags: ["pii", "auth"] + origin: user-supplied + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: > + Contains personal identifiers and authentication data. High confidentiality is required to protect user privacy, and integrity is critical to prevent account takeovers. + + Orders: + id: orders + description: "Order history, addresses, and payment metadata (no raw card numbers)." + usage: business + tags: ["pii"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: important + availability: important + justification_cia_rating: > + Contains users’ personal data and business transaction records. Integrity and confidentiality are important to prevent fraud or privacy breaches. + + Product Catalog: + id: product-catalog + description: "Product information (names, descriptions, prices) available to all users." + usage: business + tags: ["public"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: public + integrity: important + availability: important + justification_cia_rating: > + Product data is intended to be public, but its integrity is important (to avoid defacement or price manipulation that could mislead users). + + Tokens & Sessions: + id: tokens-sessions + description: "Session identifiers, JWTs for authenticated sessions, CSRF tokens." + usage: business + tags: ["auth", "tokens"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: important + availability: important + justification_cia_rating: > + If session tokens are compromised, attackers can hijack user sessions. They must be kept confidential and intact; availability is less critical (tokens can be reissued). + + Logs: + id: logs + description: "Application and access logs (may inadvertently contain PII or secrets)." + usage: devops + tags: ["logs"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: > + Logs are for internal use (troubleshooting, monitoring). They should not be exposed publicly, and sensitive data should be sanitized to protect confidentiality. + +# ========================= +# TECHNICAL ASSETS +# ========================= +technical_assets: + + User Browser: + id: user-browser + description: "End-user web browser (client)." + type: external-entity + usage: business + used_as_client_by_human: true + out_of_scope: false + justification_out_of_scope: + size: system + technology: browser + tags: ["actor", "user"] + internet: true + machine: virtual + encryption: none + owner: External User + confidentiality: public + integrity: operational + availability: operational + justification_cia_rating: "Client controlled by end user (potentially an attacker)." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + To Reverse Proxy (preferred): + target: reverse-proxy + description: "User browser to reverse proxy (HTTPS on 443)." + protocol: https + authentication: session-id + authorization: enduser-identity-propagation + tags: ["primary"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - tokens-sessions + data_assets_received: + - product-catalog + + + Reverse Proxy: + id: reverse-proxy + description: "Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: application + technology: reverse-proxy + tags: ["optional", "proxy"] + internet: false + machine: virtual + encryption: transparent + owner: Lab Owner + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: "Not exposed to internet directly; improves security of inbound traffic." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: + - product-catalog + - tokens-sessions + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + To App: + target: juice-shop + description: "Proxy forwarding to app (HTTPS internally)." + protocol: https + authentication: credentials + authorization: technical-user + tags: [] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - tokens-sessions + data_assets_received: + - product-catalog + + Juice Shop Application: + id: juice-shop + description: "OWASP Juice Shop server (Node.js/Express, v19.0.0)." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: application + technology: web-server + tags: ["app", "nodejs"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: "In-scope web application (contains all business logic and vulnerabilities by design)." + multi_tenant: false + redundant: false + custom_developed_parts: true + data_assets_processed: + - user-accounts + - orders + - product-catalog + - tokens-sessions + data_assets_stored: + - logs + data_formats_accepted: + - json + communication_links: + + + Persistent Storage: + id: persistent-storage + description: "Host-mounted volume for database, file uploads, and logs." + type: datastore + usage: devops + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: component + technology: file-server + tags: ["storage", "volume"] + internet: false + machine: virtual + encryption: transparent + owner: Lab Owner + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: "Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs)." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: + - logs + - user-accounts + - orders + - product-catalog + data_formats_accepted: + - file + communication_links: {} + + +# ========================= +# TRUST BOUNDARIES +# ========================= +trust_boundaries: + + Internet: + id: internet + description: "Untrusted public network (Internet)." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - user-browser + trust_boundaries_nested: + - host + + Host: + id: host + description: "Local host machine / VM running the Docker environment." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - reverse-proxy + - persistent-storage + trust_boundaries_nested: + - container-network + + Container Network: + id: container-network + description: "Docker container network (isolated internal network for containers)." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - juice-shop + trust_boundaries_nested: [] + +# ========================= +# SHARED RUNTIMES +# ========================= +shared_runtimes: + + Docker Host: + id: docker-host + description: "Docker Engine and default bridge network on the host." + tags: ["docker"] + technical_assets_running: + - juice-shop + # If the reverse proxy is containerized, include it: + # - reverse-proxy + +# ========================= +# INDIVIDUAL RISK CATEGORIES (optional) +# ========================= +individual_risk_categories: {} + +# ========================= +# RISK TRACKING (optional) +# ========================= +risk_tracking: {} + +# (Optional diagram layout tweaks can be added here) +#diagram_tweak_edge_layout: spline +#diagram_tweak_layout_left_to_right: true \ No newline at end of file diff --git a/submissions/lab2.md b/submissions/lab2.md new file mode 100644 index 000000000..92987f42b --- /dev/null +++ b/submissions/lab2.md @@ -0,0 +1,80 @@ +### Task 1: Baseline Threat Model + +### Risk count by severity + +| Severity | Count | +| -------- | ----- | +| Critical | 0 | +| High | 0 | +| Elevated | 4 | +| Medium | 14 | +| Low | 5 | +| Total | 23 | + +### Top 5 risks (paste from jq output) + +1. cross-site-scripting — Cross-Site Scripting (XSS) risk at Juice Shop Application; severity elevated; affecting juice-shop + +2. missing-authentication — Missing Authentication covering communication link To App from Reverse Proxy to Juice Shop Application; severity elevated; affecting juice-shop + +3. unencrypted-communication — Unencrypted Communication named Direct to App (no proxy) between User Browser and Juice Shop Application transferring authentication data (like credentials, token, session-id, etc.); severity elevated; affecting user-browser + +4. unencrypted-communication — Unencrypted Communication named To App between Reverse Proxy and Juice Shop Application; severity elevated; affecting reverse-proxy + +5. unnecessary-technical-asset — Unnecessary Technical Asset named Persistent Storage; severity low; affecting persistent-storage + +### STRIDE mapping (Lecture 2 slide 7) + +For each top-5 risk, name the STRIDE letter(s) it primarily violates: + +* Risk 1: T — Cross-Site Scripting allows attackers to inject and manipulate content executed in the victim's browser, which is primarily a Tampering issue. + +* Risk 2: S — Missing authentication on the proxy-to-app link could allow unauthorized systems or users to impersonate trusted components, making it a Spoofing risk. + +* Risk 3: I — Unencrypted communication between the browser and the app may expose credentials and session tokens to interception, which is an Information Disclosure issue. + +* Risk 4: I — Unencrypted communication between the reverse proxy and the application can leak internal traffic if the network is compromised, also an Information Disclosure risk. + +* Risk 5: I — An unnecessary technical asset increases the chance of exposing stored data or logs, which primarily relates to Information Disclosure. + +### Trust boundary observation + +One important arrow crossing a trust boundary is “Direct to App (no proxy)” between User Browser and Juice Shop Application. This flow crosses from the untrusted Internet boundary into the application environment and carries authentication data such as session IDs and credentials. It is particularly attractive to an attacker because the traffic is unencrypted HTTP, making interception or manipulation possible through man-in-the-middle attacks. + + +## Task 2: Secure Variant & Diff + +### Risk count comparison + +| Severity | Baseline | Secure | Δ | +| --------- | -------: | -----: | -----: | +| Critical | 0 | 0 | 0 | +| High | 0 | 0 | 0 | +| Elevated | 4 | 1 | -3 | +| Medium | 14 | 10 | -4 | +| Low | 5 | 4 | -1 | +| **Total** | **23** | **15** | **-8** | + +### Which rules are GONE in the secure variant? + +List 3 rule IDs that fired in baseline but not in secure-variant: + +1. `missing-authentication` — fixed by changing the **Reverse Proxy → Juice Shop** communication link from `authentication: none` to `authentication: credentials` and adding authorization controls. +2. `unencrypted-communication` — fixed by removing the **Direct to App (no proxy)** HTTP connection between the browser and Juice Shop. +3. `unencrypted-communication` — fixed by changing the **Reverse Proxy → Juice Shop** communication link from `protocol: http` to `protocol: https`. + +### Which rules are STILL THERE in the secure variant? + +Threat modeling never reaches zero risk. List 2 rules that still fire and explain why your changes didn't eliminate them (2-3 sentences each). + +1. `cross-site-scripting` + + This risk remains because it originates from the application itself rather than the network architecture. The secure variant improved transport security and authentication, but it did not modify Juice Shop source code, input validation, output encoding, or browser-side protections needed to fully mitigate XSS. + +2. `unnecessary-technical-asset` + + This rule remains because the application still uses persistent storage for databases, uploads, and logs. Although storage encryption was enabled, the asset itself is still required for application functionality and therefore continues to contribute to the overall attack surface. + +### Honesty check + +No. The total number of risks dropped from 23 to 15, which is a reduction of approximately 35%. This demonstrates that relatively simple architectural hardening measures such as TLS, authentication, and removal of unnecessary communication paths can eliminate several significant risks. However, the remaining risks are largely application-level issues that require more substantial engineering effort, including secure coding practices, validation controls, and architectural redesign. \ No newline at end of file