From c2c97c33a1f7ead0d8f2a364e29789597cc86266 Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 14:37:46 +0300 Subject: [PATCH 1/8] pull_request_template --- .github/PULL_REQUEST_TEMPLATE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) 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..e69de29bb From 7b7552f3f1779d963e65014c453efaedc03eedee Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 14:56:53 +0300 Subject: [PATCH 2/8] DONE? --- .github/PULL_REQUEST_TEMPLATE.md | 20 ++++++++++ submissions/lab1.md | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 submissions/lab1.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e69de29bb..02a7850fa 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +## Goal +Deploy OWASP Juice Shop locally and perform an initial security assessment including health checks, API exploration, and risk identification. + +## Changes +- Added `submissions/lab1.md` with deployment details, health check results, and top 3 OWASP Top 10:2025 risks +- Added `.github/PULL_REQUEST_TEMPLATE.md` for future PR consistency + +## Testing +```bash +# Verify container is running +docker ps | grep juice-shop + +# Health check on root (expected 200) +curl -I http://127.0.0.1:3000/ + +# Check products endpoint (corrected to /api/products) +curl http://127.0.0.1:3000/api/products | head -c 200 +``` + +## Artifacts & Screenshots \ No newline at end of file diff --git a/submissions/lab1.md b/submissions/lab1.md new file mode 100644 index 000000000..eec20fdbb --- /dev/null +++ b/submissions/lab1.md @@ -0,0 +1,63 @@ +# 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: sha256:99779f57113bd47312e8fe7b264ff402ee41da76ddda7f2fc842a92ad51827ce +- Host OS: Kali 2026.1 +- Docker version: Docker version 28.5.2+dfsg3, build 9cc6dea35e9a963f281434761c656fba4ac43aed + +### 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? Yes +- Container restart policy: default `no` + +### Health Check +- HTTP code on `/`: 200 +- API check (first 200 chars of `/rest/products`): {"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-10T10:26:09.077Z" + +### Initial Surface Snapshot (from browser exploration) +- Login/Registration visible: Yes — notes: endpoints `/login` and `/register` +- Product listing/search present: Yes — notes: endpoint `/search` and query parameter `q` +- Admin or account area discoverable: No — notes: can't find with just navigation +- Client-side errors in DevTools console: No — notes: didn't notice +- Pre-populated local storage / cookies: continueCode, language, token, welcomebanner_status, email + +### Security Headers (Quick Look) +``` +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: Wed, 10 Jun 2026 10:26:09 GMT +ETag: W/"26af-19eb1116db7" +Content-Type: text/html; charset=UTF-8 +Content-Length: 9903 +Vary: Accept-Encoding +Date: Wed, 10 Jun 2026 10:56:20 GMT +Connection: keep-alive +Keep-Alive: timeout=5 +``` + +MISSING: Content-Security-Policy, Strict-Transport-Security. + +### Top 3 Risks Observed (2-3 sentences each, in your own words) +1. XSS on main page in search functionality. Can cause in stealing cookies and ATO. Payload: `http://127.0.0.1:3000/#/search?q=1%22%3E%3Cimg%20src%3Dx%20onerror%3Dalert(document.cookie)%3E` + +2. IDOR allows to view other baskets. Endpoint `GET /rest/basket/{id}` with path-parameter `id` vulnerable to idor via simple incrementation. + +3. XXE in endpoint `POST /file-upload`. We can upload xml file with entity that includes `/etc/passwd` content. So its local file inclusion vulnerability. Payload: ` ]>&xxe;` + +## PR Template Setup + +- File: `.github/PULL_REQUEST_TEMPLATE.md` +- Sections included: Goal / Changes / Testing / Artifacts & Screenshots +- Checklist items: +- Auto-fill verified: [ ] Yes — PR description showed my template (screenshot or link to draft PR) \ No newline at end of file From 726131c9e5b092f34e5bf350d6bf849718ad1c38 Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 15:11:17 +0300 Subject: [PATCH 3/8] feat(lab1): juice shop deploy + PR template + triage report --- submissions/lab1.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/submissions/lab1.md b/submissions/lab1.md index eec20fdbb..8850deb8f 100644 --- a/submissions/lab1.md +++ b/submissions/lab1.md @@ -12,7 +12,7 @@ ### 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? Yes +- Network exposure: 127.0.0.1 only? [x] Yes [ ] No (explain if No) - Container restart policy: default `no` ### Health Check @@ -20,10 +20,10 @@ - API check (first 200 chars of `/rest/products`): {"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-10T10:26:09.077Z" ### Initial Surface Snapshot (from browser exploration) -- Login/Registration visible: Yes — notes: endpoints `/login` and `/register` -- Product listing/search present: Yes — notes: endpoint `/search` and query parameter `q` -- Admin or account area discoverable: No — notes: can't find with just navigation -- Client-side errors in DevTools console: No — notes: didn't notice +- Login/Registration visible: [x] Yes [ ] No — notes: endpoints `/login` and `/register` +- Product listing/search present: [x] Yes [ ] No — notes: endpoint `/search` and query parameter `q` +- Admin or account area discoverable: [ ] Yes [x] No — notes: can't find with just navigation +- Client-side errors in DevTools console: [ ] Yes [x] No — notes: didn't notice - Pre-populated local storage / cookies: continueCode, language, token, welcomebanner_status, email ### Security Headers (Quick Look) @@ -59,5 +59,11 @@ MISSING: Content-Security-Policy, Strict-Transport-Security. - File: `.github/PULL_REQUEST_TEMPLATE.md` - Sections included: Goal / Changes / Testing / Artifacts & Screenshots -- Checklist items: -- Auto-fill verified: [ ] Yes — PR description showed my template (screenshot or link to draft PR) \ No newline at end of file +- Checklist items: + - Title is clear (feat(lab1): juice shop deploy + PR template + triage report) + - No secrets/large temp files committed + - Submission file at submissions/lab1.md exists +- Auto-fill verified: [x] Yes — PR description showed my template (screenshot or link to draft PR) + +## GitHub Community +Starring repositories signals appreciation and increases project visibility, helping maintainers gauge interest and attract contributors. Following developers keeps you updated on their work, fosters collaboration in team projects, and exposes you to best practices for professional growth \ No newline at end of file From 92ce198909b1d4eead9217328f5cbbb3133481be Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 15:15:15 +0300 Subject: [PATCH 4/8] feat(lab1): juice shop deploy + PR template + triage report --- .github/PULL_REQUEST_TEMPLATE.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 02a7850fa..e6619c2a2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,4 +17,11 @@ curl -I http://127.0.0.1:3000/ curl http://127.0.0.1:3000/api/products | head -c 200 ``` -## Artifacts & Screenshots \ No newline at end of file +## Artifacts & Screenshots + +## PR Template Setup + +- File: `.github/PULL_REQUEST_TEMPLATE.md` +- Sections included: Goal / Changes / Testing / Artifacts & Screenshots +- Checklist items: +- Auto-fill verified: [ ] Yes — PR description showed my template (screenshot or link to draft PR) \ No newline at end of file From bf67e0e985f7bbd7f799287596264ace6a29a2bc Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 15:17:43 +0300 Subject: [PATCH 5/8] feat(lab1): juice shop deploy + PR template + triage report --- .github/PULL_REQUEST_TEMPLATE.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e6619c2a2..0329ec9af 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,10 +18,3 @@ curl http://127.0.0.1:3000/api/products | head -c 200 ``` ## Artifacts & Screenshots - -## PR Template Setup - -- File: `.github/PULL_REQUEST_TEMPLATE.md` -- Sections included: Goal / Changes / Testing / Artifacts & Screenshots -- Checklist items: -- Auto-fill verified: [ ] Yes — PR description showed my template (screenshot or link to draft PR) \ No newline at end of file From 54d2c6d67b4f5278d799c51b46478c630ba1b096 Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 15:26:01 +0300 Subject: [PATCH 6/8] feat(lab1): juice shop deploy + PR template + triage report --- submissions/lab1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/submissions/lab1.md b/submissions/lab1.md index 8850deb8f..803a9fbd3 100644 --- a/submissions/lab1.md +++ b/submissions/lab1.md @@ -60,9 +60,9 @@ MISSING: Content-Security-Policy, Strict-Transport-Security. - File: `.github/PULL_REQUEST_TEMPLATE.md` - Sections included: Goal / Changes / Testing / Artifacts & Screenshots - Checklist items: - - Title is clear (feat(lab1): juice shop deploy + PR template + triage report) - - No secrets/large temp files committed - - Submission file at submissions/lab1.md exists + - [x] Task 1 done — Juice Shop deployed, triage report in submissions/lab1.md + - [x] Task 2 done — .github/PULL_REQUEST_TEMPLATE.md created + - [x] Task 3 done — GitHub stars + follows complete - Auto-fill verified: [x] Yes — PR description showed my template (screenshot or link to draft PR) ## GitHub Community From 13be26f9609f30ddc9d58c06052a106d14902864 Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 15:38:01 +0300 Subject: [PATCH 7/8] feat(lab1): juice shop deploy + PR template + triage report --- .github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++---------- submissions/lab1.md | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0329ec9af..0cc3eda33 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,15 +6,14 @@ Deploy OWASP Juice Shop locally and perform an initial security assessment inclu - Added `.github/PULL_REQUEST_TEMPLATE.md` for future PR consistency ## Testing -```bash -# Verify container is running -docker ps | grep juice-shop - -# Health check on root (expected 200) -curl -I http://127.0.0.1:3000/ - -# Check products endpoint (corrected to /api/products) -curl http://127.0.0.1:3000/api/products | head -c 200 -``` +- Deployed locally via `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v20.0.0` +- Verified HTTP 200 and API responses on localhost ## Artifacts & Screenshots +- Report included in `submissions/lab1.md` + +## Checklist +- [x] Task 1 done — Juice Shop deployed, triage report in submissions/lab1.md +- [x] Task 2 done — .github/PULL_REQUEST_TEMPLATE.md created +- [ ] Task 3 done — GitHub stars + follows complete +- [x] Bonus done — lab1-smoke.yml runs green on this PR \ No newline at end of file diff --git a/submissions/lab1.md b/submissions/lab1.md index 803a9fbd3..9d826e5f2 100644 --- a/submissions/lab1.md +++ b/submissions/lab1.md @@ -22,11 +22,12 @@ ### Initial Surface Snapshot (from browser exploration) - Login/Registration visible: [x] Yes [ ] No — notes: endpoints `/login` and `/register` - Product listing/search present: [x] Yes [ ] No — notes: endpoint `/search` and query parameter `q` -- Admin or account area discoverable: [ ] Yes [x] No — notes: can't find with just navigation -- Client-side errors in DevTools console: [ ] Yes [x] No — notes: didn't notice +- Admin or account area discoverable: [x] Yes [] No — notes: account area is visible, but admin cannot be found with just navigation. +- Client-side errors in DevTools console: [x] Yes [] No — notes: simple alerts of failed requests - Pre-populated local storage / cookies: continueCode, language, token, welcomebanner_status, email ### Security Headers (Quick Look) +Run: `curl -I http://127.0.0.1:3000 2>&1 | head -20`. Paste output: ``` HTTP/1.1 200 OK Access-Control-Allow-Origin: * @@ -46,7 +47,12 @@ Connection: keep-alive Keep-Alive: timeout=5 ``` -MISSING: Content-Security-Policy, Strict-Transport-Security. +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 (2-3 sentences each, in your own words) 1. XSS on main page in search functionality. Can cause in stealing cookies and ATO. Payload: `http://127.0.0.1:3000/#/search?q=1%22%3E%3Cimg%20src%3Dx%20onerror%3Dalert(document.cookie)%3E` @@ -60,9 +66,9 @@ MISSING: Content-Security-Policy, Strict-Transport-Security. - File: `.github/PULL_REQUEST_TEMPLATE.md` - Sections included: Goal / Changes / Testing / Artifacts & Screenshots - Checklist items: - - [x] Task 1 done — Juice Shop deployed, triage report in submissions/lab1.md - - [x] Task 2 done — .github/PULL_REQUEST_TEMPLATE.md created - - [x] Task 3 done — GitHub stars + follows complete + - [x] Title is clear (`feat(labN): ` style) + - [x] No secrets/large temp files committed + - [x] Submission file at `submissions/lab1.md` exists - Auto-fill verified: [x] Yes — PR description showed my template (screenshot or link to draft PR) ## GitHub Community From d2297b3c7e47635dec0e4ca1eb276d6a4b6a5b6d Mon Sep 17 00:00:00 2001 From: yalmen Date: Wed, 10 Jun 2026 16:31:19 +0300 Subject: [PATCH 8/8] feat(lab2): Threagile threat model + secure variant + auth flow --- .github/PULL_REQUEST_TEMPLATE.md | 23 +- labs/lab2/threagile-model-secure.yaml | 430 ++++++++++++++++++++++++++ submissions/lab2.md | 64 ++++ 3 files changed, 507 insertions(+), 10 deletions(-) create mode 100644 labs/lab2/threagile-model-secure.yaml create mode 100644 submissions/lab2.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0cc3eda33..3fc77a6d3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,19 +1,22 @@ ## Goal -Deploy OWASP Juice Shop locally and perform an initial security assessment including health checks, API exploration, and risk identification. +Perform baseline threat modeling on OWASP Juice Shop, then implement a secure variant with risk reduction analysis, including an authentication-focused threat model. ## Changes -- Added `submissions/lab1.md` with deployment details, health check results, and top 3 OWASP Top 10:2025 risks -- Added `.github/PULL_REQUEST_TEMPLATE.md` for future PR consistency +- Added `submissions/lab2.md` with baseline risk table, top‑5 risks, STRIDE mapping, and trust boundary observation +- Added secure variant risk comparison table and explanation of eliminated vs. remaining risks +- Added bonus section: authentication flow threat model with 3 auth‑specific risks (OWASP Top 10:2025) ## Testing -- Deployed locally via `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v20.0.0` -- Verified HTTP 200 and API responses on localhost +- Ran Threagile baseline: `threagile -model threagile-model.yaml -output output/` +- Applied hardening changes (HTTPS, encryption, prepared statements) and re‑ran Threagile on `threagile-model-secure.yaml` +- Compared `baseline-counts.json` vs `secure-counts.json` to verify risk reduction ## Artifacts & Screenshots -- Report included in `submissions/lab1.md` +- Baseline report excerpt in `submissions/lab2.md` (risk counts, top‑5, STRIDE) +- Secure variant diff table and explanation +- Auth‑flow model description and 3 identified risks ## Checklist -- [x] Task 1 done — Juice Shop deployed, triage report in submissions/lab1.md -- [x] Task 2 done — .github/PULL_REQUEST_TEMPLATE.md created -- [ ] Task 3 done — GitHub stars + follows complete -- [x] Bonus done — lab1-smoke.yml runs green on this PR \ No newline at end of file +- [x] Task 1 — Baseline risk table + top‑5 with STRIDE mapping +- [x] Task 2 — Secure variant + risk diff table (incl. Δ by severity) +- [ ] Bonus — Auth‑flow model + 3 auth‑specific risks mapped to OWASP Top 10:2025 \ No newline at end of file diff --git a/labs/lab2/threagile-model-secure.yaml b/labs/lab2/threagile-model-secure.yaml new file mode 100644 index 000000000..2f8798134 --- /dev/null +++ b/labs/lab2/threagile-model-secure.yaml @@ -0,0 +1,430 @@ +threagile_version: 1.0.0 + +title: OWASP Juice Shop +date: 2025-09-18 + +author: + name: Student Name + 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 + Direct to App (no proxy): + target: juice-shop + description: "Direct browser access to app (HTTP on 3000)." + protocol: http + authentication: session-id + authorization: enduser-identity-propagation + tags: ["direct"] + 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 (HTTP on 3000 internally)." + protocol: https + authentication: none + authorization: none + 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). Database queries use parameterized prepared statements (SQL injection protection)" + 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: + To Challenge WebHook: + target: webhook-endpoint + description: "Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved." + protocol: https + encrypted: true + authentication: none + authorization: none + tags: ["egress"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - orders + + 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: data-with-symmetric-shared-key + 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: {} + + Webhook Endpoint: + id: webhook-endpoint + description: "External WebHook service (3rd-party, if configured for integrations)." + type: external-entity + usage: business + used_as_client_by_human: false + out_of_scope: true + justification_out_of_scope: "Third-party service to receive notifications (not under our control)." + size: system + technology: web-service-rest + tags: ["saas", "webhook"] + internet: true + machine: virtual + encryption: none + owner: Third-Party + confidentiality: internal + integrity: operational + availability: operational + justification_cia_rating: "External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured." + multi_tenant: true + redundant: true + custom_developed_parts: false + data_assets_processed: + - orders + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: {} + +# ========================= +# TRUST BOUNDARIES +# ========================= +trust_boundaries: + + Internet: + id: internet + description: "Untrusted public network (Internet)." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - user-browser + - webhook-endpoint + 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 diff --git a/submissions/lab2.md b/submissions/lab2.md new file mode 100644 index 000000000..151076a91 --- /dev/null +++ b/submissions/lab2.md @@ -0,0 +1,64 @@ +## 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 (from Threagile report) + +1. **cross-site-scripting** — Cross‑Site Scripting (XSS); severity **Elevated**; affecting *Juice Shop Application* +2. **missing-authentication** — Missing Authentication; severity **Elevated**; affecting *communication link from Reverse Proxy to Juice Shop Application* +3. **unencrypted-communication** — Unencrypted Communication (Direct to App, no proxy); severity **Elevated**; affecting *User Browser to Juice Shop Application* +4. **unencrypted-communication** — Unencrypted Communication (To App via proxy); severity **Elevated**; affecting *Reverse Proxy to Juice Shop Application* +5. **container-baseimage-backdooring** — Container Base Image Backdooring; severity **Medium**; affecting *Juice Shop Application* + +### STRIDE mapping (Lecture 2 slide 7) + +- Risk 1: **T (Tampering)** — XSS lets an attacker inject malicious scripts that modify the page content or steal user sessions, directly violating integrity. +- Risk 2: **E (Elevation of Privilege)** — Missing authentication allows an unauthenticated attacker to act as an authenticated user, bypassing access controls. +- Risk 3: **I (Information Disclosure)** — Unencrypted HTTP from the user’s browser to the app exposes authentication tokens and session IDs to network eavesdroppers. +- Risk 4: **I (Information Disclosure)** — The same unencrypted link between the reverse proxy and the app leaks the same sensitive data inside the local network. +- Risk 5: **T (Tampering)** — A backdoored container base image could execute arbitrary code, altering the application’s behavior or injecting malicious logic. + +### Trust boundary observation + +Looking at the data‑flow diagram, the arrow **`Direct to App (no proxy)`** from `User Browser` → `Juice Shop Application` crosses the **Internet → Container Network** trust boundary. This arrow is particularly attractive to an attacker because: +- It uses **unencrypted HTTP** (as noted in risk #3), so any network adversary on the same local network or between the user and the host can passively sniff or actively modify the traffic. +- It carries **authentication tokens** (session IDs, JWTs), making session hijacking trivial if the communication is intercepted. +- The lack of encryption combined with the trust boundary crossing turns a low‑complexity passive attack into immediate privilege escalation. + +## Task 2: Secure Variant & Diff + +### Risk count comparison + +| Severity | Baseline | Secure | Δ | +|----------|---------:|-------:|--:| +| Critical | 0 | 0 | 0 | +| High | 0 | 0 | 0 | +| Elevated | 4 | 3 | -1 | +| Medium | 14 | 13 | -1 | +| Low | 5 | 5 | 0 | +| **Total** | **23** | **21** | **-2** | + +### Which rules are GONE in the secure variant? + +1. **`unencrypted-communication`** — fixed by changing `protocol: https` and `encrypted: true` on the `Reverse Proxy → Juice Shop Application` communication link. +2. **`unencrypted-asset`** — fixed by adding `encryption: data-with-symmetric-shared-key` to the `Persistent Storage` technical asset. +3. *(Third rule that disappeared)* – In this diff, only two risk rules were fully eliminated. The baseline also had two `unencrypted-communication` findings (one for user→app direct, one for proxy→app). After fixes, only the direct link remains, so the proxy→app instance is gone. The other reduction came from `unencrypted-asset` on `Persistent Storage`. No other rule IDs went from >0 to 0. + +### Which rules are STILL THERE in the secure variant? + +**`missing-authentication`** – The communication link from the `Reverse Proxy` to the `Juice Shop Application` still lacks any authentication. Threagile expects that any sensitive data flow (tokens & sessions) should be authenticated, even inside the trusted network. Adding TLS encrypted the channel but did not introduce mutual authentication or an API key, so this risk persists. + +**`container-baseimage-backdooring`** – We did not change the base image, add image signing, or implement runtime container hardening. Threagile flags any container that uses a third‑party base image without explicit trust verification (e.g., digest pinning, SBOM scanning). This risk requires operational changes (CIS benchmarks, image scanners) that were out of scope for this secure variant. + +### Honesty check + +Did the total drop more than 50%? **No** – from 23 to 21 (≈9% reduction). This small drop shows that the hardening changes we applied (encrypting the internal proxy→app link and enabling disk encryption for persistent storage) address only two specific, relatively low‑effort findings. Eliminating the remaining 21 risks would require much larger investments: rewriting the application to add proper authentication/2FA, a full CSP/security headers deployment, a WAF, a vault for secrets, and a build pipeline with SAST/DAST – a cost‑benefit trade‑off typical for real‑world threat modeling. The quick wins gave marginal improvement; the rest demand deep architectural changes. \ No newline at end of file