diff --git a/labs/lab2/threagile-model-secure.yaml b/labs/lab2/threagile-model-secure.yaml new file mode 100644 index 000000000..4f45319c0 --- /dev/null +++ b/labs/lab2/threagile-model-secure.yaml @@ -0,0 +1,390 @@ +threagile_version: 1.0.0 + +title: OWASP Juice Shop — Local Lab Threat Model +date: 2025-09-18 + +author: + name: Mikhail Novikov + homepage: https://pornhub.innopolis.university + +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 + +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: [] + +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: + - docker + - nodejs + - pii + - auth + - tokens + - logs + - public + - actor + - user + - optional + - proxy + - app + - storage + - volume + - saas + - webhook + - primary + - direct + - egress + +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." + + 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." + + 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." + + 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." + + 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." + +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." + 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: https + 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." + 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). App uses parameterized queries for database access." + 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." + 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 + 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." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: + - 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." + multi_tenant: true + redundant: true + custom_developed_parts: false + data_assets_processed: + - orders + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: {} + +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: + + Docker Host: + id: docker-host + description: "Docker Engine and default bridge network on the host." + tags: ["docker"] + technical_assets_running: + - juice-shop \ No newline at end of file diff --git a/labs/lab2/threagile-model.yaml b/labs/lab2/threagile-model.yaml index 85c01a799..d8da603be 100644 --- a/labs/lab2/threagile-model.yaml +++ b/labs/lab2/threagile-model.yaml @@ -4,8 +4,8 @@ title: OWASP Juice Shop — Local Lab Threat Model date: 2025-09-18 author: - name: Student Name - homepage: https://example.edu + name: Mikhail Novikov + homepage: https://pornhub.innopolis.university management_summary_comment: > Threat model for a local OWASP Juice Shop setup. Users access the app diff --git a/submissions/e2/l20.png b/submissions/e2/l20.png new file mode 100644 index 000000000..c3b4f7eb9 Binary files /dev/null and b/submissions/e2/l20.png differ diff --git a/submissions/lab2.md b/submissions/lab2.md new file mode 100644 index 000000000..548cd153e --- /dev/null +++ b/submissions/lab2.md @@ -0,0 +1,75 @@ +# Lab 2 — Submission + +## Task 1: Baseline Threat Model + +### Threagile run + +```pwsh +docker run --rm ` +>> -v "${PWD}/labs/lab2:/app/work" ` +>> threagile/threagile:0.9.1 ` +>> -model /app/work/threagile-model.yaml ` +>> -output /app/work/output ` +>> -generate-risks-excel=false ` +>> -generate-tags-excel=false +``` + +### Risk count by severity + +| Severity | Count | +|----------|---------:| +| Critical | 0 | +| High | 7 | +| Elevated | 4 | +| Medium | 14 | +| Low | 5 | +| Total | 23 | + +[risks](e2\l20.png) + +### Top 5 risks (paste from `jq` output) +1. **cross-site-scripting** — Cross-Site Scripting (XSS); severity Elevated; affecting Juice Shop Server +2. **unencrypted-communication** — Unencrypted Communication Link; severity Elevated; affecting Direct HTTP to App +3. **unencrypted-communication** — Unencrypted Communication Link; severity Elevated; affecting Forward to App +4. **missing-authentication** — Missing Authentication; severity Elevated; affecting Forward to App +5. **sql-injection** — SQL-Injection; severity Medium; affecting Juice Shop Server + +### STRIDE mapping (Lecture 2 slide 7) +For each top-5 risk, name the STRIDE letter(s) it primarily violates: +- Risk 1: **T, S** (Tampering, Spoofing) — Malicious JS payloads can alter the page content and steal active session tokens from other users. +- Risk 2: **I** (Information Disclosure) — Traffic travels in plain text over the network, allowing any MITM attacker to sniff authentication cookies. +- Risk 3: **I** (Information Disclosure) — Internal traffic between the proxy and the app is unencrypted, exposing sensitive data if the host network is compromised. +- Risk 4: **E, S** (Elevation of Privilege, Spoofing) — The app blindly trusts the proxy without internal auth, allowing an attacker inside the network to forge requests. +- Risk 5: **T, I** (Tampering, Information Disclosure) — Crafted inputs can manipulate database queries to extract hidden records or modify existing data. + +### Trust boundary observation +Looking at the data-flow diagram, the **`Direct HTTP to App`** arrow crosses the trust boundary from the **Internet** directly into the **Host Machine / Container Net**. +This path is extremely attractive to an attacker because it completely bypasses the Reverse Proxy. Not only is the traffic sent over plain HTTP (exposing tokens to network sniffing), but it also evades any security headers, rate limiting, or WAF rules that the proxy might have enforced. + +## Task 2: Secure Variant & Diff + +### Risk count comparison +| Severity | Baseline | Secure | Δ | +|----------|---------:|-------:|--:| +| Critical | 0 | 0 | 0 | +| High | 7 | 7 | 0 | +| Elevated | 4 | 2 | -2 | +| Medium | 14 | 13 | -1 | +| Low | 5 | 5 | 0 | +| **Total** | 30 | 27 | -3 | + +### Which rules are GONE in the secure variant? +1. `unencrypted-communication` — fixed by changing the protocol from HTTP to HTTPS on the direct browser-to-app link. +2. `unencrypted-asset` — fixed by applying `data-with-symmetric-shared-key` encryption to the Persistent Storage volume. +3. `sql-injection` — fixed by declaring that the application uses parameterized queries in its description. + +### Which rules are STILL THERE in the secure variant? +1. `cross-site-scripting` — This is an application-level code vulnerability. Hardening the infrastructure (like adding HTTPS or encrypting the DB at rest) doesn't fix bad code that renders user input without sanitization. +2. `missing-authentication` — Juice Shop is designed to have publicly accessible endpoints (like viewing the product catalog). Threagile will continue to flag this because the architecture intentionally allows unauthenticated access to certain flows. + +### Honesty check +Did the total drop more than 50%? **No, it only dropped by 10% (from 30 to 27).** +This demonstrates the cost-benefit reality of threat modeling. Infrastructure-level hardening (flipping toggles for HTTPS and DB encryption) is a cheap, quick win. However, the vast majority of remaining risks are application-level vulnerabilities (XSS, missing auth, business logic flaws). Eliminating those requires developer time to rewrite the actual code, which is significantly more expensive and time-consuming than tweaking architectural configurations. + +## Bonus Task: Auth Flow Threat Model +ну его \ No newline at end of file